import { AggregateRoot, ValidationException } from '@modules/shared';
import { LeadCreatedEvent } from '../events/lead-created.event';
import { LeadStatusChangedEvent } from '../events/lead-status-changed.event';
import { type LeadScore } from '../value-objects/lead-score.vo';

export type LeadStatus = 'NEW' | 'CONTACTED' | 'QUALIFIED' | 'NEGOTIATING' | 'CONVERTED' | 'LOST';

const VALID_TRANSITIONS: Record<LeadStatus, LeadStatus[]> = {
  NEW: ['CONTACTED', 'LOST'],
  CONTACTED: ['QUALIFIED', 'LOST'],
  QUALIFIED: ['NEGOTIATING', 'LOST'],
  NEGOTIATING: ['CONVERTED', 'LOST'],
  CONVERTED: [],
  LOST: [],
};

export interface LeadProps {
  agentId: string;
  name: string;
  phone: string;
  email: string | null;
  source: string;
  score: LeadScore | null;
  notes: unknown;
  status: LeadStatus;
}

export class LeadEntity extends AggregateRoot<string> {
  private _agentId: string;
  private _name: string;
  private _phone: string;
  private _email: string | null;
  private _source: string;
  private _score: LeadScore | null;
  private _notes: unknown;
  private _status: LeadStatus;

  constructor(id: string, props: LeadProps, createdAt?: Date, updatedAt?: Date) {
    super(id, createdAt);
    if (updatedAt) this.updatedAt = updatedAt;
    this._agentId = props.agentId;
    this._name = props.name;
    this._phone = props.phone;
    this._email = props.email;
    this._source = props.source;
    this._score = props.score;
    this._notes = props.notes;
    this._status = props.status;
  }

  get agentId(): string { return this._agentId; }
  get name(): string { return this._name; }
  get phone(): string { return this._phone; }
  get email(): string | null { return this._email; }
  get source(): string { return this._source; }
  get score(): LeadScore | null { return this._score; }
  get notes(): unknown { return this._notes; }
  get status(): LeadStatus { return this._status; }

  static createNew(
    id: string,
    agentId: string,
    name: string,
    phone: string,
    email: string | null,
    source: string,
    score: LeadScore | null,
    notes: unknown,
  ): LeadEntity {
    const lead = new LeadEntity(id, {
      agentId,
      name,
      phone,
      email,
      source,
      score,
      notes,
      status: 'NEW',
    });

    lead.addDomainEvent(new LeadCreatedEvent(id, agentId));
    return lead;
  }

  updateStatus(newStatus: LeadStatus): void {
    const allowed = VALID_TRANSITIONS[this._status];
    if (!allowed.includes(newStatus)) {
      throw new ValidationException(
        `Không thể chuyển trạng thái từ ${this._status} sang ${newStatus}`,
      );
    }

    const oldStatus = this._status;
    this._status = newStatus;
    this.updatedAt = new Date();

    this.addDomainEvent(
      new LeadStatusChangedEvent(this.id, this._agentId, oldStatus, newStatus),
    );
  }
}
