import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  Index,
  ManyToOne,
  JoinColumn,
} from 'typeorm';
import { Lane } from './lane.entity';

/**
 * Tipo de Tarifa
 */
export enum TipoTarifa {
  POR_VIAJE = 'POR_VIAJE',
  POR_KM = 'POR_KM',
  POR_TONELADA = 'POR_TONELADA',
  POR_M3 = 'POR_M3',
  POR_PALLET = 'POR_PALLET',
  POR_HORA = 'POR_HORA',
  MIXTA = 'MIXTA',
}

@Entity({ schema: 'billing', name: 'tarifas' })
@Index('idx_tarifa_tenant', ['tenantId'])
@Index('idx_tarifa_cliente', ['clienteId'])
@Index('idx_tarifa_lane', ['laneId'])
@Index('idx_tarifa_activa', ['tenantId', 'activa', 'fechaInicio'])
export class Tarifa {
  @PrimaryGeneratedColumn('uuid')
  id: string;

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

  // Identificación
  @Column({ type: 'varchar', length: 50 })
  codigo: string;

  @Column({ type: 'varchar', length: 200 })
  nombre: string;

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

  // Cliente (opcional para tarifas generales)
  @Column({ name: 'cliente_id', type: 'uuid', nullable: true })
  clienteId: string | null;

  // Lane (opcional)
  @Column({ name: 'lane_id', type: 'uuid', nullable: true })
  laneId: string | null;

  @ManyToOne(() => Lane)
  @JoinColumn({ name: 'lane_id' })
  lane: Lane | null;

  // Tipo de servicio
  @Column({ name: 'modalidad_servicio', type: 'varchar', length: 50, nullable: true })
  modalidadServicio: string | null;

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

  // Tipo de tarifa
  @Column({ name: 'tipo_tarifa', type: 'enum', enum: TipoTarifa })
  tipoTarifa: TipoTarifa;

  // Precios
  @Column({ name: 'tarifa_base', type: 'decimal', precision: 15, scale: 2 })
  tarifaBase: number;

  @Column({ name: 'tarifa_km', type: 'decimal', precision: 10, scale: 4, nullable: true })
  tarifaKm: number | null;

  @Column({ name: 'tarifa_tonelada', type: 'decimal', precision: 10, scale: 4, nullable: true })
  tarifaTonelada: number | null;

  @Column({ name: 'tarifa_m3', type: 'decimal', precision: 10, scale: 4, nullable: true })
  tarifaM3: number | null;

  @Column({ name: 'tarifa_pallet', type: 'decimal', precision: 10, scale: 4, nullable: true })
  tarifaPallet: number | null;

  @Column({ name: 'tarifa_hora', type: 'decimal', precision: 10, scale: 4, nullable: true })
  tarifaHora: number | null;

  // Mínimos
  @Column({ name: 'minimo_facturar', type: 'decimal', precision: 15, scale: 2, nullable: true })
  minimoFacturar: number | null;

  @Column({ name: 'peso_minimo_kg', type: 'decimal', precision: 10, scale: 2, nullable: true })
  pesoMinimoKg: number | null;

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

  // Vigencia
  @Column({ name: 'fecha_inicio', type: 'date' })
  fechaInicio: Date;

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

  // Estado
  @Column({ type: 'boolean', default: true })
  activa: boolean;

  // 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 vigente(): boolean {
    const hoy = new Date();
    const inicio = new Date(this.fechaInicio);
    const fin = this.fechaFin ? new Date(this.fechaFin) : null;
    return this.activa && hoy >= inicio && (!fin || hoy <= fin);
  }

  get esEspecifica(): boolean {
    return !!this.clienteId;
  }

  calcularMonto(params: { km?: number; toneladas?: number; m3?: number; pallets?: number; horas?: number }): number {
    let total = this.tarifaBase;

    switch (this.tipoTarifa) {
      case TipoTarifa.POR_KM:
        total += (params.km || 0) * (this.tarifaKm || 0);
        break;
      case TipoTarifa.POR_TONELADA:
        total += (params.toneladas || 0) * (this.tarifaTonelada || 0);
        break;
      case TipoTarifa.POR_M3:
        total += (params.m3 || 0) * (this.tarifaM3 || 0);
        break;
      case TipoTarifa.POR_PALLET:
        total += (params.pallets || 0) * (this.tarifaPallet || 0);
        break;
      case TipoTarifa.POR_HORA:
        total += (params.horas || 0) * (this.tarifaHora || 0);
        break;
      case TipoTarifa.MIXTA:
        total += (params.km || 0) * (this.tarifaKm || 0);
        total += (params.toneladas || 0) * (this.tarifaTonelada || 0);
        break;
    }

    return this.minimoFacturar ? Math.max(total, this.minimoFacturar) : total;
  }
}
