/**
 * AccountPayable Entity - Cuentas por Pagar
 *
 * Registro de obligaciones con proveedores y subcontratistas.
 *
 * @module Finance
 */

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  ManyToOne,
  OneToMany,
  JoinColumn,
  Index,
} from 'typeorm';
import { APPayment } from './ap-payment.entity';

export type APStatus = 'pending' | 'partial' | 'paid' | 'overdue' | 'cancelled' | 'disputed';
export type APDocumentType = 'invoice' | 'credit_note' | 'debit_note' | 'advance' | 'retention';

@Entity('accounts_payable', { schema: 'finance' })
@Index(['tenantId', 'supplierId'])
@Index(['tenantId', 'status'])
@Index(['tenantId', 'dueDate'])
@Index(['tenantId', 'projectId'])
export class AccountPayable {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ name: 'tenant_id', type: 'uuid' })
  @Index()
  tenantId!: string;

  // Número de documento
  @Column({ name: 'document_number', length: 100 })
  documentNumber!: string;

  @Column({
    name: 'document_type',
    type: 'enum',
    enum: ['invoice', 'credit_note', 'debit_note', 'advance', 'retention'],
    enumName: 'ap_document_type',
    default: 'invoice',
  })
  documentType!: APDocumentType;

  // Proveedor
  @Column({ name: 'supplier_id', type: 'uuid' })
  supplierId!: string;

  @Column({ name: 'supplier_name', length: 255 })
  supplierName!: string;

  @Column({ name: 'supplier_rfc', length: 13, nullable: true })
  supplierRfc?: string;

  // Estado
  @Column({
    type: 'enum',
    enum: ['pending', 'partial', 'paid', 'overdue', 'cancelled', 'disputed'],
    enumName: 'ap_status',
    default: 'pending',
  })
  status!: APStatus;

  // Fechas
  @Column({ name: 'invoice_date', type: 'date' })
  invoiceDate!: Date;

  @Column({ name: 'received_date', type: 'date', nullable: true })
  receivedDate?: Date;

  @Column({ name: 'due_date', type: 'date' })
  dueDate!: Date;

  @Column({ name: 'payment_date', type: 'date', nullable: true })
  paymentDate?: Date;

  // Montos
  @Column({
    type: 'decimal',
    precision: 18,
    scale: 2,
  })
  subtotal!: number;

  @Column({
    name: 'tax_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    default: 0,
  })
  taxAmount!: number;

  @Column({
    name: 'retention_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    default: 0,
  })
  retentionAmount!: number;

  @Column({
    name: 'total_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
  })
  totalAmount!: number;

  @Column({
    name: 'paid_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    default: 0,
  })
  paidAmount!: number;

  @Column({
    name: 'balance',
    type: 'decimal',
    precision: 18,
    scale: 2,
  })
  balance!: number;

  // Moneda
  @Column({ length: 3, default: 'MXN' })
  currency!: string;

  @Column({
    name: 'exchange_rate',
    type: 'decimal',
    precision: 12,
    scale: 6,
    default: 1,
  })
  exchangeRate!: number;

  // Origen (orden de compra, contrato)
  @Column({ name: 'source_module', length: 50, nullable: true })
  sourceModule?: string;

  @Column({ name: 'source_id', type: 'uuid', nullable: true })
  sourceId?: string;

  @Column({ name: 'purchase_order_number', length: 50, nullable: true })
  purchaseOrderNumber?: string;

  // Proyecto asociado
  @Column({ name: 'project_id', type: 'uuid', nullable: true })
  projectId?: string;

  @Column({ name: 'project_code', length: 50, nullable: true })
  projectCode?: string;

  // Centro de costo
  @Column({ name: 'cost_center_id', type: 'uuid', nullable: true })
  costCenterId?: string;

  // Cuenta contable de contrapartida
  @Column({ name: 'expense_account_id', type: 'uuid', nullable: true })
  expenseAccountId?: string;

  // Condiciones de pago
  @Column({ name: 'payment_terms', length: 100, nullable: true })
  paymentTerms?: string;

  @Column({ name: 'payment_days', type: 'int', default: 30 })
  paymentDays!: number;

  // Días de atraso (calculado)
  @Column({ name: 'days_overdue', type: 'int', default: 0 })
  daysOverdue!: number;

  // CFDI (facturación electrónica México)
  @Column({ name: 'cfdi_uuid', length: 36, nullable: true })
  cfdiUuid?: string;

  @Column({ name: 'cfdi_xml_path', length: 500, nullable: true })
  cfdiXmlPath?: string;

  @Column({ name: 'cfdi_pdf_path', length: 500, nullable: true })
  cfdiPdfPath?: string;

  // Aprobación
  @Column({ name: 'approved_for_payment', type: 'boolean', default: false })
  approvedForPayment!: boolean;

  @Column({ name: 'approved_by_id', type: 'uuid', nullable: true })
  approvedById?: string;

  @Column({ name: 'approved_at', type: 'timestamptz', nullable: true })
  approvedAt?: Date;

  // Póliza contable generada
  @Column({ name: 'accounting_entry_id', type: 'uuid', nullable: true })
  accountingEntryId?: string;

  // Pagos asociados
  @OneToMany(() => APPayment, (payment) => payment.accountPayable)
  payments?: APPayment[];

  // Notas y metadatos
  @Column({ type: 'text', nullable: true })
  notes?: string;

  @Column({ type: 'jsonb', nullable: true })
  metadata?: Record<string, any>;

  // Auditoría
  @Column({ name: 'created_by', type: 'uuid', nullable: true })
  createdBy?: string;

  @Column({ name: 'updated_by', type: 'uuid', nullable: true })
  updatedBy?: string;

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt!: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
  updatedAt!: Date;

  @Column({ name: 'deleted_at', type: 'timestamptz', nullable: true })
  deletedAt?: Date;
}
