/**
 * 对话状态常量
 */
export const ConversationStatus = {
  ACTIVE: 'ACTIVE',
  ENDED: 'ENDED',
  ARCHIVED: 'ARCHIVED',
  DELETED: 'DELETED',
} as const;

export type ConversationStatusType =
  (typeof ConversationStatus)[keyof typeof ConversationStatus];

/**
 * 咨询阶段常量
 */
export const ConsultingStage = {
  GREETING: 'greeting',
  NEEDS_DISCOVERY: 'needs_discovery',
  INFO_COLLECTION: 'info_collection',
  ASSESSMENT: 'assessment',
  RECOMMENDATION: 'recommendation',
  OBJECTION_HANDLING: 'objection_handling',
  CONVERSION: 'conversion',
  HANDOFF: 'handoff',
} as const;

export type ConsultingStageType =
  (typeof ConsultingStage)[keyof typeof ConsultingStage];

/**
 * 咨询状态结构（存储为JSON）
 */
export interface ConsultingStateJson {
  strategyId: string;
  currentStageId: string;
  stageTurnCount: number;
  collectedInfo: Record<string, unknown>;
  assessmentResult?: {
    recommendedPrograms: string[];
    suitabilityScore: number;
    highlights: string[];
    concerns: string[];
  };
  conversionPath?: string;
  stageHistory: Array<{
    stageId: string;
    enteredAt: string;
    exitedAt?: string;
    turnsInStage: number;
  }>;
}

/**
 * Device info structure
 */
export interface DeviceInfo {
  ip?: string;
  userAgent?: string;
  fingerprint?: string;
  region?: string;
}

/**
 * Conversation Domain Entity
 */
export class ConversationEntity {
  readonly id: string;
  userId: string;
  status: ConversationStatusType;
  title: string | null;
  summary: string | null;
  category: string | null;
  messageCount: number;
  userMessageCount: number;
  assistantMessageCount: number;
  totalInputTokens: number;
  totalOutputTokens: number;
  rating: number | null;
  feedback: string | null;
  hasConverted: boolean;
  consultingStage: ConsultingStageType | null;
  consultingState: ConsultingStateJson | null;
  collectedInfo: Record<string, unknown> | null;
  recommendedPrograms: string[] | null;
  conversionPath: string | null;
  deviceInfo: DeviceInfo | null;
  readonly createdAt: Date;
  updatedAt: Date;
  endedAt: Date | null;

  private constructor(props: {
    id: string;
    userId: string;
    status: ConversationStatusType;
    title: string | null;
    summary: string | null;
    category: string | null;
    messageCount: number;
    userMessageCount: number;
    assistantMessageCount: number;
    totalInputTokens: number;
    totalOutputTokens: number;
    rating: number | null;
    feedback: string | null;
    hasConverted: boolean;
    consultingStage: ConsultingStageType | null;
    consultingState: ConsultingStateJson | null;
    collectedInfo: Record<string, unknown> | null;
    recommendedPrograms: string[] | null;
    conversionPath: string | null;
    deviceInfo: DeviceInfo | null;
    createdAt: Date;
    updatedAt: Date;
    endedAt: Date | null;
  }) {
    Object.assign(this, props);
  }

  static create(props: {
    id: string;
    userId: string;
    title?: string;
    category?: string;
    deviceInfo?: DeviceInfo;
  }): ConversationEntity {
    const now = new Date();
    return new ConversationEntity({
      id: props.id,
      userId: props.userId,
      status: ConversationStatus.ACTIVE,
      title: props.title || null,
      summary: null,
      category: props.category || null,
      messageCount: 0,
      userMessageCount: 0,
      assistantMessageCount: 0,
      totalInputTokens: 0,
      totalOutputTokens: 0,
      rating: null,
      feedback: null,
      hasConverted: false,
      consultingStage: ConsultingStage.GREETING,
      consultingState: null,
      collectedInfo: null,
      recommendedPrograms: null,
      conversionPath: null,
      deviceInfo: props.deviceInfo || null,
      createdAt: now,
      updatedAt: now,
      endedAt: null,
    });
  }

  static fromPersistence(props: {
    id: string;
    userId: string;
    status: ConversationStatusType;
    title: string | null;
    summary: string | null;
    category: string | null;
    messageCount: number;
    userMessageCount: number;
    assistantMessageCount: number;
    totalInputTokens: number;
    totalOutputTokens: number;
    rating: number | null;
    feedback: string | null;
    hasConverted: boolean;
    consultingStage: ConsultingStageType | null;
    consultingState: ConsultingStateJson | null;
    collectedInfo: Record<string, unknown> | null;
    recommendedPrograms: string[] | null;
    conversionPath: string | null;
    deviceInfo: DeviceInfo | null;
    createdAt: Date;
    updatedAt: Date;
    endedAt: Date | null;
  }): ConversationEntity {
    return new ConversationEntity(props);
  }

  incrementMessageCount(role: 'user' | 'assistant'): void {
    this.messageCount++;
    if (role === 'user') {
      this.userMessageCount++;
    } else {
      this.assistantMessageCount++;
    }
    this.updatedAt = new Date();
  }

  addTokens(inputTokens: number, outputTokens: number): void {
    this.totalInputTokens += inputTokens;
    this.totalOutputTokens += outputTokens;
    this.updatedAt = new Date();
  }

  updateConsultingStage(stage: ConsultingStageType): void {
    this.consultingStage = stage;
    this.updatedAt = new Date();
  }

  updateConsultingState(state: ConsultingStateJson): void {
    this.consultingState = state;
    this.collectedInfo = state.collectedInfo;
    if (state.assessmentResult?.recommendedPrograms) {
      this.recommendedPrograms = state.assessmentResult.recommendedPrograms;
    }
    if (state.conversionPath) {
      this.conversionPath = state.conversionPath;
    }
    this.updatedAt = new Date();
  }

  setRating(rating: number, feedback?: string): void {
    this.rating = rating;
    if (feedback) {
      this.feedback = feedback;
    }
    this.updatedAt = new Date();
  }

  markAsConverted(): void {
    this.hasConverted = true;
    this.updatedAt = new Date();
  }

  end(): void {
    this.status = ConversationStatus.ENDED;
    this.endedAt = new Date();
    this.updatedAt = new Date();
  }

  archive(): void {
    this.status = ConversationStatus.ARCHIVED;
    this.updatedAt = new Date();
  }

  softDelete(): void {
    this.status = ConversationStatus.DELETED;
    this.updatedAt = new Date();
  }

  isActive(): boolean {
    return this.status === ConversationStatus.ACTIVE;
  }

  isEnded(): boolean {
    return this.status === ConversationStatus.ENDED;
  }

  isDeleted(): boolean {
    return this.status === ConversationStatus.DELETED;
  }
}
