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

/**
 * SupplierCostPriceEntity — per stakeholder spec, DMCs need to
 * capture what they PAY a supplier for each service × vehicle type,
 * so quotes can warn when selling price dips below cost.
 *
 * Keyed on (tenant × supplier × transport_service × vehicle_type ×
 * season). Season is nullable to support tenants that don't tier
 * cost pricing seasonally. Unique-index enforces a single row per
 * combination so lookups can't return ambiguous results.
 *
 * Currency stored explicitly — supplier quotes often come in the
 * destination's local currency while the booking may sell in USD;
 * keeping currency on the row lets the quote editor do the
 * conversion at lookup time.
 *
 * (Activity cost pricing will follow the same pattern in a sibling
 * entity once stakeholder signs off on the UX; the transport variant
 * is the urgent path for the movement chart.)
 */
/**
 * Sale modes — mirrors transport_pricing.mode. Same semantics:
 *   PVT — per-vehicle cost, broken down by vehicle_type_id
 *   SIC — per-person cost on a shared coach; vehicle_type_id is NULL
 *         because the customer-facing rate doesn't depend on which
 *         coach the supplier dispatches.
 */
export enum SupplierCostPriceMode {
  PVT = 'PVT',
  SIC = 'SIC',
}

@Entity('supplier_cost_prices')
// Four partial unique indexes — one per (mode × seasoned/all-season)
// quadrant. SIC rows have NULL vehicle_type_id and seasoned rows may
// have NULL season_id; Postgres' NULL-distinct semantics on plain
// unique indexes would let duplicates slip through, so each quadrant
// gets its own predicate.
@Index(
  'IDX_scp_pvt_seasoned_unique',
  ['tenant_id', 'supplier_id', 'transport_service_id', 'vehicle_type_id', 'mode', 'season_id'],
  { unique: true, where: '"is_deleted" = false AND "mode" = \'PVT\' AND "season_id" IS NOT NULL' },
)
@Index(
  'IDX_scp_pvt_default_unique',
  ['tenant_id', 'supplier_id', 'transport_service_id', 'vehicle_type_id', 'mode'],
  { unique: true, where: '"is_deleted" = false AND "mode" = \'PVT\' AND "season_id" IS NULL' },
)
@Index(
  'IDX_scp_sic_seasoned_unique',
  ['tenant_id', 'supplier_id', 'transport_service_id', 'mode', 'season_id'],
  {
    unique: true,
    where:
      '"is_deleted" = false AND "mode" = \'SIC\' AND "vehicle_type_id" IS NULL AND "season_id" IS NOT NULL',
  },
)
@Index('IDX_scp_sic_default_unique', ['tenant_id', 'supplier_id', 'transport_service_id', 'mode'], {
  unique: true,
  where:
    '"is_deleted" = false AND "mode" = \'SIC\' AND "vehicle_type_id" IS NULL AND "season_id" IS NULL',
})
export class SupplierCostPriceEntity extends BaseEntity {
  @ManyToOne(() => SupplierEntity, { onDelete: 'CASCADE' })
  @JoinColumn({ name: 'supplier_id' })
  supplier: SupplierEntity;

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

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

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

  /**
   * Vehicle type — required for PVT, NULL for SIC (per-person rate
   * doesn't depend on which coach the supplier dispatches).
   */
  @ManyToOne(() => VehicleTypeEntity, { nullable: true, onDelete: 'CASCADE' })
  @JoinColumn({ name: 'vehicle_type_id' })
  vehicle_type: VehicleTypeEntity | null;

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

  /**
   * Sale mode — defaults to PVT so existing rows tag automatically
   * as private (per-vehicle), preserving every pre-mode integration
   * byte-for-byte.
   */
  @Column({ type: 'varchar', length: 8, default: SupplierCostPriceMode.PVT })
  mode: SupplierCostPriceMode;

  /**
   * Season-scoped cost pricing. Null means "default / all-season"
   * so tenants without seasonal cost variation only capture one
   * row per (supplier × service × vehicle_type).
   */
  @ManyToOne(() => SeasonEntity, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'season_id' })
  season: SeasonEntity | null;

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

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

  @ManyToOne(() => CurrencyEntity, { nullable: true })
  @JoinColumn({ name: 'currency_id' })
  currency: CurrencyEntity | null;

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

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

  @Column({ type: 'boolean', default: true })
  is_active: boolean;
}
