import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { OutboxRepository } from '../../infrastructure/persistence/repositories/outbox.repository';
import { UserWalletType, AssetType, TransactionType } from '@prisma/client';
import Decimal from 'decimal.js';

export interface CreditContributionInput {
  accountSequence: string;
  amount: Decimal;
  contributionType: 'PERSONAL' | 'TEAM_LEVEL' | 'TEAM_BONUS';
  levelDepth?: number;
  bonusTier?: number;
  effectiveDate: Date;
  expireDate: Date;
  sourceAdoptionId: string;
  sourceAccountSequence: string;
}

export interface CreditSystemContributionInput {
  accountType: 'OPERATION' | 'PROVINCE' | 'CITY' | 'HEADQUARTERS';
  amount: Decimal;
  provinceCode?: string;
  cityCode?: string;
  neverExpires: boolean;
  sourceAdoptionId: string;
  sourceAccountSequence: string;
  memo?: string;
}

@Injectable()
export class ContributionWalletService {
  private readonly logger = new Logger(ContributionWalletService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly outboxRepo: OutboxRepository,
  ) {}

  /**
   * 为用户钱包增加贡献值
   */
  async creditContribution(input: CreditContributionInput): Promise<void> {
    await this.prisma.$transaction(async (tx) => {
      // 1. 获取或创建用户贡献值钱包
      let wallet = await tx.userWallet.findUnique({
        where: {
          accountSequence_walletType: {
            accountSequence: input.accountSequence,
            walletType: UserWalletType.CONTRIBUTION,
          },
        },
      });

      const isNewWallet = !wallet;
      if (!wallet) {
        wallet = await tx.userWallet.create({
          data: {
            accountSequence: input.accountSequence,
            walletType: UserWalletType.CONTRIBUTION,
            balance: new Decimal(0),
            frozenBalance: new Decimal(0),
          },
        });

        // 发布 UserWalletCreated 事件
        await tx.outboxEvent.create({
          data: {
            aggregateType: 'UserWallet',
            aggregateId: wallet.id,
            eventType: 'UserWalletCreated',
            topic: 'cdc.mining-wallet.outbox',
            key: input.accountSequence,
            payload: {
              id: wallet.id,
              accountSequence: wallet.accountSequence,
              walletType: wallet.walletType,
              balance: '0',
              frozenBalance: '0',
              totalInflow: 0,
              totalOutflow: 0,
              isActive: true,
            },
          },
        });
      }

      const balanceBefore = new Decimal(wallet.balance.toString());
      const balanceAfter = balanceBefore.plus(input.amount);

      // 2. 更新钱包余额
      const updatedWallet = await tx.userWallet.update({
        where: { id: wallet.id },
        data: {
          balance: balanceAfter,
          totalInflow: { increment: input.amount },
        },
      });

      // 发布 UserWalletUpdated 事件（用于 mining-admin-service 同步）
      await tx.outboxEvent.create({
        data: {
          aggregateType: 'UserWallet',
          aggregateId: wallet.id,
          eventType: 'UserWalletUpdated',
          topic: 'cdc.mining-wallet.outbox',
          key: input.accountSequence,
          payload: {
            id: wallet.id,
            accountSequence: wallet.accountSequence,
            walletType: wallet.walletType,
            balance: balanceAfter.toString(),
            frozenBalance: updatedWallet.frozenBalance.toString(),
            totalInflow: updatedWallet.totalInflow.toString(),
            totalOutflow: updatedWallet.totalOutflow.toString(),
            isActive: true,
          },
        },
      });

      // 3. 创建交易记录（分类账）
      const transaction = await tx.userWalletTransaction.create({
        data: {
          userWalletId: wallet.id,
          accountSequence: input.accountSequence,
          walletType: UserWalletType.CONTRIBUTION,
          transactionType: TransactionType.TRANSFER_IN,
          assetType: AssetType.CONTRIBUTION,
          amount: input.amount,
          balanceBefore,
          balanceAfter,
          counterpartyType: 'EXTERNAL',
          referenceId: input.sourceAdoptionId,
          referenceType: 'ADOPTION',
          memo: this.buildMemo(input),
          metadata: {
            contributionType: input.contributionType,
            levelDepth: input.levelDepth,
            bonusTier: input.bonusTier,
            effectiveDate: input.effectiveDate.toISOString(),
            expireDate: input.expireDate.toISOString(),
            sourceAccountSequence: input.sourceAccountSequence,
          },
        },
      });

      // 4. 发布事件到 Outbox
      await tx.outboxEvent.create({
        data: {
          aggregateType: 'UserWallet',
          aggregateId: wallet.id,
          eventType: 'CONTRIBUTION_CREDITED',
          topic: 'mining-wallet.contribution.credited',
          key: input.accountSequence,
          payload: {
            accountSequence: input.accountSequence,
            walletType: 'CONTRIBUTION',
            amount: input.amount.toString(),
            balanceAfter: balanceAfter.toString(),
            transactionId: transaction.id,
            contributionType: input.contributionType,
            sourceAdoptionId: input.sourceAdoptionId,
            sourceAccountSequence: input.sourceAccountSequence,
            levelDepth: input.levelDepth,
            bonusTier: input.bonusTier,
          },
        },
      });

      this.logger.debug(
        `Credited ${input.amount} contribution to ${input.accountSequence}, type: ${input.contributionType}`,
      );
    });
  }

  /**
   * 为系统账户增加贡献值
   */
  async creditSystemContribution(
    input: CreditSystemContributionInput,
  ): Promise<void> {
    await this.prisma.$transaction(async (tx) => {
      // 1. 根据 accountType 和区域查找系统账户
      let whereClause: any = { accountType: input.accountType };

      if (input.accountType === 'PROVINCE' && input.provinceCode) {
        whereClause = {
          accountType: input.accountType,
          province: { code: input.provinceCode },
        };
      } else if (input.accountType === 'CITY' && input.cityCode) {
        whereClause = {
          accountType: input.accountType,
          city: { code: input.cityCode },
        };
      }

      let systemAccount = await tx.systemAccount.findFirst({
        where: whereClause,
      });

      // 如果找不到，尝试自动创建省/市级系统账户
      if (!systemAccount) {
        systemAccount = await this.createSystemAccountIfNeeded(
          tx,
          input.accountType,
          input.provinceCode,
          input.cityCode,
        );

        if (!systemAccount) {
          this.logger.warn(
            `Failed to create system account: ${input.accountType}, province: ${input.provinceCode}, city: ${input.cityCode}`,
          );
          return;
        }
      }

      const balanceBefore = new Decimal(
        systemAccount.contributionBalance?.toString() || '0',
      );
      const balanceAfter = balanceBefore.plus(input.amount);

      // 2. 更新系统账户贡献值余额
      await tx.systemAccount.update({
        where: { id: systemAccount.id },
        data: {
          contributionBalance: balanceAfter,
        },
      });

      // 3. 创建系统账户交易记录
      await tx.systemAccountTransaction.create({
        data: {
          systemAccountId: systemAccount.id,
          transactionType: TransactionType.TRANSFER_IN,
          assetType: AssetType.CONTRIBUTION,
          amount: input.amount,
          balanceBefore,
          balanceAfter,
          counterpartyType: 'USER',
          counterpartyAccountSeq: input.sourceAccountSequence,
          referenceId: input.sourceAdoptionId,
          referenceType: 'ADOPTION',
          memo:
            input.memo ||
            `贡献值分配, 来源认种: ${input.sourceAdoptionId}, 认种人: ${input.sourceAccountSequence}`,
          metadata: {
            neverExpires: input.neverExpires,
          },
        },
      });

      this.logger.debug(
        `Credited ${input.amount} contribution to system account ${systemAccount.code}`,
      );
    });
  }

  /**
   * 处理贡献值过期
   */
  async expireContribution(
    transactionId: string,
    accountSequence: string,
    amount: Decimal,
  ): Promise<void> {
    await this.prisma.$transaction(async (tx) => {
      const wallet = await tx.userWallet.findUnique({
        where: {
          accountSequence_walletType: {
            accountSequence,
            walletType: UserWalletType.CONTRIBUTION,
          },
        },
      });

      if (!wallet) {
        this.logger.warn(
          `Wallet not found for expiry: ${accountSequence}`,
        );
        return;
      }

      const balanceBefore = new Decimal(wallet.balance.toString());
      let balanceAfter = balanceBefore.minus(amount);

      // 确保余额不为负
      if (balanceAfter.lt(0)) {
        balanceAfter = new Decimal(0);
      }

      // 更新钱包余额
      const updatedWallet = await tx.userWallet.update({
        where: { id: wallet.id },
        data: {
          balance: balanceAfter,
          totalOutflow: { increment: amount },
        },
      });

      // 发布 UserWalletUpdated 事件（用于 mining-admin-service 同步）
      await tx.outboxEvent.create({
        data: {
          aggregateType: 'UserWallet',
          aggregateId: wallet.id,
          eventType: 'UserWalletUpdated',
          topic: 'cdc.mining-wallet.outbox',
          key: accountSequence,
          payload: {
            id: wallet.id,
            accountSequence: wallet.accountSequence,
            walletType: wallet.walletType,
            balance: balanceAfter.toString(),
            frozenBalance: updatedWallet.frozenBalance.toString(),
            totalInflow: updatedWallet.totalInflow.toString(),
            totalOutflow: updatedWallet.totalOutflow.toString(),
            isActive: true,
          },
        },
      });

      // 创建过期交易记录
      await tx.userWalletTransaction.create({
        data: {
          userWalletId: wallet.id,
          accountSequence,
          walletType: UserWalletType.CONTRIBUTION,
          transactionType: TransactionType.TRANSFER_OUT,
          assetType: AssetType.CONTRIBUTION,
          amount: amount.negated(),
          balanceBefore,
          balanceAfter,
          counterpartyType: 'SYSTEM_ACCOUNT',
          referenceId: transactionId,
          referenceType: 'EXPIRY',
          memo: `贡献值过期, 原交易ID: ${transactionId}`,
          metadata: {
            originalTransactionId: transactionId,
            expiredAt: new Date().toISOString(),
          },
        },
      });

      this.logger.debug(
        `Expired ${amount} contribution for ${accountSequence}`,
      );
    });
  }

  private buildMemo(input: CreditContributionInput): string {
    const typeMap: Record<string, string> = {
      PERSONAL: '个人认种贡献',
      TEAM_LEVEL: `团队层级贡献(第${input.levelDepth}级)`,
      TEAM_BONUS: `团队奖励贡献(第${input.bonusTier}档)`,
    };
    return `${typeMap[input.contributionType]}, 来源认种: ${input.sourceAdoptionId}, 认种人: ${input.sourceAccountSequence}`;
  }

  /**
   * 自动创建省/市级系统账户（如果不存在）
   * 同时会创建对应的省/市区域记录
   */
  private async createSystemAccountIfNeeded(
    tx: any,
    accountType: string,
    provinceCode?: string,
    cityCode?: string,
  ): Promise<any | null> {
    // 只处理省/市级账户的自动创建
    if (accountType === 'PROVINCE' && provinceCode) {
      // 先找或创建省份
      let province = await tx.province.findUnique({
        where: { code: provinceCode },
      });

      if (!province) {
        province = await tx.province.create({
          data: {
            code: provinceCode,
            name: provinceCode,
            status: 'ACTIVE',
          },
        });
        this.logger.log(`Auto-created province: ${provinceCode}`);
      }

      // 创建省级系统账户
      const account = await tx.systemAccount.create({
        data: {
          accountType: 'PROVINCE',
          name: `${province.name}账户`,
          code: `PROV-${provinceCode}`,
          provinceId: province.id,
          isActive: true,
        },
      });
      this.logger.log(`Auto-created province system account: ${account.code}`);

      // 发布系统账户创建事件到 Outbox（用于 mining-admin-service 同步）
      await tx.outboxEvent.create({
        data: {
          aggregateType: 'SystemAccount',
          aggregateId: account.id,
          eventType: 'WalletSystemAccountCreated',
          topic: 'cdc.mining-wallet.outbox',
          key: account.code,
          payload: {
            id: account.id,
            accountType: account.accountType,
            name: account.name,
            code: account.code,
            provinceId: account.provinceId,
            cityId: null,
            shareBalance: 0,
            usdtBalance: 0,
            greenPointBalance: 0,
            frozenShare: 0,
            frozenUsdt: 0,
            totalInflow: 0,
            totalOutflow: 0,
            blockchainAddress: null,
            isActive: account.isActive,
          },
        },
      });

      return account;
    }

    if (accountType === 'CITY' && cityCode) {
      // 先找城市
      let city = await tx.city.findUnique({
        where: { code: cityCode },
      });

      if (!city) {
        // 城市不存在，需要先有省份
        if (!provinceCode) {
          this.logger.warn(`Cannot create city without provinceCode: ${cityCode}`);
          return null;
        }

        // 找或创建省份
        let province = await tx.province.findUnique({
          where: { code: provinceCode },
        });

        if (!province) {
          province = await tx.province.create({
            data: {
              code: provinceCode,
              name: provinceCode,
              status: 'ACTIVE',
            },
          });
          this.logger.log(`Auto-created province: ${provinceCode}`);
        }

        // 创建城市
        city = await tx.city.create({
          data: {
            code: cityCode,
            name: cityCode,
            provinceId: province.id,
            status: 'ACTIVE',
          },
        });
        this.logger.log(`Auto-created city: ${cityCode}`);
      }

      // 创建市级系统账户
      const account = await tx.systemAccount.create({
        data: {
          accountType: 'CITY',
          name: `${city.name}账户`,
          code: `CITY-${cityCode}`,
          provinceId: city.provinceId,
          cityId: city.id,
          isActive: true,
        },
      });
      this.logger.log(`Auto-created city system account: ${account.code}`);

      // 发布系统账户创建事件到 Outbox（用于 mining-admin-service 同步）
      await tx.outboxEvent.create({
        data: {
          aggregateType: 'SystemAccount',
          aggregateId: account.id,
          eventType: 'WalletSystemAccountCreated',
          topic: 'cdc.mining-wallet.outbox',
          key: account.code,
          payload: {
            id: account.id,
            accountType: account.accountType,
            name: account.name,
            code: account.code,
            provinceId: account.provinceId,
            cityId: account.cityId,
            shareBalance: 0,
            usdtBalance: 0,
            greenPointBalance: 0,
            frozenShare: 0,
            frozenUsdt: 0,
            totalInflow: 0,
            totalOutflow: 0,
            blockchainAddress: null,
            isActive: account.isActive,
          },
        },
      });

      return account;
    }

    // 其他类型（HEADQUARTERS, OPERATION, FEE）不自动创建，需要在 seed 中初始化
    return null;
  }
}
