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 { ExpenseCategory } from '../../../models/expense-category.model';
import { ExpenseCenter } from '../../../models/expense-center.model';
import { Expense, ExpensePaymentMethod, ExpenseStatus } from '../../../models/expense.model';
import { User } from '../../../models/user.model';
import { ExpenseService } from '../../../services/expense.service';
import { FormFieldComponent } from '../../../shared/components/form-field/form-field.component';

interface ExpenseDialogData {
  expense?: Expense | null;
  categories: ExpenseCategory[];
  expenseCenters: ExpenseCenter[];
  users: User[];
}

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

  categories: ExpenseCategory[] = [];
  expenseCenters: ExpenseCenter[] = [];
  users: User[] = [];

  readonly paymentMethodOptions = [
    { label: 'Efectivo', value: 'CASH' },
    { label: 'Transferencia', value: 'TRANSFER' },
    { label: 'Tarjeta', value: 'CARD' },
    { label: 'Credito', value: 'CREDIT' },
    { label: 'Otro', value: 'OTHER' }
  ];

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

  constructor(
    private fb: FormBuilder,
    private expenseService: ExpenseService,
    public dialogRef: MatDialogRef<ExpensePage>,
    @Inject(MAT_DIALOG_DATA) public data: ExpenseDialogData
  ) {
    this.form = this.fb.group({
      categoryId: [null, Validators.required],
      expenseCenterId: [null],
      userId: [null, Validators.required],
      amount: [null, [Validators.required, Validators.min(0.01)]],
      description: ['', [Validators.required, Validators.maxLength(250)]],
      expenseDate: ['', Validators.required],
      paymentMethod: ['CASH', Validators.required],
      status: ['PENDING', Validators.required],
      vendorName: ['', Validators.maxLength(120)],
      reference: ['', Validators.maxLength(120)],
      notes: ['', Validators.maxLength(500)]
    });
  }

  ngOnInit(): void {
    this.categories = this.data?.categories ?? [];
    this.expenseCenters = this.data?.expenseCenters ?? [];
    this.users = this.data?.users ?? [];

    const expense = this.data?.expense;
    if (expense) {
      this.isEditMode = true;
      this.form.patchValue({
        categoryId: expense.categoryId,
        expenseCenterId: expense.expenseCenterId ?? null,
        userId: expense.userId,
        amount: expense.amount,
        description: expense.description,
        expenseDate: this.toDateInput(expense.expenseDate),
        paymentMethod: expense.paymentMethod,
        status: expense.status,
        vendorName: expense.vendorName ?? '',
        reference: expense.reference ?? '',
        notes: expense.notes ?? ''
      });
      return;
    }

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

    this.form.patchValue({
      expenseDate: this.toDateInput(new Date().toISOString())
    });
  }

  get categoryOptions() {
    return this.categories.map(category => ({
      label: category.name,
      value: category.id
    }));
  }

  get expenseCenterOptions() {
    return this.expenseCenters.map(center => ({
      label: center.name,
      value: center.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();
  }

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

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

    const raw = this.form.getRawValue();
    const payload: Expense = {
      categoryId: Number(raw.categoryId),
      expenseCenterId: raw.expenseCenterId ? Number(raw.expenseCenterId) : null,
      userId: Number(raw.userId),
      amount: Number(raw.amount),
      description: raw.description,
      expenseDate: new Date(raw.expenseDate).toISOString(),
      paymentMethod: raw.paymentMethod as ExpensePaymentMethod,
      status: raw.status as ExpenseStatus,
      vendorName: raw.vendorName || null,
      reference: raw.reference || null,
      notes: raw.notes || null
    };

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

    request$.subscribe({
      next: () => {
        this.saving = false;
        this.dialogRef.close({
          saved: true,
          message: this.isEditMode ? 'Gasto actualizado correctamente.' : 'Gasto creado correctamente.'
        });
      },
      error: () => {
        this.saving = false;
        this.errorMessage = this.isEditMode
          ? 'No se pudo actualizar el gasto.'
          : 'No se pudo crear el gasto.';
      }
    });
  }

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

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