import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { InsuranceClaim, ClaimStatus } from '../../domain/entities/insurance-claim.entity';
import {
  INSURANCE_CLAIM_REPOSITORY,
  IInsuranceClaimRepository,
} from '../../domain/repositories/insurance-claim.repository.interface';
import {
  AUDIT_LOGGER_SERVICE,
  IAuditLoggerService,
} from '../../domain/ports/audit-logger.interface';

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

  constructor(
    @Inject(INSURANCE_CLAIM_REPOSITORY)
    private readonly claimRepo: IInsuranceClaimRepository,
    @Inject(AUDIT_LOGGER_SERVICE)
    private readonly auditLogger: IAuditLoggerService,
  ) {}

  /** Protection fund statistics */
  async getStats() {
    const [totalClaims, pendingClaims, paidClaims, rejectedClaims] = await Promise.all([
      this.claimRepo.count(),
      this.claimRepo.count({ where: { status: ClaimStatus.PENDING } }),
      this.claimRepo.count({ where: { status: ClaimStatus.PAID } }),
      this.claimRepo.count({ where: { status: ClaimStatus.REJECTED } }),
    ]);

    const [totalPaidAmount, totalPendingAmount] = await Promise.all([
      this.claimRepo.sumAmountByStatus(ClaimStatus.PAID),
      this.claimRepo.sumAmountByStatus(ClaimStatus.PENDING),
    ]);

    return {
      totalClaims,
      pendingClaims,
      paidClaims,
      rejectedClaims,
      processingClaims: totalClaims - pendingClaims - paidClaims - rejectedClaims,
      totalPaidAmount,
      totalPendingAmount,
      fundBalance: '1000000.00', // Mock: protection fund balance
    };
  }

  /** List insurance claims (paginated, filterable by status) */
  async listClaims(page: number, limit: number, status?: string) {
    const [items, total] = await this.claimRepo.findPaginated(page, limit, { status });
    return { items, total, page, limit, totalPages: Math.ceil(total / limit) };
  }

  /** Approve an insurance claim */
  async approveClaim(
    id: string,
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const claim = await this.claimRepo.findById(id);
    if (!claim) throw new NotFoundException('Insurance claim not found');

    const previousStatus = claim.status;
    claim.status = ClaimStatus.PAID;
    claim.processedAt = new Date();

    const saved = await this.claimRepo.save(claim);

    // Audit log via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'approve_claim',
      resource: 'insurance_claim',
      resourceId: id,
      ipAddress,
      details: {
        previousStatus,
        amount: claim.amount,
        userId: claim.userId,
      },
    });

    this.logger.log(`Insurance claim approved: id=${id}, amount=${claim.amount}, by admin=${adminId}`);
    return saved;
  }

  /** Reject an insurance claim */
  async rejectClaim(
    id: string,
    data: { reason?: string },
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const claim = await this.claimRepo.findById(id);
    if (!claim) throw new NotFoundException('Insurance claim not found');

    const previousStatus = claim.status;
    claim.status = ClaimStatus.REJECTED;
    claim.processedAt = new Date();
    if (data.reason) {
      claim.reason = `${claim.reason}\n\n[Rejection reason]: ${data.reason}`;
    }

    const saved = await this.claimRepo.save(claim);

    // Audit log via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'reject_claim',
      resource: 'insurance_claim',
      resourceId: id,
      ipAddress,
      details: {
        previousStatus,
        amount: claim.amount,
        userId: claim.userId,
        rejectionReason: data.reason,
      },
    });

    this.logger.log(`Insurance claim rejected: id=${id}, by admin=${adminId}`);
    return saved;
  }
}
