/**
 * Unified Invoice Entity
 * Combines commercial and SaaS billing invoices
 * Compatible with erp-core invoice.entity
 *
 * @module Invoices
 */

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  DeleteDateColumn,
  Index,
  OneToMany,
} from 'typeorm';
import { InvoiceItem } from './invoice-item.entity';

export type InvoiceType = 'sale' | 'purchase' | 'credit_note' | 'debit_note';
export type InvoiceStatus = 'draft' | 'validated' | 'sent' | 'partial' | 'paid' | 'overdue' | 'void' | 'refunded' | 'cancelled' | 'voided';
export type InvoiceContext = 'commercial' | 'saas';

@Entity({ name: 'invoices', schema: 'billing' })
export class Invoice {
  @PrimaryGeneratedColumn('uuid')
  id: string;

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

  @Index({ unique: true })
  @Column({ name: 'invoice_number', type: 'varchar', length: 30 })
  invoiceNumber: string;

  @Index()
  @Column({ name: 'invoice_type', type: 'varchar', length: 20, default: 'sale' })
  invoiceType: InvoiceType;

  @Index()
  @Column({ name: 'invoice_context', type: 'varchar', length: 20, default: 'commercial' })
  invoiceContext: InvoiceContext;

  // Commercial fields
  @Column({ name: 'sales_order_id', type: 'uuid', nullable: true })
  salesOrderId: string | null;

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

  @Index()
  @Column({ name: 'partner_id', type: 'uuid', nullable: true })
  partnerId: string | null;

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

  @Column({ name: 'partner_tax_id', type: 'varchar', length: 50, nullable: true })
  partnerTaxId: string | null;

  // SaaS billing fields
  @Index()
  @Column({ name: 'subscription_id', type: 'uuid', nullable: true })
  subscriptionId: string | null;

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

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

  // Billing information
  @Column({ name: 'billing_name', type: 'varchar', length: 200, nullable: true })
  billingName: string | null;

  @Column({ name: 'billing_email', type: 'varchar', length: 255, nullable: true })
  billingEmail: string | null;

  @Column({ name: 'billing_address', type: 'jsonb', nullable: true })
  billingAddress: Record<string, any> | null;

  @Column({ name: 'tax_id', type: 'varchar', length: 50, nullable: true })
  taxId: string | null;

  // Dates
  @Index()
  @Column({ name: 'invoice_date', type: 'date', default: () => 'CURRENT_DATE' })
  invoiceDate: Date;

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

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

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

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

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

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

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

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

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

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

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

  @Column({ name: 'amount_due', type: 'decimal', precision: 15, scale: 2, insert: false, update: false, nullable: true })
  amountDue: number | null;

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

  // Payment details
  @Column({ name: 'payment_term_days', type: 'int', default: 0 })
  paymentTermDays: number;

  @Column({ name: 'payment_method', type: 'varchar', length: 50, nullable: true })
  paymentMethod: string | null;

  @Column({ name: 'payment_reference', type: 'varchar', length: 100, nullable: true })
  paymentReference: string | null;

  // Status
  @Index()
  @Column({ type: 'varchar', length: 20, default: 'draft' })
  status: InvoiceStatus;

  // CFDI (Mexico)
  @Index()
  @Column({ name: 'cfdi_uuid', type: 'varchar', length: 40, nullable: true })
  cfdiUuid: string | null;

  @Column({ name: 'cfdi_status', type: 'varchar', length: 20, nullable: true })
  cfdiStatus: string | null;

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

  @Column({ name: 'cfdi_pdf_url', type: 'varchar', length: 500, nullable: true })
  cfdiPdfUrl: string | null;

  // Notes
  @Column({ type: 'text', nullable: true })
  notes: string | null;

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

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

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

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

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

  @DeleteDateColumn({ name: 'deleted_at', type: 'timestamptz', nullable: true })
  deletedAt: Date | null;

  // Relations
  @OneToMany(() => InvoiceItem, (item) => item.invoice, { cascade: true })
  items: InvoiceItem[];
}
