import { Entity, Column, Index, ManyToOne, JoinColumn } from 'typeorm';
import { BaseEntity } from '../database/base.entity';
import { DestinationEntity } from './destination.entity';
import { TransportServiceEntity } from './transport-service.entity';
import { VehicleTypeEntity } from './vehicle-type.entity';
import { CurrencyEntity } from './currency.entity';

/**
 * Sale modes — per stakeholder spec a transport line is either
 *   PVT — per-vehicle pricing, broken down by vehicle type
 *   SIC — per-person pricing on a shared coach; vehicle_type_id is NULL
 *         because the customer-facing rate doesn't depend on which
 *         vehicle dispatch picks (capacity / coach choice is a
 *         Movement Chart concern, not a pricing axis).
 */
export enum TransportPriceMode {
  PVT = 'PVT',
  SIC = 'SIC',
}

/**
 * Transport Pricing entity — tenant-scoped.
 *
 * Matrix: Transport Service × Mode × (Vehicle Type | NULL) × Currency
 *           → Default + 5 Seasonal Prices.
 *
 * Vehicle type is now a proper FK (vehicle_type_id) — was previously
 * stored as a free-text `cab_type` column (the legacy column survives
 * as a nullable shim in older rows; see migration 1776), which made
 * joins on the vehicle_types master fragile (relied on the unique-name
 * index + exact spelling). FK keeps the join trivial and renames in
 * the master propagate automatically.
 *
 * Two partial unique indexes pin uniqueness per mode quadrant —
 * Postgres treats NULL as distinct in plain unique indexes, so the
 * SIC-with-NULL-vehicle-type case needs its own predicate to enforce
 * "one SIC row per (service, currency)".
 *
 * Season columns are positional (1-5 by sort_order from Season Master).
 * Auto-fetched in quotations by matching travel date to SeasonDuration ranges.
 */
@Entity('transport_pricing')
@Index(
  'IDX_transport_pricing_pvt_unique',
  ['tenant_id', 'transport_service_id', 'vehicle_type_id', 'mode', 'currency_id'],
  { unique: true, where: '"is_deleted" = false AND "mode" = \'PVT\'' },
)
@Index(
  'IDX_transport_pricing_sic_unique',
  ['tenant_id', 'transport_service_id', 'mode', 'currency_id'],
  {
    unique: true,
    where: '"is_deleted" = false AND "mode" = \'SIC\' AND "vehicle_type_id" IS NULL',
  },
)
export class TransportPricingEntity extends BaseEntity {
  @ManyToOne(() => DestinationEntity)
  @JoinColumn({ name: 'destination_id' })
  destination: DestinationEntity;

  @Column({ type: 'uuid' })
  destination_id: string;

  @ManyToOne(() => TransportServiceEntity)
  @JoinColumn({ name: 'transport_service_id' })
  transport_service: TransportServiceEntity;

  @Column({ type: 'uuid' })
  transport_service_id: string;

  @Column({ type: 'varchar', length: 50 })
  category: string;

  /**
   * Vehicle type — required for PVT, NULL for SIC. SIC pricing is
   * per-person on the shared coach; the supplier picks which coach
   * actually runs the trip at dispatch time. Foreign key into
   * vehicle_types so renaming a master entry propagates everywhere.
   */
  @ManyToOne(() => VehicleTypeEntity, { nullable: true })
  @JoinColumn({ name: 'vehicle_type_id' })
  vehicle_type: VehicleTypeEntity | null;

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

  /**
   * Sale mode — PVT (per-vehicle) or SIC (per-person shared coach).
   * Defaults to PVT so existing rows automatically tag as private —
   * preserves all pre-mode behaviour byte-for-byte.
   */
  @Column({ type: 'varchar', length: 8, default: TransportPriceMode.PVT })
  mode: TransportPriceMode;

  @ManyToOne(() => CurrencyEntity)
  @JoinColumn({ name: 'currency_id' })
  currency: CurrencyEntity;

  @Column({ type: 'uuid' })
  currency_id: string;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  default_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_1_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_2_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_3_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_4_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_5_price: number | null;

  // ── Floor pricing ────────────────────────────────────────────────
  // Lowest acceptable selling price per season. Quote/Booking saves
  // validate `unit_price` against the floor for the active season; below
  // floor is blocked and routed to a Change Request for approval.
  // NULL = no floor configured for that season, allow any price.

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_default_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_1_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_2_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_3_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_4_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_5_price: number | null;

  // ── Tax bifurcation (Step 2 migration) ────────────────────────────
  // Each inclusive price cell is bifurcated into base + tax_amount at
  // save time so reads don't have to recompute. season_5 is intentionally
  // omitted — Phase 1 only uses 4 seasonal tiers + default.

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  default_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  default_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_1_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_1_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_2_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_2_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_3_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_3_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_4_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  season_4_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_default_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_default_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_1_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_1_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_2_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_2_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_3_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_3_tax_amount: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_4_base_price: number | null;

  @Column({ type: 'decimal', precision: 12, scale: 2, nullable: true })
  floor_season_4_tax_amount: number | null;
}
