import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { Dispute, DisputeStatus } from '../../domain/entities/dispute.entity';
import {
  DISPUTE_REPOSITORY,
  IDisputeRepository,
} from '../../domain/repositories/dispute.repository.interface';
import {
  AUDIT_LOGGER_SERVICE,
  IAuditLoggerService,
} from '../../domain/ports/audit-logger.interface';

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

  constructor(
    @Inject(DISPUTE_REPOSITORY)
    private readonly disputeRepo: IDisputeRepository,
    @Inject(AUDIT_LOGGER_SERVICE)
    private readonly auditLogger: IAuditLoggerService,
  ) {}

  /** List disputes (paginated, filterable by status and type) */
  async listDisputes(page: number, limit: number, status?: string, type?: string) {
    const [items, total] = await this.disputeRepo.findPaginated(page, limit, { status, type });
    return { items, total, page, limit, totalPages: Math.ceil(total / limit) };
  }

  /** Get dispute detail by ID */
  async getDisputeDetail(id: string) {
    const dispute = await this.disputeRepo.findById(id);
    if (!dispute) throw new NotFoundException('Dispute not found');
    return dispute;
  }

  /** Resolve a dispute with a decision */
  async resolveDispute(
    id: string,
    data: { resolution: string; status: 'resolved' | 'rejected' },
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const dispute = await this.disputeRepo.findById(id);
    if (!dispute) throw new NotFoundException('Dispute not found');

    const previousStatus = dispute.status;
    dispute.status = data.status === 'rejected' ? DisputeStatus.REJECTED : DisputeStatus.RESOLVED;
    dispute.resolution = data.resolution;
    dispute.resolvedAt = new Date();

    const saved = await this.disputeRepo.save(dispute);

    // Audit log via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'resolve_dispute',
      resource: 'dispute',
      resourceId: id,
      ipAddress,
      details: {
        previousStatus,
        newStatus: dispute.status,
        resolution: data.resolution,
      },
    });

    this.logger.log(`Dispute resolved: id=${id}, status=${dispute.status}, by admin=${adminId}`);
    return saved;
  }

  /** Arbitration action: move dispute to processing and record arbitration details */
  async arbitrate(
    id: string,
    data: { decision: string; notes?: string },
    adminId: string,
    adminName: string,
    ipAddress?: string,
  ) {
    const dispute = await this.disputeRepo.findById(id);
    if (!dispute) throw new NotFoundException('Dispute not found');

    const previousStatus = dispute.status;
    dispute.status = DisputeStatus.PROCESSING;
    dispute.description = dispute.description
      ? `${dispute.description}\n\n[Arbitration by ${adminName}]: ${data.decision}${data.notes ? ` - ${data.notes}` : ''}`
      : `[Arbitration by ${adminName}]: ${data.decision}${data.notes ? ` - ${data.notes}` : ''}`;

    const saved = await this.disputeRepo.save(dispute);

    // Audit log via shared service
    await this.auditLogger.log({
      adminId,
      adminName,
      action: 'arbitrate_dispute',
      resource: 'dispute',
      resourceId: id,
      ipAddress,
      details: {
        previousStatus,
        decision: data.decision,
        notes: data.notes,
      },
    });

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