// Automated Liquidity Injection/Withdrawal Executor Service

import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { v4 as uuidv4 } from 'uuid';
import { AutonomousLiquidityAction, LiquidityActionType } from './types';
import { liquidityMonitorService } from './liquidity-monitor.service';
import { glpService } from '../glp/glp-service';
import { logger } from '@/infrastructure/monitoring/logger';


export class LiquidityExecutorService {
  /**
   * Execute autonomous liquidity injection
   */
  async executeInjection(
    sovereignBankId: string,
    amount: number,
    triggerReason: string
  ): Promise<AutonomousLiquidityAction> {
    const actionId = `ALPS-INJECT-${sovereignBankId}-${Date.now()}`;

    // Create action record
    const action = await prisma.autonomous_liquidity_actions.create({
      data: {
        id: uuidv4(),
        actionId,
        actionType: LiquidityActionType.INJECTION,
        sovereignBankId,
        amount: new Decimal(amount),
        triggerReason,
        status: 'PENDING',
      },
    });

    try {
      // Execute GLP withdrawal for injection
      await glpService.requestWithdrawal({
        sovereignBankId,
        amount: amount.toString(),
      });

      // Update action status
      await prisma.autonomous_liquidity_actions.update({
        where: { id: action.id },
        data: {
          status: 'EXECUTED',
          executedAt: new Date(),
        },
      });

      logger.info(`Executed liquidity injection: ${actionId}`, {
        amount,
        sovereignBankId,
      });

      return this.mapToAction(action);
    } catch (error) {
      // Mark as failed
      await prisma.autonomous_liquidity_actions.update({
        where: { id: action.id },
        data: { status: 'FAILED' },
      });

      logger.error(`Failed to execute liquidity injection: ${actionId}`, error);
      throw error;
    }
  }

  /**
   * Execute autonomous liquidity withdrawal
   */
  async executeWithdrawal(
    sovereignBankId: string,
    amount: number,
    triggerReason: string
  ): Promise<AutonomousLiquidityAction> {
    const actionId = `ALPS-WITHDRAW-${sovereignBankId}-${Date.now()}`;

    // Create action record
    const action = await prisma.autonomous_liquidity_actions.create({
      data: {
        id: uuidv4(),
        actionId,
        actionType: LiquidityActionType.WITHDRAWAL,
        sovereignBankId,
        amount: new Decimal(amount),
        triggerReason,
        status: 'PENDING',
      },
    });

    try {
      // Contribute back to GLP
      await glpService.contribute({
        sovereignBankId,
        contributionType: 'dbis_stabilization',
        amount: amount.toString(),
      });

      // Update action status
      await prisma.autonomous_liquidity_actions.update({
        where: { id: action.id },
        data: {
          status: 'EXECUTED',
          executedAt: new Date(),
        },
      });

      logger.info(`Executed liquidity withdrawal: ${actionId}`, {
        amount,
        sovereignBankId,
      });

      return this.mapToAction(action);
    } catch (error) {
      // Mark as failed
      await prisma.autonomous_liquidity_actions.update({
        where: { id: action.id },
        data: { status: 'FAILED' },
      });

      logger.error(`Failed to execute liquidity withdrawal: ${actionId}`, error);
      throw error;
    }
  }

  /**
   * Get liquidity actions
   */
  async getActions(sovereignBankId?: string, actionType?: LiquidityActionType) {
    const where: any = {};
    if (sovereignBankId) {
      where.sovereignBankId = sovereignBankId;
    }
    if (actionType) {
      where.actionType = actionType;
    }

    return prisma.autonomous_liquidity_actions.findMany({
      where,
      orderBy: { executedAt: 'desc' },
      take: 100,
    });
  }

  private mapToAction(action: any): AutonomousLiquidityAction {
    return {
      id: action.id,
      actionId: action.actionId,
      actionType: action.actionType as LiquidityActionType,
      sovereignBankId: action.sovereignBankId,
      amount: Number(action.amount),
      currencyCode: action.currencyCode || undefined,
      triggerReason: action.triggerReason,
      executedAt: action.executedAt,
      status: action.status as any,
    };
  }
}

export const liquidityExecutorService = new LiquidityExecutorService();

