/**
 * AccountReceivable Entity - Cuentas por Cobrar
 *
 * Registro de derechos de cobro a clientes.
 *
 * @module Finance
 */

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  OneToMany,
  Index,
} from 'typeorm';
import { ARPayment } from './ar-payment.entity';

export type ARStatus = 'pending' | 'partial' | 'collected' | 'overdue' | 'cancelled' | 'written_off';
export type ARDocumentType = 'invoice' | 'credit_note' | 'debit_note' | 'advance' | 'estimation';

@Entity('accounts_receivable', { schema: 'finance' })
@Index(['tenantId', 'customerId'])
@Index(['tenantId', 'status'])
@Index(['tenantId', 'dueDate'])
@Index(['tenantId', 'projectId'])
export class AccountReceivable {
  @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', 'estimation'],
    enumName: 'ar_document_type',
    default: 'invoice',
  })
  documentType!: ARDocumentType;

  // Cliente
  @Column({ name: 'customer_id', type: 'uuid' })
  customerId!: string;

  @Column({ name: 'customer_name', length: 255 })
  customerName!: string;

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

  // Estado
  @Column({
    type: 'enum',
    enum: ['pending', 'partial', 'collected', 'overdue', 'cancelled', 'written_off'],
    enumName: 'ar_status',
    default: 'pending',
  })
  status!: ARStatus;

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

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

  @Column({ name: 'collection_date', type: 'date', nullable: true })
  collectionDate?: 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: 'collected_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    default: 0,
  })
  collectedAmount!: 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 (estimación, venta)
  @Column({ name: 'source_module', length: 50, nullable: true })
  sourceModule?: string;

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

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

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

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

  // Condiciones de cobro
  @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;

  // Cuenta contable
  @Column({ name: 'income_account_id', type: 'uuid', nullable: true })
  incomeAccountId?: string;

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

  // Seguimiento de cobranza
  @Column({ name: 'last_collection_attempt', type: 'date', nullable: true })
  lastCollectionAttempt?: Date;

  @Column({ name: 'collection_attempts', type: 'int', default: 0 })
  collectionAttempts!: number;

  @Column({ name: 'collection_notes', type: 'text', nullable: true })
  collectionNotes?: string;

  // Cobros asociados
  @OneToMany(() => ARPayment, (payment) => payment.accountReceivable)
  payments?: ARPayment[];

  // 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;
}
