import Decimal from 'decimal.js';
import { UserId, Money } from '@/domain/value-objects';
import { FiatWithdrawalStatus, PaymentMethod } from '@/domain/value-objects/fiat-withdrawal-status.enum';
import { DomainError } from '@/shared/exceptions/domain.exception';

/**
 * 收款账户信息
 */
export interface PaymentAccountInfo {
  paymentMethod: PaymentMethod;
  // 银行卡
  bankName?: string;
  bankCardNo?: string;
  cardHolderName?: string;
  // 支付宝
  alipayAccount?: string;
  alipayRealName?: string;
  // 微信
  wechatAccount?: string;
  wechatRealName?: string;
}

/**
 * 审核信息
 */
export interface ReviewInfo {
  reviewedBy: string;
  reviewedAt: Date;
  reviewRemark?: string;
}

/**
 * 打款信息
 */
export interface PaymentInfo {
  paidBy: string;
  paidAt: Date;
  paymentProof?: string;
  paymentRemark?: string;
}

/**
 * 法币提现订单聚合根
 *
 * 提现流程:
 * 1. 用户发起提现请求 -> PENDING
 * 2. 冻结用户余额 -> FROZEN
 * 3. 提交审核 -> REVIEWING
 * 4. 审核通过 -> APPROVED (等待打款)
 *    审核驳回 -> REJECTED (资金解冻)
 * 5. 开始打款 -> PAYING
 * 6. 打款完成 -> COMPLETED
 *
 * 失败/取消时解冻资金
 */
export class FiatWithdrawalOrder {
  private readonly _id: bigint;
  private readonly _orderNo: string;
  private readonly _accountSequence: string;
  private readonly _userId: UserId;
  private readonly _amount: Money;           // 提现金额 (绿积分, 1:1人民币)
  private readonly _fee: Money;              // 手续费

  // 收款方式
  private readonly _paymentMethod: PaymentMethod;
  // 银行卡信息
  private readonly _bankName: string | null;
  private readonly _bankCardNo: string | null;
  private readonly _cardHolderName: string | null;
  // 支付宝信息
  private readonly _alipayAccount: string | null;
  private readonly _alipayRealName: string | null;
  // 微信信息
  private readonly _wechatAccount: string | null;
  private readonly _wechatRealName: string | null;

  // 状态
  private _status: FiatWithdrawalStatus;
  private _errorMessage: string | null;

  // 审核信息
  private _reviewedBy: string | null;
  private _reviewedAt: Date | null;
  private _reviewRemark: string | null;

  // 打款信息
  private _paidBy: string | null;
  private _paidAt: Date | null;
  private _paymentProof: string | null;
  private _paymentRemark: string | null;

  // 详细备注
  private _detailMemo: string | null;

  // 时间戳
  private _frozenAt: Date | null;
  private _completedAt: Date | null;
  private readonly _createdAt: Date;

  private constructor(
    id: bigint,
    orderNo: string,
    accountSequence: string,
    userId: UserId,
    amount: Money,
    fee: Money,
    paymentMethod: PaymentMethod,
    bankName: string | null,
    bankCardNo: string | null,
    cardHolderName: string | null,
    alipayAccount: string | null,
    alipayRealName: string | null,
    wechatAccount: string | null,
    wechatRealName: string | null,
    status: FiatWithdrawalStatus,
    errorMessage: string | null,
    reviewedBy: string | null,
    reviewedAt: Date | null,
    reviewRemark: string | null,
    paidBy: string | null,
    paidAt: Date | null,
    paymentProof: string | null,
    paymentRemark: string | null,
    detailMemo: string | null,
    frozenAt: Date | null,
    completedAt: Date | null,
    createdAt: Date,
  ) {
    this._id = id;
    this._orderNo = orderNo;
    this._accountSequence = accountSequence;
    this._userId = userId;
    this._amount = amount;
    this._fee = fee;
    this._paymentMethod = paymentMethod;
    this._bankName = bankName;
    this._bankCardNo = bankCardNo;
    this._cardHolderName = cardHolderName;
    this._alipayAccount = alipayAccount;
    this._alipayRealName = alipayRealName;
    this._wechatAccount = wechatAccount;
    this._wechatRealName = wechatRealName;
    this._status = status;
    this._errorMessage = errorMessage;
    this._reviewedBy = reviewedBy;
    this._reviewedAt = reviewedAt;
    this._reviewRemark = reviewRemark;
    this._paidBy = paidBy;
    this._paidAt = paidAt;
    this._paymentProof = paymentProof;
    this._paymentRemark = paymentRemark;
    this._detailMemo = detailMemo;
    this._frozenAt = frozenAt;
    this._completedAt = completedAt;
    this._createdAt = createdAt;
  }

  // Getters
  get id(): bigint { return this._id; }
  get orderNo(): string { return this._orderNo; }
  get accountSequence(): string { return this._accountSequence; }
  get userId(): UserId { return this._userId; }
  get amount(): Money { return this._amount; }
  get fee(): Money { return this._fee; }
  get netAmount(): Money { return Money.USDT(new Decimal(this._amount.value).minus(this._fee.value)); }
  get paymentMethod(): PaymentMethod { return this._paymentMethod; }
  get bankName(): string | null { return this._bankName; }
  get bankCardNo(): string | null { return this._bankCardNo; }
  get cardHolderName(): string | null { return this._cardHolderName; }
  get alipayAccount(): string | null { return this._alipayAccount; }
  get alipayRealName(): string | null { return this._alipayRealName; }
  get wechatAccount(): string | null { return this._wechatAccount; }
  get wechatRealName(): string | null { return this._wechatRealName; }
  get status(): FiatWithdrawalStatus { return this._status; }
  get errorMessage(): string | null { return this._errorMessage; }
  get reviewedBy(): string | null { return this._reviewedBy; }
  get reviewedAt(): Date | null { return this._reviewedAt; }
  get reviewRemark(): string | null { return this._reviewRemark; }
  get paidBy(): string | null { return this._paidBy; }
  get paidAt(): Date | null { return this._paidAt; }
  get paymentProof(): string | null { return this._paymentProof; }
  get paymentRemark(): string | null { return this._paymentRemark; }
  get detailMemo(): string | null { return this._detailMemo; }
  get frozenAt(): Date | null { return this._frozenAt; }
  get completedAt(): Date | null { return this._completedAt; }
  get createdAt(): Date { return this._createdAt; }

  // 状态判断
  get isPending(): boolean { return this._status === FiatWithdrawalStatus.PENDING; }
  get isFrozen(): boolean { return this._status === FiatWithdrawalStatus.FROZEN; }
  get isReviewing(): boolean { return this._status === FiatWithdrawalStatus.REVIEWING; }
  get isApproved(): boolean { return this._status === FiatWithdrawalStatus.APPROVED; }
  get isPaying(): boolean { return this._status === FiatWithdrawalStatus.PAYING; }
  get isCompleted(): boolean { return this._status === FiatWithdrawalStatus.COMPLETED; }
  get isRejected(): boolean { return this._status === FiatWithdrawalStatus.REJECTED; }
  get isFailed(): boolean { return this._status === FiatWithdrawalStatus.FAILED; }
  get isCancelled(): boolean { return this._status === FiatWithdrawalStatus.CANCELLED; }
  get isFinished(): boolean {
    return this._status === FiatWithdrawalStatus.COMPLETED ||
           this._status === FiatWithdrawalStatus.REJECTED ||
           this._status === FiatWithdrawalStatus.FAILED ||
           this._status === FiatWithdrawalStatus.CANCELLED;
  }

  /**
   * 生成提现订单号
   */
  private static generateOrderNo(): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substring(2, 8).toUpperCase();
    return `FW${timestamp}${random}`;
  }

  /**
   * 获取收款账户显示信息
   */
  getPaymentAccountDisplay(): string {
    switch (this._paymentMethod) {
      case PaymentMethod.BANK_CARD:
        const maskedCardNo = this._bankCardNo
          ? `****${this._bankCardNo.slice(-4)}`
          : '';
        return `${this._bankName || ''} ${maskedCardNo} (${this._cardHolderName || ''})`;
      case PaymentMethod.ALIPAY:
        return `支付宝: ${this._alipayAccount || ''} (${this._alipayRealName || ''})`;
      case PaymentMethod.WECHAT:
        return `微信: ${this._wechatAccount || ''} (${this._wechatRealName || ''})`;
      default:
        return '未知收款方式';
    }
  }

  /**
   * 获取收款方式中文名称
   */
  getPaymentMethodName(): string {
    switch (this._paymentMethod) {
      case PaymentMethod.BANK_CARD:
        return '银行卡';
      case PaymentMethod.ALIPAY:
        return '支付宝';
      case PaymentMethod.WECHAT:
        return '微信';
      default:
        return '未知';
    }
  }

  /**
   * 创建法币提现订单
   */
  static create(params: {
    accountSequence: string;
    userId: UserId;
    amount: Money;
    fee: Money;
    paymentAccount: PaymentAccountInfo;
  }): FiatWithdrawalOrder {
    // 验证金额
    if (params.amount.value <= 0) {
      throw new DomainError('提现金额必须大于0');
    }

    // 验证手续费
    if (params.fee.value < 0) {
      throw new DomainError('手续费不能为负数');
    }

    // 验证净额大于0
    const netAmount = new Decimal(params.amount.value).minus(params.fee.value);
    if (netAmount.lte(0)) {
      throw new DomainError('提现金额必须大于手续费');
    }

    // 根据收款方式验证必填信息
    const { paymentAccount } = params;
    switch (paymentAccount.paymentMethod) {
      case PaymentMethod.BANK_CARD:
        if (!paymentAccount.bankName || !paymentAccount.bankCardNo || !paymentAccount.cardHolderName) {
          throw new DomainError('银行卡信息不完整');
        }
        break;
      case PaymentMethod.ALIPAY:
        if (!paymentAccount.alipayAccount || !paymentAccount.alipayRealName) {
          throw new DomainError('支付宝信息不完整');
        }
        break;
      case PaymentMethod.WECHAT:
        if (!paymentAccount.wechatAccount || !paymentAccount.wechatRealName) {
          throw new DomainError('微信信息不完整');
        }
        break;
      default:
        throw new DomainError('不支持的收款方式');
    }

    const now = new Date();
    const orderNo = this.generateOrderNo();

    // 构建初始备注
    const detailMemo = [
      `[${now.toLocaleString('zh-CN')}] 用户发起提现申请`,
      `  订单号: ${orderNo}`,
      `  提现金额: ${params.amount.value} 绿积分`,
      `  手续费: ${params.fee.value} 绿积分`,
      `  实际到账: ${netAmount.toFixed(2)} 元人民币`,
      `  收款方式: ${paymentAccount.paymentMethod === PaymentMethod.BANK_CARD ? '银行卡' :
                    paymentAccount.paymentMethod === PaymentMethod.ALIPAY ? '支付宝' : '微信'}`,
    ].join('\n');

    return new FiatWithdrawalOrder(
      BigInt(0), // Will be set by database
      orderNo,
      params.accountSequence,
      params.userId,
      params.amount,
      params.fee,
      paymentAccount.paymentMethod,
      paymentAccount.bankName || null,
      paymentAccount.bankCardNo || null,
      paymentAccount.cardHolderName || null,
      paymentAccount.alipayAccount || null,
      paymentAccount.alipayRealName || null,
      paymentAccount.wechatAccount || null,
      paymentAccount.wechatRealName || null,
      FiatWithdrawalStatus.PENDING,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      detailMemo,
      null,
      null,
      now,
    );
  }

  /**
   * 从数据库重建
   */
  static reconstruct(params: {
    id: bigint;
    orderNo: string;
    accountSequence: string;
    userId: bigint;
    amount: Decimal;
    fee: Decimal;
    paymentMethod: string;
    bankName?: string | null;
    bankCardNo?: string | null;
    cardHolderName?: string | null;
    alipayAccount?: string | null;
    alipayRealName?: string | null;
    wechatAccount?: string | null;
    wechatRealName?: string | null;
    status: string;
    errorMessage?: string | null;
    reviewedBy?: string | null;
    reviewedAt?: Date | null;
    reviewRemark?: string | null;
    paidBy?: string | null;
    paidAt?: Date | null;
    paymentProof?: string | null;
    paymentRemark?: string | null;
    detailMemo?: string | null;
    frozenAt?: Date | null;
    completedAt?: Date | null;
    createdAt: Date;
  }): FiatWithdrawalOrder {
    return new FiatWithdrawalOrder(
      params.id,
      params.orderNo,
      params.accountSequence,
      UserId.create(params.userId),
      Money.USDT(params.amount),
      Money.USDT(params.fee),
      params.paymentMethod as PaymentMethod,
      params.bankName || null,
      params.bankCardNo || null,
      params.cardHolderName || null,
      params.alipayAccount || null,
      params.alipayRealName || null,
      params.wechatAccount || null,
      params.wechatRealName || null,
      params.status as FiatWithdrawalStatus,
      params.errorMessage || null,
      params.reviewedBy || null,
      params.reviewedAt || null,
      params.reviewRemark || null,
      params.paidBy || null,
      params.paidAt || null,
      params.paymentProof || null,
      params.paymentRemark || null,
      params.detailMemo || null,
      params.frozenAt || null,
      params.completedAt || null,
      params.createdAt,
    );
  }

  /**
   * 添加备注
   */
  private appendMemo(message: string): void {
    const now = new Date();
    const newLine = `[${now.toLocaleString('zh-CN')}] ${message}`;
    this._detailMemo = this._detailMemo
      ? `${this._detailMemo}\n${newLine}`
      : newLine;
  }

  /**
   * 标记为已冻结 (资金已从可用余额冻结)
   */
  markAsFrozen(): void {
    if (this._status !== FiatWithdrawalStatus.PENDING) {
      throw new DomainError('只有待处理的提现订单可以冻结资金');
    }
    this._status = FiatWithdrawalStatus.FROZEN;
    this._frozenAt = new Date();
    this.appendMemo('资金已冻结，等待审核');
  }

  /**
   * 提交审核
   */
  submitForReview(): void {
    if (this._status !== FiatWithdrawalStatus.FROZEN) {
      throw new DomainError('只有已冻结的提现订单可以提交审核');
    }
    this._status = FiatWithdrawalStatus.REVIEWING;
    this.appendMemo('已提交审核');
  }

  /**
   * 审核通过
   */
  approve(reviewedBy: string, remark?: string): void {
    if (this._status !== FiatWithdrawalStatus.REVIEWING && this._status !== FiatWithdrawalStatus.FROZEN) {
      throw new DomainError('只有审核中或已冻结的订单可以通过审核');
    }
    this._status = FiatWithdrawalStatus.APPROVED;
    this._reviewedBy = reviewedBy;
    this._reviewedAt = new Date();
    this._reviewRemark = remark || null;
    this.appendMemo(`审核通过 - 审核人: ${reviewedBy}${remark ? `, 备注: ${remark}` : ''}`);
  }

  /**
   * 审核驳回
   */
  reject(reviewedBy: string, remark: string): void {
    if (this._status !== FiatWithdrawalStatus.REVIEWING && this._status !== FiatWithdrawalStatus.FROZEN) {
      throw new DomainError('只有审核中或已冻结的订单可以驳回');
    }
    this._status = FiatWithdrawalStatus.REJECTED;
    this._reviewedBy = reviewedBy;
    this._reviewedAt = new Date();
    this._reviewRemark = remark;
    this.appendMemo(`审核驳回 - 审核人: ${reviewedBy}, 原因: ${remark}`);
  }

  /**
   * 开始打款
   */
  startPayment(paidBy: string): void {
    if (this._status !== FiatWithdrawalStatus.APPROVED) {
      throw new DomainError('只有审核通过的订单可以开始打款');
    }
    this._status = FiatWithdrawalStatus.PAYING;
    this._paidBy = paidBy;
    this.appendMemo(`开始打款 - 操作人: ${paidBy}`);
  }

  /**
   * 完成打款
   */
  completePayment(paymentProof?: string, remark?: string): void {
    if (this._status !== FiatWithdrawalStatus.PAYING) {
      throw new DomainError('只有打款中的订单可以完成打款');
    }
    this._status = FiatWithdrawalStatus.COMPLETED;
    this._paidAt = new Date();
    this._completedAt = new Date();
    this._paymentProof = paymentProof || null;
    this._paymentRemark = remark || null;

    const proofInfo = paymentProof ? `, 凭证: ${paymentProof}` : '';
    const remarkInfo = remark ? `, 备注: ${remark}` : '';
    this.appendMemo(`打款完成${proofInfo}${remarkInfo}`);
    this.appendMemo(`  收款账户: ${this.getPaymentAccountDisplay()}`);
    this.appendMemo(`  到账金额: ${this.netAmount.value.toFixed(2)} 元人民币`);
  }

  /**
   * 标记为失败
   */
  markAsFailed(errorMessage: string): void {
    if (this.isFinished) {
      throw new DomainError('已完成的提现订单无法标记为失败');
    }
    this._status = FiatWithdrawalStatus.FAILED;
    this._errorMessage = errorMessage;
    this.appendMemo(`提现失败 - 原因: ${errorMessage}`);
  }

  /**
   * 取消提现
   */
  cancel(reason?: string): void {
    if (this._status !== FiatWithdrawalStatus.PENDING && this._status !== FiatWithdrawalStatus.FROZEN) {
      throw new DomainError('只有待处理或已冻结的提现订单可以取消');
    }
    this._status = FiatWithdrawalStatus.CANCELLED;
    this.appendMemo(`用户取消提现${reason ? ` - 原因: ${reason}` : ''}`);
  }

  /**
   * 是否需要解冻资金 (驳回/失败/取消且已冻结)
   */
  needsUnfreeze(): boolean {
    return (this._status === FiatWithdrawalStatus.REJECTED ||
            this._status === FiatWithdrawalStatus.FAILED ||
            this._status === FiatWithdrawalStatus.CANCELLED)
           && this._frozenAt !== null;
  }
}
