import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
import { CargoType } from './cargo-type.entity';
import { ContainerType } from './container-type.entity';

export const RATE_TYPES = [
  'CONTAINER_IMPORT',
  'CONTAINER_EXPORT',
  'BULK_IMPORT',
  'BULK_EXPORT',
  'INTERCITY_BULK',
  'INTERCITY_CONTAINER',
  'FIRST_MILE',
  'LAST_MILE',
  'DEMURRAGE',
  'LASHING',
  'DOUBLE_HANDLING',
  'CONTAINER_WITH_RETURN',
  'CANCELLATION_FEE',
  'OVERWEIGHT_PER_TON',
  'HAZARD_SURCHARGE',
  'REEFER_SURCHARGE',
  'PIL_EXTRA_FEE',
] as const;

export type RateType = typeof RATE_TYPES[number];

export const RATE_STATUSES = ['DRAFT', 'PENDING_APPROVAL', 'LIVE', 'SUPERSEDED'] as const;
export type RateStatus = typeof RATE_STATUSES[number];

export const RATE_UNITS = [
  'PER_WAGON',
  'PER_TON',
  'PER_CONTAINER',
  'PER_KM',
  'PER_INVOICE',
  'FLAT',
] as const;
export type RateUnit = typeof RATE_UNITS[number];

/**
 * Friendly, admin-facing category that determines how the rate is used in
 * pricing and which fields the rate form shows. Replaces the cryptic
 * `rateType` matrix for the configuration UI (rateType is still persisted and
 * derived from `appliesTo` + `tradeDirection` + `trigger` for base-freight
 * lookup and snapshots).
 *
 *  - BULK / CONTAINER / INTERCITY : base rail freight (trigger = ALWAYS)
 *  - FIRST_MILE / LAST_MILE       : pickup / delivery legs
 *  - OTHER                        : trigger-based surcharges (hazard, reefer …)
 */
export const RATE_APPLIES_TO = [
  'BULK',
  'CONTAINER',
  'INTERCITY',
  'FIRST_MILE',
  'LAST_MILE',
  'OTHER',
] as const;
export type RateAppliesTo = typeof RATE_APPLIES_TO[number];

/**
 * What makes a rate apply to a booking. `ALWAYS` is base freight (matched by
 * direction + container/bulk scope). Everything else is a surcharge that the
 * rule engine adds on top, additively, when the booking matches the trigger —
 * so hazard stacks on container/bulk with each line's own unit.
 */
export const RATE_TRIGGERS = [
  'ALWAYS',
  'HAZARDOUS',
  'OVERWEIGHT',
  'REEFER',
  'SHIPPING_LINE',
  'CONSOLIDATION',
  'CANCELLATION',
  'DEMURRAGE',
  'PIL_EXTRA_FEE',
] as const;
export type RateTrigger = typeof RATE_TRIGGERS[number];

@Entity({ schema: 'freight', name: 'rates' })
@Index(['rateType'])
@Index(['status'])
@Index(['effectiveFrom'])
@Index(['containerTypeId'])
@Index(['trigger'])
export class Rate extends BaseEntity {
  @Column({ name: 'rate_type', type: 'varchar', length: 50 })
  rateType!: RateType;

  @Column({ name: 'applies_to', type: 'varchar', length: 20, default: 'OTHER' })
  appliesTo!: RateAppliesTo;

  @Column({ name: 'trigger', type: 'varchar', length: 20, default: 'ALWAYS' })
  trigger!: RateTrigger;

  @Column({ name: 'container_type_id', type: 'uuid', nullable: true })
  containerTypeId?: string | null;

  @ManyToOne(() => ContainerType, { nullable: true, eager: false })
  @JoinColumn({ name: 'container_type_id' })
  containerType?: ContainerType | null;

  @Column({ name: 'cargo_type_id', type: 'uuid', nullable: true })
  cargoTypeId?: string | null;

  @ManyToOne(() => CargoType, { nullable: true, eager: false })
  @JoinColumn({ name: 'cargo_type_id' })
  cargoType?: CargoType | null;

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

  @Column({ name: 'currency', type: 'varchar', length: 5 })
  currency!: string;

  @Column({ name: 'rate_value', type: 'numeric', precision: 14, scale: 4 })
  rateValue!: number;

  @Column({ name: 'rate_unit', type: 'varchar', length: 30 })
  rateUnit!: RateUnit;

  @Column({ name: 'status', type: 'varchar', length: 20, default: 'DRAFT' })
  status!: RateStatus;

  @Column({ name: 'proposed_by_staff_id', type: 'uuid' })
  proposedByStaffId!: string;

  @Column({ name: 'approved_by_ceo_id', type: 'uuid', nullable: true })
  approvedByCeoId?: string | null;

  @Column({ name: 'approved_at', type: 'timestamptz', nullable: true })
  approvedAt?: Date | null;

  @Column({ name: 'effective_from', type: 'date' })
  effectiveFrom!: Date;

  @Column({ name: 'effective_to', type: 'date', nullable: true })
  effectiveTo?: Date | null;
}
