import { BaseEntity } from '@edr/api-common';
import { Column, Entity, Index, OneToMany, ManyToOne, JoinColumn } from 'typeorm';

import { TrainSet } from '../../train-sets/entities/train-set.entity';
import { Yard } from '../../rule-engine/entities/yard.entity';

export const LOCOMOTIVE_STATUSES = [
  'AVAILABLE',
  'UNAVAILABLE',
  'IMPORT_READY',
  'EXPORT_READY',
  'ASSIGNED',
  'MAINTENANCE',
  'OUT_OF_SERVICE',
] as const;

export const LOCOMOTIVE_TYPES = ['DIESEL', 'ELECTRIC'] as const;

export type LocomotiveStatus = (typeof LOCOMOTIVE_STATUSES)[number];
export type LocomotiveType = (typeof LOCOMOTIVE_TYPES)[number];

@Entity({ schema: 'freight', name: 'locomotives' })
@Index(['code'])
@Index(['status'])
@Index(['currentYardId'])
export class Locomotive extends BaseEntity {
  @Column({ name: 'code', type: 'varchar', length: 32, unique: true })
  code!: string;

  /**
   * Optional, but unique when set. Enforced in the DB by the partial expression
   * index `UQ_locomotives_name_active` (see UniqueLocomotiveName2430000000000):
   * case- and whitespace-insensitive, live rows only, blanks exempt. Not a
   * `unique: true` column — that would be case-sensitive and would let a
   * soft-deleted locomotive keep holding its name.
   */
  @Column({ name: 'name', type: 'varchar', length: 100, nullable: true })
  name?: string | null;

  @Column({ name: 'locomotive_type', type: 'varchar', length: 20, default: 'DIESEL' })
  locomotiveType!: LocomotiveType;

  @Column({ name: 'max_pull_weight_tons', type: 'numeric', precision: 10, scale: 3 })
  maxPullWeightTons!: number;

  @Column({ name: 'max_train_length_meters', type: 'numeric', precision: 10, scale: 3, default: 760 })
  maxTrainLengthMeters!: number;

  /** Allowed deviation above maxPullWeightTons before a train is blocked (e.g. the 37th PW2 wagon in the fertilizer example runs 90T over 3,500T and is still accepted). Null/0 = no tolerance. */
  @Column({
    name: 'overage_tolerance_tons',
    type: 'numeric',
    precision: 10,
    scale: 3,
    nullable: true,
  })
  overageToleranceTons?: number | null;

  /** Allowed deviation above maxTrainLengthMeters before a train is blocked. Null/0 = no tolerance. */
  @Column({
    name: 'overage_tolerance_meters',
    type: 'numeric',
    precision: 10,
    scale: 3,
    nullable: true,
  })
  overageToleranceMeters?: number | null;

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

  @Column({ name: 'current_yard_id', type: 'uuid', nullable: true })
  currentYardId!: string | null;

  @ManyToOne(() => Yard, { nullable: true, onDelete: 'SET NULL' })
  @JoinColumn({ name: 'current_yard_id' })
  currentYard?: Yard | null;

  @OneToMany(() => TrainSet, (trainSet) => trainSet.locomotive)
  trainSets?: TrainSet[];
}
