import { CommonModule } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
import { MatDialog, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';

import { Branch } from '../../../models/branch.model';
import { Client } from '../../../models/client.model';
import { ReceivablePayment } from '../../../models/receivable-payment.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 { ReceivablePaymentPage } from '../receivable-payment/receivable-payment.page';

interface ReceivableDetailDialogData {
  receivableId: number;
  clients: Client[];
  branches: Branch[];
  tickets: ticket[];
  users: User[];
}

@Component({
  selector: 'app-receivable-detail-page',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './receivable-detail.page.html',
  styleUrls: ['./receivable-detail.page.scss']
})
export class ReceivableDetailPage implements OnInit {
  receivable: Receivable | null = null;
  loading = true;
  errorMessage = '';

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

  constructor(
    private receivableService: ReceivableService,
    private dialog: MatDialog,
    public dialogRef: MatDialogRef<ReceivableDetailPage>,
    @Inject(MAT_DIALOG_DATA) public data: ReceivableDetailDialogData
  ) {}

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

  loadDetail(): void {
    this.loading = true;
    this.errorMessage = '';

    this.receivableService.getById(this.data.receivableId).subscribe({
      next: receivable => {
        this.receivable = receivable;
        this.loading = false;
      },
      error: () => {
        this.loading = false;
        this.errorMessage = 'No se pudo cargar el detalle de la cuenta.';
      }
    });
  }

  openPaymentModal(): void {
    const dialogRef = this.dialog.open(ReceivablePaymentPage, {
      width: '720px',
      data: {
        receivableId: this.data.receivableId,
        users: this.users
      }
    });

    dialogRef.afterClosed().subscribe(result => {
      if (!result?.saved) {
        return;
      }

      this.loadDetail();
      this.dialogRef.close({
        refresh: true,
        message: result.message
      });
    });
  }

  getPayments(): ReceivablePayment[] {
    if (!this.receivable) {
      return [];
    }

    return this.receivable.payments ?? this.receivable.receivablePayments ?? [];
  }

  getClientName(clientId: number): string {
    return this.clients.find(client => client.id === clientId)?.name ?? `Cliente #${clientId}`;
  }

  getBranchName(branchId: number): string {
    return this.branches.find(branch => branch.id === branchId)?.name ?? `Sucursal #${branchId}`;
  }

  getTicketLabel(ticketId: number): string {
    const ticketRecord = this.tickets.find(ticketItem => ticketItem.id === ticketId);
    return ticketRecord?.folio || ticketRecord?.uuid || `Ticket #${ticketId}`;
  }

  getUserName(userId: number): string {
    return this.users.find(user => user.id === userId)?.name ?? `Usuario #${userId}`;
  }

  getStatusLabel(status: ReceivableStatus): string {
    switch (status) {
      case 'PARTIAL':
        return 'Parcial';
      case 'PAID':
        return 'Pagado';
      case 'OVERDUE':
        return 'Vencido';
      case 'CANCELLED':
        return 'Cancelado';
      default:
        return 'Pendiente';
    }
  }

  getPaidAmount(): number {
    if (!this.receivable) {
      return 0;
    }

    return Number(
      this.receivable.paidAmount ??
      this.getPayments().reduce((sum, payment) => sum + Number(payment.amount ?? 0), 0)
    );
  }

  getBalanceAmount(): number {
    if (!this.receivable) {
      return 0;
    }

    const fallbackBalance = Number(this.receivable.totalAmount ?? 0) - this.getPaidAmount();
    return Number(this.receivable.balanceAmount ?? fallbackBalance);
  }
}
