import { Injectable, Inject, Logger, NotFoundException } from '@nestjs/common';
import { Settlement, SettlementStatus } from '../../domain/entities/settlement.entity';
import { JournalType } from '../../domain/entities/journal-entry.entity';
import {
  SETTLEMENT_REPOSITORY,
  ISettlementRepository,
} from '../../domain/repositories/settlement.repository.interface';
import { SettlementAmount } from '../../domain/value-objects/settlement-amount.vo';

@Injectable()
export class SettlementService {
  private readonly logger = new Logger('SettlementService');

  constructor(
    @Inject(SETTLEMENT_REPOSITORY)
    private readonly settlementRepo: ISettlementRepository,
  ) {}

  async createSettlement(data: {
    tradeId: string;
    buyerId: string;
    sellerId: string;
    amount: string;
    buyerFee: string;
    sellerFee: string;
  }): Promise<Settlement> {
    // Validate amounts using VO
    const amount = SettlementAmount.create(data.amount);
    const buyerFee = SettlementAmount.create(data.buyerFee);
    const sellerFee = SettlementAmount.create(data.sellerFee);
    const sellerPayout = amount.subtract(sellerFee);

    const settlementData: Partial<Settlement> = {
      tradeId: data.tradeId,
      buyerId: data.buyerId,
      sellerId: data.sellerId,
      amount: amount.value,
      buyerFee: buyerFee.value,
      sellerFee: sellerFee.value,
      status: SettlementStatus.PENDING,
    };

    // Double-entry bookkeeping journal entries
    const journalEntries = [
      {
        entryType: JournalType.SETTLEMENT,
        referenceType: 'settlement',
        debitAccount: 'buyer_wallet',
        creditAccount: 'escrow',
        amount: amount.value,
        description: `Trade settlement ${data.tradeId}`,
      },
      {
        entryType: JournalType.TRADE_FEE,
        referenceType: 'settlement',
        debitAccount: 'escrow',
        creditAccount: 'platform_revenue',
        amount: buyerFee.value,
        description: `Buyer fee for trade ${data.tradeId}`,
      },
      {
        entryType: JournalType.TRADE_FEE,
        referenceType: 'settlement',
        debitAccount: 'escrow',
        creditAccount: 'platform_revenue',
        amount: sellerFee.value,
        description: `Seller fee for trade ${data.tradeId}`,
      },
      {
        entryType: JournalType.SETTLEMENT,
        referenceType: 'settlement',
        debitAccount: 'escrow',
        creditAccount: 'seller_wallet',
        amount: sellerPayout.value,
        description: `Seller payout for trade ${data.tradeId}`,
      },
    ];

    const saved = await this.settlementRepo.createSettlementWithJournalEntries(
      settlementData,
      journalEntries,
    );

    this.logger.log(`Settlement created for trade ${data.tradeId}: ${saved.id}`);
    return saved;
  }

  async completeSettlement(id: string): Promise<Settlement> {
    const settlement = await this.settlementRepo.findById(id);
    if (!settlement) {
      throw new NotFoundException('Settlement not found');
    }
    settlement.status = SettlementStatus.COMPLETED;
    settlement.settledAt = new Date();
    return this.settlementRepo.save(settlement);
  }

  async getByTradeId(tradeId: string): Promise<Settlement | null> {
    return this.settlementRepo.findByTradeId(tradeId);
  }

  async list(
    page: number,
    limit: number,
    status?: string,
  ): Promise<{ items: Settlement[]; total: number; page: number; limit: number }> {
    const [items, total] = await this.settlementRepo.findAndCount({
      status: status as SettlementStatus | undefined,
      page,
      limit,
    });
    return { items, total, page, limit };
  }
}
