// IRU Provisioning Service
import { v4 as uuidv4 } from 'uuid';
// Main orchestrator for IRU provisioning

import { resourceAllocator } from './resource-allocator.service';
import { configurationGenerator } from './configuration-generator.service';
import { provisioningValidator } from './provisioning-validator.service';
import prisma from '@/shared/database/prisma';
import { DbisError, ErrorCode } from '@/shared/types';

import { DeploymentConfig, ProvisioningResources, ProvisioningConfiguration } from '../types/common.types';

export interface ProvisioningRequest {
  subscriptionId: string;
  deploymentConfig?: DeploymentConfig;
}

export interface ProvisioningResult {
  subscriptionId: string;
  status: string;
  deploymentId: string;
  resources: ProvisioningResources;
  configuration: ProvisioningConfiguration;
  estimatedCompletion: Date;
}

export class IRUProvisioningService {
  /**
   * Provision IRU infrastructure
   */
  async provision(request: ProvisioningRequest): Promise<ProvisioningResult> {
    const subscription = await prisma.iruSubscription.findUnique({
      where: { subscriptionId: request.subscriptionId },
      include: {
        offering: true,
        inquiry: true,
      },
    });

    if (!subscription) {
      throw new DbisError(ErrorCode.NOT_FOUND, `Subscription ${request.subscriptionId} not found`);
    }

    if (subscription.subscriptionStatus !== 'active') {
      throw new DbisError(
        ErrorCode.VALIDATION_ERROR,
        `Subscription ${request.subscriptionId} is not active`
      );
    }

    // Step 1: Allocate resources
    const resources = await resourceAllocator.allocate({
      capacityTier: subscription.capacityTier,
      institutionalType: subscription.offering.institutionalType,
      deploymentConfig: request.deploymentConfig,
    });

    // Step 2: Generate configuration
    const configuration = await configurationGenerator.generate({
      subscription,
      resources,
      deploymentConfig: request.deploymentConfig,
    });

    // Step 3: Validate provisioning
    const validation = await provisioningValidator.validate({
      resources,
      configuration,
      subscription,
    });

    if (!validation.valid) {
      throw new DbisError(
        ErrorCode.VALIDATION_ERROR,
        `Provisioning validation failed: ${validation.errors.join(', ')}`
      );
    }

    // Step 4: Create deployment record (within transaction)
    const deploymentId = `DEP-${Date.now()}`;
    const estimatedCompletion = new Date(Date.now() + 2 * 60 * 60 * 1000); // 2 hours

    await prisma.$transaction(async (tx) => {
      // Create deployment record
      await tx.iruDeployment.create({
        data: {
          id: uuidv4(),
          deploymentId,
          subscriptionId: subscription.id,
          status: 'provisioning',
          progress: 10,
          stages: [
            {
              name: 'Resource Allocation',
              status: 'completed',
              completedAt: new Date(),
            },
          ],
          estimatedCompletion,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
      });

      // Update subscription status if needed
      if (subscription.subscriptionStatus === 'pending') {
        await tx.iruSubscription.update({
          where: { id: subscription.id },
          data: {
            subscriptionStatus: 'active',
            updatedAt: new Date(),
          },
        });
      }
    });

    return {
      subscriptionId: subscription.subscriptionId,
      status: 'provisioning',
      deploymentId,
      resources,
      configuration,
      estimatedCompletion,
    };
  }

  /**
   * Get provisioning status
   */
  async getProvisioningStatus(subscriptionId: string): Promise<{
    subscriptionId: string;
    status: string;
    deploymentId?: string;
    progress?: number;
  }> {
    // Get from deployment orchestrator
    const deployment = await prisma.iruDeployment.findFirst({
      where: {
        subscription: {
          subscriptionId,
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
      select: {
        deploymentId: true,
        status: true,
        progress: true,
      },
    });

    if (deployment) {
      return {
        subscriptionId,
        status: deployment.status,
        deploymentId: deployment.deploymentId,
        progress: deployment.progress,
      };
    }

    return {
      subscriptionId,
      status: 'pending',
    };
  }
}

export const iruProvisioningService = new IRUProvisioningService();
