import { Injectable } from '@nestjs/common';
import { ApprovalRequest } from '../entities/approval-request.entity';
import { RedisEventBus } from '@it0/events';
import { EventPatterns } from '@it0/common';

export interface ApprovalResult {
  approved: boolean;
  decidedBy: string;
  reason?: string;
}

const LEVEL1_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
const LEVEL2_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes

@Injectable()
export class ApprovalWorkflowService {
  private pendingApprovals = new Map<string, {
    resolve: (result: ApprovalResult) => void;
    timer: ReturnType<typeof setTimeout>;
  }>();

  constructor(private readonly eventBus: RedisEventBus) {}

  async processApproval(request: ApprovalRequest): Promise<ApprovalResult> {
    const isLowRisk = request.riskLevel <= 1;
    const timeoutMs = isLowRisk ? LEVEL1_TIMEOUT_MS : LEVEL2_TIMEOUT_MS;

    request.expiresAt = new Date(Date.now() + timeoutMs);
    request.status = 'pending';

    await this.eventBus.publish(EventPatterns.APPROVAL_REQUIRED, {
      id: crypto.randomUUID(),
      tenantId: request.tenantId,
      timestamp: new Date(),
      source: 'ops-service',
      type: 'approval.required',
      payload: {
        taskId: request.taskId,
        command: request.command,
        riskLevel: request.riskLevel,
        targetServer: '',
        expiresAt: request.expiresAt,
      },
    });

    return new Promise<ApprovalResult>((resolve) => {
      const timer = setTimeout(() => {
        this.pendingApprovals.delete(request.id);

        if (isLowRisk) {
          request.status = 'approved';
          request.decidedBy = 'system:auto-approve';
          request.decidedAt = new Date();
          resolve({
            approved: true,
            decidedBy: 'system:auto-approve',
            reason: 'Level 1 timeout - auto-approved',
          });
        } else {
          request.status = 'expired';
          request.decidedBy = 'system:auto-reject';
          request.decidedAt = new Date();
          resolve({
            approved: false,
            decidedBy: 'system:auto-reject',
            reason: 'Level 2 timeout - auto-rejected',
          });
        }
      }, timeoutMs);

      this.pendingApprovals.set(request.id, { resolve, timer });
    });
  }

  resolveApproval(
    requestId: string,
    approved: boolean,
    decidedBy: string,
    reason?: string,
  ): boolean {
    const pending = this.pendingApprovals.get(requestId);
    if (!pending) return false;

    clearTimeout(pending.timer);
    this.pendingApprovals.delete(requestId);

    pending.resolve({ approved, decidedBy, reason });
    return true;
  }
}
