import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  Index,
  OneToMany,
} from 'typeorm';
import { LineaFactura } from './linea-factura.entity';

/**
 * Estado de Factura
 */
export enum EstadoFactura {
  BORRADOR = 'BORRADOR',
  EMITIDA = 'EMITIDA',
  ENVIADA = 'ENVIADA',
  PAGADA = 'PAGADA',
  PARCIAL = 'PARCIAL',
  VENCIDA = 'VENCIDA',
  CANCELADA = 'CANCELADA',
}

@Entity({ schema: 'billing', name: 'facturas_transporte' })
@Index('idx_factura_tenant', ['tenantId'])
@Index('idx_factura_cliente', ['clienteId'])
@Index('idx_factura_estado', ['tenantId', 'estado'])
@Index('idx_factura_fecha', ['fechaEmision'])
@Index('idx_factura_folio', ['tenantId', 'serie', 'folio'], { unique: true })
export class FacturaTransporte {
  @PrimaryGeneratedColumn('uuid')
  id: string;

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

  // Identificación
  @Column({ type: 'varchar', length: 10, nullable: true })
  serie: string | null;

  @Column({ type: 'varchar', length: 20 })
  folio: string;

  @Column({ name: 'uuid_cfdi', type: 'uuid', nullable: true })
  uuidCfdi: string | null;

  // Cliente
  @Column({ name: 'cliente_id', type: 'uuid' })
  clienteId: string;

  @Column({ name: 'cliente_rfc', type: 'varchar', length: 13 })
  clienteRfc: string;

  @Column({ name: 'cliente_razon_social', type: 'varchar', length: 200 })
  clienteRazonSocial: string;

  @Column({ name: 'cliente_uso_cfdi', type: 'varchar', length: 10, nullable: true })
  clienteUsoCfdi: string | null;

  // Fechas
  @Column({ name: 'fecha_emision', type: 'timestamptz' })
  fechaEmision: Date;

  @Column({ name: 'fecha_vencimiento', type: 'date', nullable: true })
  fechaVencimiento: Date | null;

  // Totales
  @Column({ type: 'decimal', precision: 15, scale: 2 })
  subtotal: number;

  @Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
  descuento: number;

  @Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
  iva: number;

  @Column({ name: 'retencion_iva', type: 'decimal', precision: 15, scale: 2, default: 0 })
  retencionIva: number;

  @Column({ name: 'retencion_isr', type: 'decimal', precision: 15, scale: 2, default: 0 })
  retencionIsr: number;

  @Column({ type: 'decimal', precision: 15, scale: 2 })
  total: number;

  @Column({ type: 'varchar', length: 3, default: 'MXN' })
  moneda: string;

  @Column({ name: 'tipo_cambio', type: 'decimal', precision: 10, scale: 4, default: 1 })
  tipoCambio: number;

  // Pago
  @Column({ name: 'forma_pago', type: 'varchar', length: 10, nullable: true })
  formaPago: string | null;

  @Column({ name: 'metodo_pago', type: 'varchar', length: 10, nullable: true })
  metodoPago: string | null;

  @Column({ name: 'condiciones_pago', type: 'varchar', length: 200, nullable: true })
  condicionesPago: string | null;

  // Relacionados
  @Column({ name: 'viaje_ids', type: 'uuid', array: true, nullable: true })
  viajeIds: string[] | null;

  @Column({ name: 'ot_ids', type: 'uuid', array: true, nullable: true })
  otIds: string[] | null;

  // CFDI
  @Column({ name: 'xml_cfdi', type: 'text', nullable: true })
  xmlCfdi: string | null;

  @Column({ name: 'pdf_url', type: 'text', nullable: true })
  pdfUrl: string | null;

  // Estado
  @Column({ type: 'enum', enum: EstadoFactura, default: EstadoFactura.BORRADOR })
  estado: EstadoFactura;

  // Pago
  @Column({ name: 'monto_pagado', type: 'decimal', precision: 15, scale: 2, default: 0 })
  montoPagado: number;

  @Column({ name: 'fecha_pago', type: 'timestamptz', nullable: true })
  fechaPago: Date | null;

  // Cancelación
  @Column({ name: 'fecha_cancelacion', type: 'timestamptz', nullable: true })
  fechaCancelacion: Date | null;

  @Column({ name: 'motivo_cancelacion', type: 'text', nullable: true })
  motivoCancelacion: string | null;

  // Relations
  @OneToMany(() => LineaFactura, (linea) => linea.factura)
  lineas: LineaFactura[];

  // Auditoría
  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt: Date;

  @Column({ name: 'created_by_id', type: 'uuid' })
  createdById: string;

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

  // Helpers
  get saldoPendiente(): number {
    return this.total - this.montoPagado;
  }

  get estaPagada(): boolean {
    return this.estado === EstadoFactura.PAGADA || this.montoPagado >= this.total;
  }

  get estaVencida(): boolean {
    if (!this.fechaVencimiento || this.estaPagada) return false;
    return new Date() > new Date(this.fechaVencimiento);
  }

  get diasVencida(): number {
    if (!this.fechaVencimiento || !this.estaVencida) return 0;
    const hoy = new Date();
    const vencimiento = new Date(this.fechaVencimiento);
    return Math.ceil((hoy.getTime() - vencimiento.getTime()) / (1000 * 60 * 60 * 24));
  }

  get folioCompleto(): string {
    return this.serie ? `${this.serie}-${this.folio}` : this.folio;
  }
}
