// DBIS Temporal Liquidity Portal - Buffer Service
// Temporal settlement buffer management

import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { Decimal } from '@prisma/client/runtime/library';
import { tlpPortalService } from './tlp-portal.service';


export type BufferType = 'interplanetary_settlement' | 'csse' | 'ai_policy_correction';

export interface CreateBufferRequest {
  portalId: string;
  bufferType: BufferType;
  bufferAmount: number;
}

export interface AllocateBufferRequest {
  bufferId: string;
  amount: number;
}

export class TlpBufferService {
  /**
   * Create temporal settlement buffer
   */
  async createBuffer(request: CreateBufferRequest) {
    const portal = await tlpPortalService.getPortal(request.portalId);
    if (!portal) {
      throw new Error(`Portal not found: ${request.portalId}`);
    }

    const bufferId = `TB-${uuidv4()}`;

    const buffer = await prisma.temporalBuffer.create({
      data: {
        bufferId,
        portalId: request.portalId,
        bufferType: request.bufferType,
        bufferAmount: new Decimal(request.bufferAmount),
        allocatedAmount: new Decimal(0),
        status: 'active',
      },
    });

    return buffer;
  }

  /**
   * Allocate buffer amount
   */
  async allocateBuffer(request: AllocateBufferRequest) {
    const buffer = await prisma.temporalBuffer.findUnique({
      where: { bufferId: request.bufferId },
    });

    if (!buffer) {
      throw new Error(`Buffer not found: ${request.bufferId}`);
    }

    if (buffer.status !== 'active') {
      throw new Error(`Buffer is not active: ${buffer.status}`);
    }

    const allocateAmount = new Decimal(request.amount);
    const newAllocatedAmount = buffer.allocatedAmount.plus(allocateAmount);

    if (newAllocatedAmount.gt(buffer.bufferAmount)) {
      throw new Error(`Allocation exceeds buffer amount. Available: ${buffer.bufferAmount.minus(buffer.allocatedAmount)}`);
    }

    const updatedBuffer = await prisma.temporalBuffer.update({
      where: { bufferId: request.bufferId },
      data: {
        allocatedAmount: newAllocatedAmount,
        status: newAllocatedAmount.gte(buffer.bufferAmount) ? 'exhausted' : 'active',
      },
    });

    return updatedBuffer;
  }

  /**
   * Get buffer by ID
   */
  async getBuffer(bufferId: string) {
    return await prisma.temporalBuffer.findUnique({
      where: { bufferId },
      include: {
        portal: true,
      },
    });
  }

  /**
   * Get buffers by type
   */
  async getBuffersByType(bufferType: BufferType) {
    return await prisma.temporalBuffer.findMany({
      where: {
        bufferType,
        status: 'active',
      },
      include: {
        portal: true,
      },
    });
  }

  /**
   * Get buffers for a portal
   */
  async getBuffersForPortal(portalId: string) {
    return await prisma.temporalBuffer.findMany({
      where: { portalId },
      orderBy: { createdAt: 'desc' },
    });
  }

  /**
   * Get available buffer amount
   */
  async getAvailableBuffer(bufferId: string) {
    const buffer = await prisma.temporalBuffer.findUnique({
      where: { bufferId },
    });

    if (!buffer) {
      throw new Error(`Buffer not found: ${bufferId}`);
    }

    const available = buffer.bufferAmount.minus(buffer.allocatedAmount);
    return {
      bufferId,
      totalAmount: buffer.bufferAmount.toNumber(),
      allocatedAmount: buffer.allocatedAmount.toNumber(),
      availableAmount: available.toNumber(),
      bufferType: buffer.bufferType,
    };
  }
}

export const tlpBufferService = new TlpBufferService();

