import { Entity, Column, Index, Check, ManyToOne, JoinColumn } from 'typeorm';
import { BaseEntity } from '../database/base.entity';
import { ServicePaymentCollectionEntity } from './service-payment-collection.entity';
import { UserEntity } from './user.entity';

/**
 * One row = one confirmed collection event on a
 * ServicePaymentCollectionEntity.
 *
 * ## Append-only + void
 * Rows are never deleted. Amending a confirmation (edit-confirmed
 * flow, guarded by PAYMENT_COLLECTION:delete) is modelled as
 *   1. Mark the previous row `voided_at = NOW(), voided_by = user`
 *   2. Insert a fresh row
 * so the history of what was ever recorded stays queryable in the
 * domain model — no need to walk audit_log to answer "what was the
 * original amount?".
 *
 * The parent's `status` snapshot always reflects the latest live
 * (non-voided) confirmation.
 *
 * ## Ledger link
 * `settlement_payment_id` links to the SettlementPaymentEntity created
 * when this confirmation was recorded. Voiding a confirmation refunds
 * that payment (or marks it void) via
 * PaymentSettlementService.voidPayment.
 *
 * ## Difference reason
 * `difference_reason` is required by service-layer validation when
 * `actual_amount !== collection.expected_amount`. Kept nullable at
 * the DB level because the check spans two rows-in-flight fields.
 */
@Entity('service_payment_collection_confirmations')
@Index('ix_spcc_collection', ['collection_id'])
// Fast "latest live confirmation for this collection" lookup — the
// hot path when the MD renders status + amount.
@Index('ix_spcc_collection_live', ['collection_id'], {
  where: '"voided_at" IS NULL AND "is_deleted" = false',
})
@Check('chk_spcc_actual_non_neg', `"actual_amount" >= 0`)
export class ServicePaymentCollectionConfirmationEntity extends BaseEntity {
  @ManyToOne(() => ServicePaymentCollectionEntity, (c) => c.confirmations, {
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'collection_id' })
  collection: ServicePaymentCollectionEntity;

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

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

  /** When the guest paid (user-entered, not `created_at`). */
  @Column({ type: 'timestamptz' })
  collected_at: Date;

  @ManyToOne(() => UserEntity)
  @JoinColumn({ name: 'collected_by' })
  collected_by_user: UserEntity;

  /** DMC user who recorded the event (not the physical collector —
   *  that's the driver/supplier assigned to the parent service item). */
  @Column({ type: 'uuid' })
  collected_by: string;

  @Column({ type: 'varchar', length: 500, nullable: true })
  difference_reason: string | null;

  /** FK to settlement_payments — the ledger row that credits the
   *  booking's customer receivable when this confirmation lands.
   *  Nullable so a confirmation can be recorded even if the ledger
   *  write fails (audited separately, ops retries). */
  @Column({ type: 'uuid', nullable: true })
  settlement_payment_id: string | null;

  @Column({ type: 'timestamptz', nullable: true })
  voided_at: Date | null;

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

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