import { CommonModule } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  ReactiveFormsModule,
  Validators
} from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';

import { Branch } from '../../../models/branch.model';
import { Client } from '../../../models/client.model';
import { Receivable, ReceivableStatus } from '../../../models/receivable.model';
import { ticket } from '../../../models/Ticket.model';
import { User } from '../../../models/user.model';
import { ReceivableService } from '../../../services/receivable.service';
import { FormFieldComponent } from '../../../shared/components/form-field/form-field.component';

interface ReceivableFormDialogData {
  receivable?: Receivable | null;
  clients: Client[];
  branches: Branch[];
  tickets: ticket[];
  users: User[];
}

@Component({
  selector: 'app-receivable-form-page',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, FormFieldComponent],
  templateUrl: './receivable-form.page.html',
  styleUrls: ['./receivable-form.page.scss']
})
export class ReceivableFormPage implements OnInit {
  form: FormGroup;
  isEditMode = false;
  saving = false;
  errorMessage = '';

  clients: Client[] = [];
  branches: Branch[] = [];
  tickets: ticket[] = [];
  users: User[] = [];

  readonly statusOptions = [
    { label: 'Pendiente', value: 'PENDING' },
    { label: 'Parcial', value: 'PARTIAL' },
    { label: 'Pagado', value: 'PAID' },
    { label: 'Vencido', value: 'OVERDUE' },
    { label: 'Cancelado', value: 'CANCELLED' }
  ];

  constructor(
    private fb: FormBuilder,
    private receivableService: ReceivableService,
    public dialogRef: MatDialogRef<ReceivableFormPage>,
    @Inject(MAT_DIALOG_DATA) public data: ReceivableFormDialogData
  ) {
    this.form = this.fb.group({
      clientId: [null, Validators.required],
      branchId: [null, Validators.required],
      ticketId: [null, Validators.required],
      createdByUserId: [null, Validators.required],
      description: ['', [Validators.required, Validators.maxLength(250)]],
      totalAmount: [null, [Validators.required, Validators.min(0.01)]],
      issueDate: ['', Validators.required],
      dueDate: ['', Validators.required],
      status: ['PENDING', Validators.required],
      reference: ['', Validators.maxLength(120)],
      notes: ['', Validators.maxLength(500)]
    });
  }

  ngOnInit(): void {
    this.clients = this.data.clients ?? [];
    this.branches = this.data.branches ?? [];
    this.tickets = this.data.tickets ?? [];
    this.users = this.data.users ?? [];

    const receivable = this.data.receivable;
    if (receivable) {
      this.isEditMode = true;
      this.form.patchValue({
        clientId: receivable.clientId,
        branchId: receivable.branchId,
        ticketId: receivable.ticketId,
        createdByUserId: receivable.createdByUserId,
        description: receivable.description,
        totalAmount: receivable.totalAmount,
        issueDate: this.toDateInput(receivable.issueDate),
        dueDate: this.toDateInput(receivable.dueDate),
        status: receivable.status,
        reference: receivable.reference ?? '',
        notes: receivable.notes ?? ''
      });
      return;
    }

    if (this.users.length === 1) {
      this.form.patchValue({ createdByUserId: this.users[0].id ?? null });
    }

    const today = this.toDateInput(new Date().toISOString());
    this.form.patchValue({
      issueDate: today,
      dueDate: today
    });
  }

  get clientOptions() {
    return this.clients.map(client => ({
      label: client.name,
      value: client.id
    }));
  }

  get branchOptions() {
    return this.branches.map(branch => ({
      label: branch.name,
      value: branch.id
    }));
  }

  get ticketOptions() {
    return this.tickets.map(ticketItem => ({
      label: ticketItem.folio || ticketItem.uuid || `Ticket #${ticketItem.id}`,
      value: ticketItem.id
    }));
  }

  get userOptions() {
    return this.users.map(user => ({
      label: user.name,
      value: user.id
    }));
  }

  getSafeControl(name: string): FormControl {
    return (this.form.get(name) as FormControl) ?? new FormControl();
  }

  hasRequiredCatalogs(): boolean {
    return this.clients.length > 0 && this.branches.length > 0 && this.tickets.length > 0 && this.users.length > 0;
  }

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

    this.saving = true;
    this.errorMessage = '';

    const raw = this.form.getRawValue();
    const payload: Receivable = {
      clientId: Number(raw.clientId),
      branchId: Number(raw.branchId),
      ticketId: Number(raw.ticketId),
      createdByUserId: Number(raw.createdByUserId),
      description: raw.description,
      totalAmount: Number(raw.totalAmount),
      issueDate: new Date(raw.issueDate).toISOString(),
      dueDate: new Date(raw.dueDate).toISOString(),
      status: raw.status as ReceivableStatus,
      reference: raw.reference || null,
      notes: raw.notes || null
    };

    const request$ = this.isEditMode && this.data.receivable?.id
      ? this.receivableService.update(this.data.receivable.id, payload)
      : this.receivableService.create(payload);

    request$.subscribe({
      next: () => {
        this.saving = false;
        this.dialogRef.close({
          saved: true,
          message: this.isEditMode
            ? 'Cuenta por cobrar actualizada correctamente.'
            : 'Cuenta por cobrar creada correctamente.'
        });
      },
      error: () => {
        this.saving = false;
        this.errorMessage = this.isEditMode
          ? 'No se pudo actualizar la cuenta por cobrar.'
          : 'No se pudo crear la cuenta por cobrar.';
      }
    });
  }

  private toDateInput(value: string): string {
    return value ? value.slice(0, 10) : '';
  }
}
