import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { USER_REPOSITORY, IUserRepository } from '../../domain/repositories/user.repository.interface';
import { KYC_REPOSITORY, IKycRepository } from '../../domain/repositories/kyc.repository.interface';
import { WALLET_REPOSITORY, IWalletRepository } from '../../domain/repositories/wallet.repository.interface';
import { TRANSACTION_REPOSITORY, ITransactionRepository } from '../../domain/repositories/transaction.repository.interface';
import { KycStatus } from '../../domain/entities/kyc-submission.entity';
import { UserStatus } from '../../domain/entities/user.entity';

@Injectable()
export class AdminUserService {
  constructor(
    @Inject(USER_REPOSITORY) private readonly userRepo: IUserRepository,
    @Inject(KYC_REPOSITORY) private readonly kycRepo: IKycRepository,
    @Inject(WALLET_REPOSITORY) private readonly walletRepo: IWalletRepository,
    @Inject(TRANSACTION_REPOSITORY) private readonly txRepo: ITransactionRepository,
  ) {}

  async listUsers(filters: {
    page: number;
    limit: number;
    search?: string;
    kycLevel?: number;
    status?: string;
  }) {
    const { page, limit } = filters;
    const [items, total] = await this.userRepo.findByFilters(filters);
    return { items, total, page, limit };
  }

  async getUserDetail(id: string) {
    const user = await this.userRepo.findById(id);
    if (!user) throw new NotFoundException('User not found');

    const [kyc, wallet] = await Promise.all([
      this.kycRepo.findLatestByUserId(id),
      this.walletRepo.findByUserId(id),
    ]);

    return { user, kyc, wallet };
  }

  async reviewKyc(userId: string, action: 'approve' | 'reject', reason?: string) {
    const kyc = await this.kycRepo.findLatestByUserId(userId);
    if (!kyc) throw new NotFoundException('KYC submission not found');

    kyc.status = action === 'approve' ? KycStatus.APPROVED : KycStatus.REJECTED;
    kyc.reviewedAt = new Date();

    if (action === 'reject' && reason) {
      kyc.rejectReason = reason;
    }

    await this.kycRepo.save(kyc);

    if (action === 'approve') {
      await this.userRepo.updateKycLevel(userId, kyc.targetLevel);
    }

    return { success: true };
  }

  async freezeUser(id: string, reason: string) {
    const user = await this.userRepo.findById(id);
    if (!user) throw new NotFoundException('User not found');

    user.status = UserStatus.FROZEN;
    await this.userRepo.save(user);
    return { success: true };
  }

  async unfreezeUser(id: string) {
    const user = await this.userRepo.findById(id);
    if (!user) throw new NotFoundException('User not found');

    user.status = UserStatus.ACTIVE;
    await this.userRepo.save(user);
    return { success: true };
  }

  async getUserTransactions(userId: string, page: number, limit: number) {
    const wallet = await this.walletRepo.findByUserId(userId);
    if (!wallet) {
      return { items: [], total: 0, page, limit };
    }

    const [items, total] = await this.txRepo.findByWalletId(wallet.id, page, limit);
    return { items, total, page, limit };
  }
}
