/**
 * Bid Entity - Licitaciones/Propuestas
 *
 * Representa una licitación o propuesta formal vinculada a una oportunidad.
 *
 * @module Bidding
 */

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  ManyToOne,
  OneToMany,
  JoinColumn,
  Index,
} from 'typeorm';
import { User } from '../../core/entities/user.entity';
import { Opportunity } from './opportunity.entity';
import { BidDocument } from './bid-document.entity';
import { BidCalendar } from './bid-calendar.entity';
import { BidBudget } from './bid-budget.entity';
import { BidCompetitor } from './bid-competitor.entity';
import { BidTeam } from './bid-team.entity';

export type BidType = 'public' | 'private' | 'invitation' | 'direct_award' | 'framework_agreement';

export type BidStatus =
  | 'draft'
  | 'preparation'
  | 'review'
  | 'approved'
  | 'submitted'
  | 'clarification'
  | 'evaluation'
  | 'awarded'
  | 'rejected'
  | 'cancelled'
  | 'withdrawn';

export type BidStage =
  | 'initial'
  | 'technical_proposal'
  | 'economic_proposal'
  | 'final_submission'
  | 'post_submission';

@Entity('bids', { schema: 'bidding' })
@Index(['tenantId', 'status'])
@Index(['tenantId', 'bidType'])
@Index(['tenantId', 'opportunityId'])
export class Bid {
  @PrimaryGeneratedColumn('uuid')
  id!: string;

  @Column({ name: 'tenant_id', type: 'uuid' })
  @Index()
  tenantId!: string;

  // Referencia a oportunidad
  @Column({ name: 'opportunity_id', type: 'uuid' })
  opportunityId!: string;

  @ManyToOne(() => Opportunity, (opp) => opp.bids)
  @JoinColumn({ name: 'opportunity_id' })
  opportunity?: Opportunity;

  // Información básica
  @Column({ length: 100 })
  code!: string;

  @Column({ length: 500 })
  name!: string;

  @Column({ type: 'text', nullable: true })
  description?: string;

  @Column({
    name: 'bid_type',
    type: 'enum',
    enum: ['public', 'private', 'invitation', 'direct_award', 'framework_agreement'],
    enumName: 'bid_type',
  })
  bidType!: BidType;

  @Column({
    type: 'enum',
    enum: ['draft', 'preparation', 'review', 'approved', 'submitted', 'clarification', 'evaluation', 'awarded', 'rejected', 'cancelled', 'withdrawn'],
    enumName: 'bid_status',
    default: 'draft',
  })
  status!: BidStatus;

  @Column({
    type: 'enum',
    enum: ['initial', 'technical_proposal', 'economic_proposal', 'final_submission', 'post_submission'],
    enumName: 'bid_stage',
    default: 'initial',
  })
  stage!: BidStage;

  // Referencia de convocatoria
  @Column({ name: 'tender_number', length: 100, nullable: true })
  tenderNumber?: string;

  @Column({ name: 'tender_name', length: 500, nullable: true })
  tenderName?: string;

  @Column({ name: 'contracting_entity', length: 255, nullable: true })
  contractingEntity?: string;

  // Fechas clave
  @Column({ name: 'publication_date', type: 'date', nullable: true })
  publicationDate?: Date;

  @Column({ name: 'site_visit_date', type: 'timestamptz', nullable: true })
  siteVisitDate?: Date;

  @Column({ name: 'clarification_deadline', type: 'timestamptz', nullable: true })
  clarificationDeadline?: Date;

  @Column({ name: 'submission_deadline', type: 'timestamptz' })
  submissionDeadline!: Date;

  @Column({ name: 'opening_date', type: 'timestamptz', nullable: true })
  openingDate?: Date;

  @Column({ name: 'award_date', type: 'date', nullable: true })
  awardDate?: Date;

  @Column({ name: 'contract_signing_date', type: 'date', nullable: true })
  contractSigningDate?: Date;

  // Montos
  @Column({
    name: 'base_budget',
    type: 'decimal',
    precision: 18,
    scale: 2,
    nullable: true,
  })
  baseBudget?: number;

  @Column({
    name: 'our_proposal_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    nullable: true,
  })
  ourProposalAmount?: number;

  @Column({
    name: 'winning_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    nullable: true,
  })
  winningAmount?: number;

  @Column({ name: 'currency', length: 3, default: 'MXN' })
  currency!: string;

  // Propuesta técnica
  @Column({
    name: 'technical_score',
    type: 'decimal',
    precision: 5,
    scale: 2,
    nullable: true,
  })
  technicalScore?: number;

  @Column({
    name: 'technical_weight',
    type: 'decimal',
    precision: 5,
    scale: 2,
    default: 50,
  })
  technicalWeight!: number;

  // Propuesta económica
  @Column({
    name: 'economic_score',
    type: 'decimal',
    precision: 5,
    scale: 2,
    nullable: true,
  })
  economicScore?: number;

  @Column({
    name: 'economic_weight',
    type: 'decimal',
    precision: 5,
    scale: 2,
    default: 50,
  })
  economicWeight!: number;

  // Puntuación final
  @Column({
    name: 'final_score',
    type: 'decimal',
    precision: 5,
    scale: 2,
    nullable: true,
  })
  finalScore?: number;

  @Column({ name: 'ranking_position', type: 'int', nullable: true })
  rankingPosition?: number;

  // Garantías
  @Column({
    name: 'bid_bond_amount',
    type: 'decimal',
    precision: 18,
    scale: 2,
    nullable: true,
  })
  bidBondAmount?: number;

  @Column({ name: 'bid_bond_number', length: 100, nullable: true })
  bidBondNumber?: string;

  @Column({ name: 'bid_bond_expiry', type: 'date', nullable: true })
  bidBondExpiry?: Date;

  // Asignación
  @Column({ name: 'bid_manager_id', type: 'uuid', nullable: true })
  bidManagerId?: string;

  @ManyToOne(() => User, { nullable: true })
  @JoinColumn({ name: 'bid_manager_id' })
  bidManager?: User;

  // Resultado
  @Column({ name: 'winner_name', length: 255, nullable: true })
  winnerName?: string;

  @Column({ name: 'rejection_reason', type: 'text', nullable: true })
  rejectionReason?: string;

  @Column({ name: 'lessons_learned', type: 'text', nullable: true })
  lessonsLearned?: string;

  // Progreso
  @Column({
    name: 'completion_percentage',
    type: 'decimal',
    precision: 5,
    scale: 2,
    default: 0,
  })
  completionPercentage!: number;

  // Checklist de documentos
  @Column({ name: 'checklist', type: 'jsonb', nullable: true })
  checklist?: Record<string, any>;

  // Notas y metadatos
  @Column({ type: 'text', nullable: true })
  notes?: string;

  @Column({ type: 'jsonb', nullable: true })
  metadata?: Record<string, any>;

  // Relaciones
  @OneToMany(() => BidDocument, (doc) => doc.bid)
  documents?: BidDocument[];

  @OneToMany(() => BidCalendar, (event) => event.bid)
  calendarEvents?: BidCalendar[];

  @OneToMany(() => BidBudget, (budget) => budget.bid)
  budgetItems?: BidBudget[];

  @OneToMany(() => BidCompetitor, (comp) => comp.bid)
  competitors?: BidCompetitor[];

  @OneToMany(() => BidTeam, (team) => team.bid)
  teamMembers?: BidTeam[];

  // Conversión a proyecto
  @Column({ name: 'converted_to_project_id', type: 'uuid', nullable: true })
  convertedToProjectId?: string;

  @Column({ name: 'converted_at', type: 'timestamptz', nullable: true })
  convertedAt?: Date;

  // Auditoría
  @Column({ name: 'created_by', type: 'uuid', nullable: true })
  createdBy?: string;

  @Column({ name: 'updated_by', type: 'uuid', nullable: true })
  updatedBy?: string;

  @CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
  createdAt!: Date;

  @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
  updatedAt!: Date;

  @Column({ name: 'deleted_at', type: 'timestamptz', nullable: true })
  deletedAt?: Date;
}
