import { Injectable, Logger, BadRequestException, NotFoundException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TradingAccountRepository } from '../../infrastructure/persistence/repositories/trading-account.repository';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { TradingAccountAggregate } from '../../domain/aggregates/trading-account.aggregate';
import { Money } from '../../domain/value-objects/money.vo';

interface RecipientInfo {
  exists: boolean;
  accountSequence?: string;
  nickname?: string;
}

interface P2pFeeConfig {
  fee: number;
  minTransferAmount: number;
}

export interface P2pTransferResult {
  transferNo: string;
  amount: string;
  fee: string;
  toPhone: string;
  toNickname?: string;
  status: string;
  createdAt: Date;
}

export interface P2pTransferHistoryItem {
  transferNo: string;
  fromAccountSequence: string;
  fromPhone?: string | null;
  fromNickname?: string | null;
  toAccountSequence: string;
  toPhone: string;
  toNickname?: string | null;
  amount: string;
  fee?: string;
  memo?: string | null;
  status: string;
  createdAt: Date;
}

/** 系统成本费账户序列号 */
const FEE_ACCOUNT_SEQUENCE = 'S0000000002';

@Injectable()
export class P2pTransferService {
  private readonly logger = new Logger(P2pTransferService.name);
  private readonly authServiceUrl: string;
  private readonly miningAdminServiceUrl: string;

  constructor(
    private readonly accountRepository: TradingAccountRepository,
    private readonly prisma: PrismaService,
    private readonly configService: ConfigService,
  ) {
    this.authServiceUrl = this.configService.get<string>('AUTH_SERVICE_URL', 'http://auth-service:3024');
    this.miningAdminServiceUrl = this.configService.get<string>(
      'MINING_ADMIN_SERVICE_URL', 'http://mining-admin-service:3023',
    );
  }

  /**
   * 获取P2P手续费配置（从 mining-admin-service 动态读取）
   */
  private async getP2pFeeConfig(): Promise<P2pFeeConfig> {
    try {
      const response = await fetch(
        `${this.miningAdminServiceUrl}/api/v2/configs/internal/p2p-transfer-fee`,
      );
      if (!response.ok) {
        this.logger.warn('Failed to fetch P2P fee config, using defaults');
        return { fee: 5, minTransferAmount: 6 };
      }
      const result = await response.json();
      const data = result.data || result;
      return {
        fee: parseFloat(data.fee) || 5,
        minTransferAmount: parseFloat(data.minTransferAmount) || 6,
      };
    } catch (error: any) {
      this.logger.warn(`Failed to fetch P2P fee config: ${error.message}`);
      return { fee: 5, minTransferAmount: 6 };
    }
  }

  /**
   * 获取P2P手续费配置（供 Controller 暴露给前端）
   */
  async getP2pFeeConfigPublic(): Promise<{ fee: string; minTransferAmount: string }> {
    const config = await this.getP2pFeeConfig();
    return {
      fee: config.fee.toString(),
      minTransferAmount: config.minTransferAmount.toString(),
    };
  }

  /**
   * 查找收款方
   */
  async lookupRecipient(phone: string, token: string): Promise<RecipientInfo> {
    try {
      const response = await fetch(`${this.authServiceUrl}/api/v2/auth/user/lookup?phone=${phone}`, {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        return { exists: false };
      }

      const result = await response.json();
      if (!result.success || !result.data) {
        return { exists: false };
      }

      return result.data;
    } catch (error: any) {
      this.logger.warn(`Failed to lookup recipient: ${error.message}`);
      return { exists: false };
    }
  }

  /**
   * P2P转账（积分值）— 含手续费扣除
   */
  async transfer(
    fromAccountSequence: string,
    toPhone: string,
    amount: string,
    memo?: string,
    token?: string,
  ): Promise<P2pTransferResult> {
    const transferAmount = new Money(amount);

    // 获取动态手续费配置
    const feeConfig = await this.getP2pFeeConfig();
    const feeAmount = new Money(feeConfig.fee.toString());

    // 验证最小转账金额
    if (transferAmount.value.lessThan(feeConfig.minTransferAmount)) {
      throw new BadRequestException(`最小转账金额为 ${feeConfig.minTransferAmount} 积分值`);
    }

    // 查找收款方
    const recipient = await this.lookupRecipient(toPhone, token || '');
    if (!recipient.exists || !recipient.accountSequence) {
      throw new NotFoundException('收款方账户不存在');
    }

    // 不能转给自己
    if (recipient.accountSequence === fromAccountSequence) {
      throw new BadRequestException('不能转账给自己');
    }

    // 查找发送方账户
    const fromAccount = await this.accountRepository.findByAccountSequence(fromAccountSequence);
    if (!fromAccount) {
      throw new NotFoundException('发送方账户不存在');
    }

    // 计算总扣除金额 = 转账金额 + 手续费
    const totalDeduction = transferAmount.add(feeAmount);

    // 检查余额（需覆盖手续费）
    if (fromAccount.availableCash.isLessThan(totalDeduction)) {
      throw new BadRequestException(
        `可用积分值不足（需要 ${totalDeduction.toFixed(2)}，含手续费 ${feeAmount.toFixed(2)}）`,
      );
    }

    const transferNo = this.generateTransferNo();

    // 使用事务执行转账
    try {
      await this.prisma.$transaction(async (tx) => {
        // 1. 创建转账记录
        await tx.p2pTransfer.create({
          data: {
            transferNo,
            fromAccountSequence,
            toAccountSequence: recipient.accountSequence!,
            toPhone,
            toNickname: recipient.nickname,
            amount: transferAmount.value,
            fee: feeAmount.value,
            memo,
            status: 'PENDING',
          },
        });

        // 2. 扣减发送方余额（转账金额 + 手续费）
        fromAccount.withdraw(totalDeduction, transferNo);

        // 保存发送方账户变动
        await tx.tradingAccount.update({
          where: { accountSequence: fromAccountSequence },
          data: {
            cashBalance: fromAccount.cashBalance.value,
          },
        });

        // 手动写入发送方交易流水（拆分为转账和手续费两条记录）
        const balanceBeforeTransfer = fromAccount.cashBalance.add(totalDeduction);
        const balanceAfterTransfer = balanceBeforeTransfer.subtract(transferAmount);

        // 流水1: 转账金额
        await tx.tradingTransaction.create({
          data: {
            accountSequence: fromAccountSequence,
            type: 'WITHDRAW',
            assetType: 'CASH',
            amount: transferAmount.value,
            balanceBefore: balanceBeforeTransfer.value,
            balanceAfter: balanceAfterTransfer.value,
            referenceId: transferNo,
            referenceType: 'P2P_TRANSFER',
            counterpartyType: 'USER',
            counterpartyAccountSeq: recipient.accountSequence,
            memo: `P2P转出给 ${toPhone}`,
          },
        });

        // 流水2: 手续费（仅当手续费 > 0）
        if (!feeAmount.isZero()) {
          await tx.tradingTransaction.create({
            data: {
              accountSequence: fromAccountSequence,
              type: 'WITHDRAW',
              assetType: 'CASH',
              amount: feeAmount.value,
              balanceBefore: balanceAfterTransfer.value,
              balanceAfter: fromAccount.cashBalance.value,
              referenceId: transferNo,
              referenceType: 'P2P_TRANSFER_FEE',
              counterpartyType: 'SYSTEM',
              memo: 'P2P转账手续费',
            },
          });
        }

        fromAccount.clearPendingTransactions();

        // 3. 增加收款方余额（仅转账金额，不含手续费）
        let toAccount = await this.accountRepository.findByAccountSequence(recipient.accountSequence!);
        if (!toAccount) {
          toAccount = TradingAccountAggregate.create(recipient.accountSequence!);
          // 创建新账户
          await tx.tradingAccount.create({
            data: {
              accountSequence: recipient.accountSequence!,
              shareBalance: 0,
              cashBalance: 0,
              frozenShares: 0,
              frozenCash: 0,
              totalBought: 0,
              totalSold: 0,
            },
          });
        }

        toAccount.deposit(transferAmount, transferNo);

        // 保存收款方账户变动
        await tx.tradingAccount.update({
          where: { accountSequence: recipient.accountSequence! },
          data: {
            cashBalance: toAccount.cashBalance.value,
          },
        });

        // 记录收款方交易流水
        for (const txn of toAccount.pendingTransactions) {
          await tx.tradingTransaction.create({
            data: {
              accountSequence: recipient.accountSequence!,
              type: txn.type,
              assetType: txn.assetType,
              amount: txn.amount.value,
              balanceBefore: txn.balanceBefore.value,
              balanceAfter: txn.balanceAfter.value,
              referenceId: transferNo,
              referenceType: 'P2P_TRANSFER',
              counterpartyType: 'USER',
              counterpartyAccountSeq: fromAccountSequence,
              memo: `P2P转入来自 ${fromAccountSequence}`,
            },
          });
        }

        // 4. 手续费存入系统成本费账户（仅当手续费 > 0）
        if (!feeAmount.isZero()) {
          let feeAccount = await this.accountRepository.findByAccountSequence(FEE_ACCOUNT_SEQUENCE);
          if (feeAccount) {
            feeAccount.deposit(feeAmount, transferNo);

            await tx.tradingAccount.update({
              where: { accountSequence: FEE_ACCOUNT_SEQUENCE },
              data: {
                cashBalance: feeAccount.cashBalance.value,
              },
            });

            for (const txn of feeAccount.pendingTransactions) {
              await tx.tradingTransaction.create({
                data: {
                  accountSequence: FEE_ACCOUNT_SEQUENCE,
                  type: txn.type,
                  assetType: txn.assetType,
                  amount: txn.amount.value,
                  balanceBefore: txn.balanceBefore.value,
                  balanceAfter: txn.balanceAfter.value,
                  referenceId: transferNo,
                  referenceType: 'P2P_TRANSFER_FEE',
                  counterpartyType: 'USER',
                  counterpartyAccountSeq: fromAccountSequence,
                  memo: 'P2P转账手续费收入',
                },
              });
            }
          } else {
            this.logger.warn(`Fee account ${FEE_ACCOUNT_SEQUENCE} not found, fee not deposited`);
          }
        }

        // 5. 更新转账记录为完成
        await tx.p2pTransfer.update({
          where: { transferNo },
          data: {
            status: 'COMPLETED',
            completedAt: new Date(),
          },
        });
      });

      this.logger.log(
        `P2P transfer completed: ${transferNo}, ${fromAccountSequence} -> ${toPhone}, amount=${amount}, fee=${feeAmount.toFixed(8)}`,
      );

      return {
        transferNo,
        amount,
        fee: feeAmount.toFixed(8),
        toPhone,
        toNickname: recipient.nickname,
        status: 'COMPLETED',
        createdAt: new Date(),
      };
    } catch (error: any) {
      // 更新转账记录为失败
      await this.prisma.p2pTransfer.update({
        where: { transferNo },
        data: {
          status: 'FAILED',
          errorMessage: error.message,
        },
      }).catch(() => {});

      this.logger.error(`P2P transfer failed: ${transferNo}, ${error.message}`);
      throw error;
    }
  }

  /**
   * 获取P2P转账历史
   */
  async getTransferHistory(
    accountSequence: string,
    page: number = 1,
    pageSize: number = 20,
  ): Promise<{ data: P2pTransferHistoryItem[]; total: number }> {
    // 确保 page 和 pageSize 是有效数字
    const validPage = Math.max(1, Number(page) || 1);
    const validPageSize = Math.max(1, Math.min(100, Number(pageSize) || 20));

    const [records, total] = await Promise.all([
      this.prisma.p2pTransfer.findMany({
        where: {
          OR: [
            { fromAccountSequence: accountSequence },
            { toAccountSequence: accountSequence },
          ],
        },
        orderBy: { createdAt: 'desc' },
        skip: (validPage - 1) * validPageSize,
        take: validPageSize,
      }),
      this.prisma.p2pTransfer.count({
        where: {
          OR: [
            { fromAccountSequence: accountSequence },
            { toAccountSequence: accountSequence },
          ],
        },
      }),
    ]);

    const data = records.map((record) => ({
      transferNo: record.transferNo,
      fromAccountSequence: record.fromAccountSequence,
      toAccountSequence: record.toAccountSequence,
      toPhone: record.toPhone,
      amount: record.amount.toString(),
      fee: record.fee.toString(),
      memo: record.memo,
      status: record.status,
      createdAt: record.createdAt,
    } as P2pTransferHistoryItem));

    return { data, total };
  }

  /**
   * 获取全部P2P转账记录（管理后台用，不限用户）
   */
  async getAllTransfers(
    page: number = 1,
    pageSize: number = 20,
    search?: string,
  ): Promise<{
    data: P2pTransferHistoryItem[];
    total: number;
    summary: { totalFee: string; totalAmount: string; totalCount: number };
  }> {
    const validPage = Math.max(1, Number(page) || 1);
    const validPageSize = Math.max(1, Math.min(100, Number(pageSize) || 20));

    const where: any = { status: 'COMPLETED' };
    if (search) {
      where.OR = [
        { fromAccountSequence: { contains: search } },
        { toAccountSequence: { contains: search } },
        { toPhone: { contains: search } },
        { fromPhone: { contains: search } },
        { transferNo: { contains: search } },
      ];
    }

    const [records, total, agg] = await Promise.all([
      this.prisma.p2pTransfer.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        skip: (validPage - 1) * validPageSize,
        take: validPageSize,
      }),
      this.prisma.p2pTransfer.count({ where }),
      this.prisma.p2pTransfer.aggregate({
        where: { status: 'COMPLETED' },
        _sum: { fee: true, amount: true },
        _count: true,
      }),
    ]);

    const data: P2pTransferHistoryItem[] = records.map((record) => ({
      transferNo: record.transferNo,
      fromAccountSequence: record.fromAccountSequence,
      fromPhone: record.fromPhone,
      fromNickname: record.fromNickname,
      toAccountSequence: record.toAccountSequence,
      toPhone: record.toPhone,
      toNickname: record.toNickname,
      amount: record.amount.toString(),
      fee: record.fee.toString(),
      memo: record.memo,
      status: record.status,
      createdAt: record.createdAt,
    }));

    return {
      data,
      total,
      summary: {
        totalFee: agg._sum.fee?.toString() || '0',
        totalAmount: agg._sum.amount?.toString() || '0',
        totalCount: agg._count,
      },
    };
  }

  private generateTransferNo(): string {
    const timestamp = Date.now().toString(36);
    const random = Math.random().toString(36).substring(2, 8);
    return `P2P${timestamp}${random}`.toUpperCase();
  }
}
