export enum PaymentMethod {
  ALIPAY = 'ALIPAY',
  WECHAT = 'WECHAT',
  CREDIT_CARD = 'CREDIT_CARD',
}

export enum PaymentStatus {
  PENDING = 'PENDING',
  PROCESSING = 'PROCESSING',
  COMPLETED = 'COMPLETED',
  FAILED = 'FAILED',
  REFUNDED = 'REFUNDED',
  CANCELLED = 'CANCELLED',
}

/**
 * Payment Domain Entity
 */
export class PaymentEntity {
  readonly id: string;
  readonly orderId: string;
  readonly method: PaymentMethod;
  readonly amount: number;
  readonly currency: string;
  status: PaymentStatus;
  transactionId: string | null;
  qrCodeUrl: string | null;
  paymentUrl: string | null;
  readonly expiresAt: Date;
  paidAt: Date | null;
  failedReason: string | null;
  callbackPayload: Record<string, unknown> | null;
  readonly createdAt: Date;
  updatedAt: Date;

  private constructor(props: {
    id: string;
    orderId: string;
    method: PaymentMethod;
    amount: number;
    currency: string;
    status: PaymentStatus;
    transactionId: string | null;
    qrCodeUrl: string | null;
    paymentUrl: string | null;
    expiresAt: Date;
    paidAt: Date | null;
    failedReason: string | null;
    callbackPayload: Record<string, unknown> | null;
    createdAt: Date;
    updatedAt: Date;
  }) {
    Object.assign(this, props);
  }

  static create(props: {
    orderId: string;
    method: PaymentMethod;
    amount: number;
    currency?: string;
    qrCodeUrl?: string;
    paymentUrl?: string;
    expirationMinutes?: number;
  }): PaymentEntity {
    const now = new Date();
    return new PaymentEntity({
      id: crypto.randomUUID(),
      orderId: props.orderId,
      method: props.method,
      amount: props.amount,
      currency: props.currency || 'CNY',
      status: PaymentStatus.PENDING,
      transactionId: null,
      qrCodeUrl: props.qrCodeUrl || null,
      paymentUrl: props.paymentUrl || null,
      expiresAt: new Date(now.getTime() + (props.expirationMinutes || 30) * 60 * 1000),
      paidAt: null,
      failedReason: null,
      callbackPayload: null,
      createdAt: now,
      updatedAt: now,
    });
  }

  static fromPersistence(props: {
    id: string;
    orderId: string;
    method: string;
    amount: number;
    currency: string;
    status: string;
    transactionId: string | null;
    qrCodeUrl: string | null;
    paymentUrl: string | null;
    expiresAt: Date;
    paidAt: Date | null;
    failedReason: string | null;
    callbackPayload: Record<string, unknown> | null;
    createdAt: Date;
    updatedAt: Date;
  }): PaymentEntity {
    return new PaymentEntity({
      ...props,
      method: props.method as PaymentMethod,
      status: props.status as PaymentStatus,
    });
  }

  markAsCompleted(transactionId: string, callbackPayload: Record<string, unknown>): void {
    this.status = PaymentStatus.COMPLETED;
    this.transactionId = transactionId;
    this.callbackPayload = callbackPayload;
    this.paidAt = new Date();
    this.updatedAt = new Date();
  }

  markAsFailed(reason: string, callbackPayload: Record<string, unknown>): void {
    this.status = PaymentStatus.FAILED;
    this.failedReason = reason;
    this.callbackPayload = callbackPayload;
    this.updatedAt = new Date();
  }

  isExpired(): boolean {
    return this.expiresAt < new Date();
  }

  isPending(): boolean {
    return this.status === PaymentStatus.PENDING;
  }
}
