import { Component, OnInit, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { FormBuilder, FormArray, 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 { WorkflowService } from '../services/workflow.service';
import { DepartmentService } from '../../departments/services/department.service';
import { NotificationService } from '../../../core/services/notification.service';
import { AuthService } from '../../../core/services/auth.service';
import { DepartmentResponseDto } from '../../../api/models';
import {
  INPUT_LIMITS,
  noScriptValidator,
  noNullBytesValidator,
  notOnlyWhitespaceValidator,
  normalizeWhitespace,
} from '../../../shared/utils/form-validators';
import { createSubmitDebounce } from '../../../shared/utils/form-utils';

@Component({
  selector: 'app-workflow-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 Workflow' : 'Create Workflow'"
        [subtitle]="isEditMode() ? 'Update workflow configuration' : 'Define a new approval workflow'"
      >
        <button mat-button routerLink="/workflows">
          <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()">
              <div class="form-section">
                <h3>Basic Information</h3>
                <div class="form-grid">
                  <mat-form-field appearance="outline">
                    <mat-label>Workflow Name</mat-label>
                    <input matInput formControlName="name" placeholder="e.g., Resort License Workflow" [maxlength]="limits.NAME_MAX" />
                    @if (form.controls.name.hasError('required')) {
                      <mat-error>Name is required</mat-error>
                    }
                    @if (form.controls.name.hasError('minlength')) {
                      <mat-error>Minimum {{ limits.NAME_MIN }} characters required</mat-error>
                    }
                    @if (form.controls.name.hasError('maxlength')) {
                      <mat-error>Maximum {{ limits.NAME_MAX }} characters allowed</mat-error>
                    }
                    @if (form.controls.name.hasError('dangerousContent')) {
                      <mat-error>Invalid characters detected</mat-error>
                    }
                  </mat-form-field>

                  <mat-form-field appearance="outline">
                    <mat-label>Workflow Type</mat-label>
                    <mat-select formControlName="workflowType">
                      <mat-option value="NEW_LICENSE">New License</mat-option>
                      <mat-option value="RENEWAL">Renewal</mat-option>
                      <mat-option value="AMENDMENT">Amendment</mat-option>
                    </mat-select>
                  </mat-form-field>

                  <mat-form-field appearance="outline" class="full-width">
                    <mat-label>Description</mat-label>
                    <textarea matInput formControlName="description" rows="2" [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>
              </div>

              <div class="form-section">
                <div class="section-header">
                  <h3>Approval Stages</h3>
                  <button mat-button type="button" color="primary" (click)="addStage()" [disabled]="stagesArray.length >= maxStages">
                    <mat-icon>add</mat-icon>
                    Add Stage {{ stagesArray.length >= maxStages ? '(max reached)' : '' }}
                  </button>
                </div>

                <div formArrayName="stages" class="stages-list">
                  @for (stage of stagesArray.controls; track $index; let i = $index) {
                    <mat-card class="stage-card" [formGroupName]="i">
                      <div class="stage-header">
                        <span class="stage-number">Stage {{ i + 1 }}</span>
                        <button mat-icon-button type="button" (click)="removeStage(i)" [disabled]="stagesArray.length <= 1">
                          <mat-icon>delete</mat-icon>
                        </button>
                      </div>
                      <div class="stage-form">
                        <mat-form-field appearance="outline">
                          <mat-label>Stage Name</mat-label>
                          <input matInput formControlName="name" [maxlength]="limits.NAME_MAX" />
                        </mat-form-field>
                        <mat-form-field appearance="outline">
                          <mat-label>Department</mat-label>
                          <mat-select formControlName="departmentId">
                            @for (dept of departments(); track dept.id) {
                              <mat-option [value]="dept.id">{{ dept.name }}</mat-option>
                            }
                          </mat-select>
                        </mat-form-field>
                        <mat-checkbox formControlName="isRequired">Required</mat-checkbox>
                      </div>
                    </mat-card>
                  }
                </div>
              </div>

              <div class="form-actions">
                <button mat-button type="button" routerLink="/workflows">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' : 'Create' }}
                  }
                </button>
              </div>
            </form>
          }
        </mat-card-content>
      </mat-card>
    </div>
  `,
  styles: [
    `
      .form-card {
        max-width: 900px;
      }

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

      .form-section {
        margin-bottom: 32px;

        h3 {
          margin: 0 0 16px;
          font-size: 1.125rem;
          font-weight: 500;
        }
      }

      .section-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16px;

        h3 {
          margin: 0;
        }
      }

      .form-grid {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 16px;
      }

      .full-width {
        grid-column: 1 / -1;
      }

      .stages-list {
        display: flex;
        flex-direction: column;
        gap: 16px;
      }

      .stage-card {
        padding: 16px;
      }

      .stage-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16px;
      }

      .stage-number {
        font-weight: 500;
        color: #1976d2;
      }

      .stage-form {
        display: grid;
        grid-template-columns: 1fr 1fr auto;
        gap: 16px;
        align-items: center;
      }

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

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

  readonly loading = signal(false);
  readonly submitting = signal(false);
  readonly isEditMode = signal(false);
  readonly departments = signal<DepartmentResponseDto[]>([]);
  private workflowId: string | null = null;

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

  /** Maximum number of approval stages allowed */
  readonly maxStages = 20;

  readonly form = this.fb.nonNullable.group({
    name: ['', [
      Validators.required,
      Validators.minLength(INPUT_LIMITS.NAME_MIN),
      Validators.maxLength(INPUT_LIMITS.NAME_MAX),
      noScriptValidator(),
      noNullBytesValidator(),
      notOnlyWhitespaceValidator(),
    ]],
    description: ['', [
      Validators.maxLength(INPUT_LIMITS.DESCRIPTION_MAX),
      noScriptValidator(),
      noNullBytesValidator(),
    ]],
    workflowType: ['NEW_LICENSE', [Validators.required]],
    stages: this.fb.array([this.createStageGroup()]),
  });

  get stagesArray(): FormArray {
    return this.form.get('stages') as FormArray;
  }

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

  private loadDepartments(): void {
    this.departmentService.getDepartments(1, 100).subscribe({
      next: (response) => {
        this.departments.set(response?.data ?? []);
      },
    });
  }

  private loadWorkflow(): void {
    if (!this.workflowId) return;

    this.loading.set(true);
    this.workflowService.getWorkflow(this.workflowId).subscribe({
      next: (workflow) => {
        this.form.patchValue({
          name: workflow.name,
          description: workflow.description || '',
          workflowType: workflow.workflowType,
        });

        this.stagesArray.clear();
        const stages = workflow.definition?.stages || [];
        stages.forEach((stage) => {
          // Find department by code to get departmentId
          const dept = this.departments().find(d =>
            d.code === stage.requiredApprovals?.[0]?.departmentCode
          );
          this.stagesArray.push(
            this.fb.group({
              id: [stage.stageId],
              name: [stage.stageName, Validators.required],
              departmentId: [dept?.id || '', Validators.required],
              order: [stage.stageOrder],
              isRequired: [stage.metadata?.['isRequired'] ?? true],
            })
          );
        });

        this.loading.set(false);
      },
      error: () => {
        this.notification.error('Failed to load workflow');
        this.router.navigate(['/workflows']);
      },
    });
  }

  private createStageGroup() {
    return this.fb.group({
      id: [''],
      name: ['', [
        Validators.required,
        Validators.minLength(INPUT_LIMITS.NAME_MIN),
        Validators.maxLength(INPUT_LIMITS.NAME_MAX),
        noScriptValidator(),
        noNullBytesValidator(),
        notOnlyWhitespaceValidator(),
      ]],
      departmentId: ['', Validators.required],
      order: [1],
      isRequired: [true],
    });
  }

  addStage(): void {
    // Prevent adding more than max stages
    if (this.stagesArray.length >= this.maxStages) {
      this.notification.warning(`Maximum ${this.maxStages} stages allowed`);
      return;
    }

    const order = this.stagesArray.length + 1;
    const group = this.createStageGroup();
    group.patchValue({ order });
    this.stagesArray.push(group);
  }

  removeStage(index: number): void {
    if (this.stagesArray.length > 1) {
      this.stagesArray.removeAt(index);
      this.updateStageOrders();
    }
  }

  private updateStageOrders(): void {
    this.stagesArray.controls.forEach((control, index) => {
      control.patchValue({ order: index + 1 });
    });
  }

  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();
      // Also mark stage controls as touched
      this.stagesArray.controls.forEach(control => {
        control.markAllAsTouched();
      });
      return;
    }

    this.submitting.set(true);
    const values = this.form.getRawValue();
    const currentUser = this.authService.currentUser();

    // Get departmentId from current user or first stage
    const departmentId = currentUser?.departmentId ||
      (values.stages[0]?.departmentId) || '';

    // Transform to backend DTO format
    const dto: any = {
      name: normalizeWhitespace(values.name),
      description: normalizeWhitespace(values.description) || undefined,
      workflowType: values.workflowType!,
      stages: values.stages.map((s, i) => {
        const department = this.departments().find(d => d.id === s.departmentId);
        return {
          stageId: s.id || `stage-${i + 1}`,
          stageName: normalizeWhitespace(s.name) || `Stage ${i + 1}`,
          stageOrder: i,  // Backend expects 0-indexed
          executionType: 'SEQUENTIAL' as const,
          requiredApprovals: [{
            departmentCode: department?.code || '',
            departmentName: department?.name || 'Unknown',
            canDelegate: false,
          }],
          completionCriteria: 'ALL' as const,
          rejectionHandling: 'FAIL_REQUEST' as const,
          metadata: {
            isRequired: s.isRequired ?? true,
          },
        };
      }),
    };

    const action$ = this.isEditMode()
      ? this.workflowService.updateWorkflow(this.workflowId!, dto)
      : this.workflowService.createWorkflow(dto);

    action$.subscribe({
      next: (result) => {
        this.notification.success(
          this.isEditMode() ? 'Workflow updated' : 'Workflow created'
        );
        this.router.navigate(['/workflows', result.id]);
      },
      error: (err) => {
        this.submitting.set(false);
        this.notification.error(err?.error?.message || 'Failed to save workflow. Please try again.');
      },
    });
  }
}
