import { Component, OnInit, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { PageHeaderComponent } from '../../../shared/components/page-header/page-header.component';
import { WebhookService } from '../services/webhook.service';
import { NotificationService } from '../../../core/services/notification.service';
import { WebhookEvent } from '../../../api/models';
import {
  INPUT_LIMITS,
  noScriptValidator,
  noNullBytesValidator,
  strictUrlValidator,
  normalizeWhitespace,
} from '../../../shared/utils/form-validators';
import { createSubmitDebounce } from '../../../shared/utils/form-utils';

@Component({
  selector: 'app-webhook-form',
  standalone: true,
  imports: [
    CommonModule,
    RouterModule,
    ReactiveFormsModule,
    MatCardModule,
    MatFormFieldModule,
    MatInputModule,
    MatSelectModule,
    MatButtonModule,
    MatIconModule,
    MatCheckboxModule,
    MatProgressSpinnerModule,
    PageHeaderComponent,
  ],
  template: `
    <div class="page-container">
      <app-page-header
        [title]="isEditMode() ? 'Edit Webhook' : 'Register Webhook'"
        [subtitle]="isEditMode() ? 'Update webhook configuration' : 'Configure a new webhook endpoint'"
      >
        <button mat-button routerLink="/webhooks">
          <mat-icon>arrow_back</mat-icon>
          Back
        </button>
      </app-page-header>

      <mat-card class="form-card">
        <mat-card-content>
          @if (loading()) {
            <div class="loading-container">
              <mat-spinner diameter="48"></mat-spinner>
            </div>
          } @else {
            <form [formGroup]="form" (ngSubmit)="onSubmit()">
              <mat-form-field appearance="outline">
                <mat-label>Webhook URL</mat-label>
                <input
                  matInput
                  formControlName="url"
                  placeholder="https://your-server.com/webhook"
                  [maxlength]="limits.URL_MAX"
                />
                @if (form.controls.url.hasError('required')) {
                  <mat-error>URL is required</mat-error>
                }
                @if (form.controls.url.hasError('httpsRequired')) {
                  <mat-error>HTTPS is required for webhook URLs</mat-error>
                }
                @if (form.controls.url.hasError('invalidUrl')) {
                  <mat-error>Enter a valid URL</mat-error>
                }
                @if (form.controls.url.hasError('dangerousUrl')) {
                  <mat-error>URL contains unsafe content</mat-error>
                }
                @if (form.controls.url.hasError('urlTooLong')) {
                  <mat-error>URL is too long (max {{ limits.URL_MAX }} characters)</mat-error>
                }
                <mat-hint>Must be a publicly accessible HTTPS endpoint</mat-hint>
              </mat-form-field>

              <mat-form-field appearance="outline">
                <mat-label>Events</mat-label>
                <mat-select formControlName="events" multiple>
                  @for (event of eventOptions; track event.value) {
                    <mat-option [value]="event.value">{{ event.label }}</mat-option>
                  }
                </mat-select>
                @if (form.controls.events.hasError('required')) {
                  <mat-error>Select at least one event</mat-error>
                }
                <mat-hint>Select the events you want to receive notifications for</mat-hint>
              </mat-form-field>

              <mat-form-field appearance="outline">
                <mat-label>Description (optional)</mat-label>
                <textarea
                  matInput
                  formControlName="description"
                  rows="2"
                  placeholder="What is this webhook used for?"
                  [maxlength]="limits.DESCRIPTION_MAX"
                ></textarea>
                @if (form.controls.description.hasError('maxlength')) {
                  <mat-error>Maximum {{ limits.DESCRIPTION_MAX }} characters allowed</mat-error>
                }
                @if (form.controls.description.hasError('dangerousContent')) {
                  <mat-error>Invalid characters detected</mat-error>
                }
                <mat-hint align="end">{{ form.controls.description.value?.length || 0 }}/{{ limits.DESCRIPTION_MAX }}</mat-hint>
              </mat-form-field>

              <div class="form-actions">
                <button mat-button type="button" routerLink="/webhooks">Cancel</button>
                <button
                  mat-raised-button
                  color="primary"
                  type="submit"
                  [disabled]="form.invalid || submitting()"
                >
                  @if (submitting()) {
                    <mat-spinner diameter="20"></mat-spinner>
                  } @else {
                    {{ isEditMode() ? 'Update' : 'Register' }}
                  }
                </button>
              </div>
            </form>
          }
        </mat-card-content>
      </mat-card>
    </div>
  `,
  styles: [
    `
      .form-card {
        max-width: 600px;
      }

      .loading-container {
        display: flex;
        justify-content: center;
        padding: 48px;
      }

      form {
        display: flex;
        flex-direction: column;
        gap: 16px;
      }

      .form-actions {
        display: flex;
        gap: 12px;
        justify-content: flex-end;
        margin-top: 16px;
        padding-top: 16px;
        border-top: 1px solid #eee;
      }
    `,
  ],
})
export class WebhookFormComponent implements OnInit {
  private readonly fb = inject(FormBuilder);
  private readonly route = inject(ActivatedRoute);
  private readonly router = inject(Router);
  private readonly webhookService = inject(WebhookService);
  private readonly notification = inject(NotificationService);

  /** Debounce handler to prevent double-click submissions */
  private readonly submitDebounce = createSubmitDebounce(500);

  readonly loading = signal(false);
  readonly submitting = signal(false);
  readonly isEditMode = signal(false);
  private webhookId: string | null = null;

  /** Input limits exposed for template binding */
  readonly limits = INPUT_LIMITS;

  readonly eventOptions: { value: WebhookEvent; label: string }[] = [
    { value: 'APPROVAL_REQUIRED', label: 'Approval Required' },
    { value: 'DOCUMENT_UPDATED', label: 'Document Updated' },
    { value: 'REQUEST_APPROVED', label: 'Request Approved' },
    { value: 'REQUEST_REJECTED', label: 'Request Rejected' },
    { value: 'CHANGES_REQUESTED', label: 'Changes Requested' },
    { value: 'LICENSE_MINTED', label: 'License Minted' },
    { value: 'LICENSE_REVOKED', label: 'License Revoked' },
  ];

  readonly form = this.fb.nonNullable.group({
    url: ['', [
      Validators.required,
      strictUrlValidator(true), // Require HTTPS for webhooks
    ]],
    events: [[] as WebhookEvent[], [Validators.required]],
    description: ['', [
      Validators.maxLength(INPUT_LIMITS.DESCRIPTION_MAX),
      noScriptValidator(),
      noNullBytesValidator(),
    ]],
  });

  ngOnInit(): void {
    this.webhookId = this.route.snapshot.paramMap.get('id');
    if (this.webhookId) {
      this.isEditMode.set(true);
      this.loadWebhook();
    }
  }

  private loadWebhook(): void {
    if (!this.webhookId) return;

    this.loading.set(true);
    this.webhookService.getWebhook(this.webhookId).subscribe({
      next: (webhook) => {
        this.form.patchValue({
          url: webhook.url,
          events: webhook.events,
          description: webhook.description || '',
        });
        this.loading.set(false);
      },
      error: () => {
        this.notification.error('Failed to load webhook');
        this.router.navigate(['/webhooks']);
      },
    });
  }

  onSubmit(): void {
    // Debounce to prevent double-click submissions
    this.submitDebounce(() => this.performSubmit());
  }

  private performSubmit(): void {
    // Prevent submission if already in progress
    if (this.submitting()) {
      return;
    }

    if (this.form.invalid) {
      this.form.markAllAsTouched();
      return;
    }

    this.submitting.set(true);
    const rawValues = this.form.getRawValue();

    // Normalize and sanitize values
    const values = {
      url: rawValues.url.trim(),
      events: rawValues.events,
      description: normalizeWhitespace(rawValues.description),
    };

    const action$ = this.isEditMode()
      ? this.webhookService.updateWebhook(this.webhookId!, values)
      : this.webhookService.createWebhook(values);

    action$.subscribe({
      next: () => {
        this.notification.success(
          this.isEditMode() ? 'Webhook updated' : 'Webhook registered'
        );
        this.router.navigate(['/webhooks']);
      },
      error: (err) => {
        this.submitting.set(false);
        this.notification.error(err?.error?.message || 'Failed to save webhook. Please try again.');
      },
    });
  }
}
