import { Injectable, Logger } from '@nestjs/common';
import { TaskRepository } from '../../infrastructure/repositories/task.repository';
import { RunbookRepository } from '../../infrastructure/repositories/runbook.repository';
import { ApprovalRepository } from '../../infrastructure/repositories/approval.repository';
import { ApprovalWorkflowService } from '../../domain/services/approval-workflow.service';
import { OpsTask } from '../../domain/entities/ops-task.entity';
import { ApprovalRequest } from '../../domain/entities/approval-request.entity';
import { TaskType } from '../../domain/value-objects/task-type.vo';
import * as crypto from 'crypto';

export interface CreateDeploymentTaskInput {
  tenantId: string;
  title: string;
  description?: string;
  targetServers: string[];
  runbookId?: string;
  createdBy: string;
  priority?: number;
}

@Injectable()
export class CreateDeploymentTaskUseCase {
  private readonly logger = new Logger(CreateDeploymentTaskUseCase.name);

  constructor(
    private readonly taskRepository: TaskRepository,
    private readonly runbookRepository: RunbookRepository,
    private readonly approvalRepository: ApprovalRepository,
    private readonly approvalWorkflowService: ApprovalWorkflowService,
  ) {}

  async execute(input: CreateDeploymentTaskInput): Promise<OpsTask> {
    this.logger.log(`Creating deployment task: ${input.title}`);

    if (input.runbookId) {
      const runbook = await this.runbookRepository.findById(input.runbookId);
      if (!runbook) {
        throw new Error(`Runbook ${input.runbookId} not found`);
      }
    }

    const task = new OpsTask();
    task.id = crypto.randomUUID();
    task.tenantId = input.tenantId;
    task.type = TaskType.DEPLOYMENT;
    task.title = input.title;
    task.description = input.description;
    task.status = 'pending';
    task.priority = input.priority ?? 2;
    task.targetServers = input.targetServers;
    task.runbookId = input.runbookId;
    task.createdBy = input.createdBy;
    task.createdAt = new Date();

    const saved = await this.taskRepository.save(task);

    // Deployment tasks require approval (risk level 2)
    const approval = new ApprovalRequest();
    approval.id = crypto.randomUUID();
    approval.tenantId = input.tenantId;
    approval.taskId = saved.id;
    approval.command = `deploy:${input.title}`;
    approval.riskLevel = 2;
    approval.status = 'pending';
    approval.expiresAt = new Date(Date.now() + 30 * 60 * 1000);
    approval.notificationChannels = ['push', 'im'];

    await this.approvalRepository.save(approval);

    this.logger.log(`Deployment task created: ${saved.id}, approval required: ${approval.id}`);
    return saved;
  }
}
