// DBIS Admin Console - GRU Command Center Service
// GRU Monetary, Indexes, Bonds, Supranational Pools

import prisma from '@/shared/database/prisma';
import { logger } from '@/infrastructure/monitoring/logger';
import Decimal from 'decimal.js';

export interface GRUMonetaryMetrics {
  supply: {
    m00: number;
    m0: number;
    m1: number;
    sr1: number;
    sr2: number;
    sr3: number;
  };
  locked: {
    m00: boolean;
    m0: boolean;
    m1: boolean;
    sr1: boolean;
    sr2: boolean;
    sr3: boolean;
  };
}

export interface GRUIndexInfo {
  indexId: string;
  indexName: string;
  indexCode: string; // LiXAU, LiPMG, LiBMG1-3
  currentPrice: number;
  components: Array<{
    asset: string;
    weight: number;
  }>;
  priceHistory: Array<{
    timestamp: Date;
    price: number;
  }>;
  circuitBreakers: {
    maxIntradayMove: number;
    enabled: boolean;
  };
}

export interface GRUBondInfo {
  bondId: string;
  bondName: string;
  bondCode: string; // Li99PpOsB10, Li99PpAvB10
  outstanding: number;
  buyers: number;
  yield: number;
  issuanceWindow: 'open' | 'closed';
  primaryMarketParams: Record<string, unknown>;
}

export interface GRUSupranationalPool {
  poolId: string;
  poolName: string;
  totalReserves: number;
  allocations: Array<{
    reserveClass: string;
    amount: number;
  }>;
}

export interface GRUCommandDashboard {
  monetary: GRUMonetaryMetrics;
  indexes: GRUIndexInfo[];
  bonds: GRUBondInfo[];
  supranationalPools: GRUSupranationalPool[];
}

export class GRUCommandService {
  /**
   * Get GRU command center dashboard
   */
  async getGRUCommandDashboard(): Promise<GRUCommandDashboard> {
    const [monetary, indexes, bonds, supranationalPools] = await Promise.all([
      this.getGRUMonetary(),
      this.getGRUIndexes(),
      this.getGRUBonds(),
      this.getGRUSupranationalPools(),
    ]);

    return {
      monetary,
      indexes,
      bonds,
      supranationalPools,
    };
  }

  /**
   * Get GRU monetary metrics
   */
  async getGRUMonetary(): Promise<GRUMonetaryMetrics> {
    // Get all GRU units
    const gruUnits = await prisma.gruUnit.findMany({
      where: { status: 'active' },
    });

    // Calculate supply by class (placeholder - would need proper aggregation)
    const supply = {
      m00: 0,
      m0: 0,
      m1: 0,
      sr1: 0,
      sr2: 0,
      sr3: 0,
    };

    // Check locked status (placeholder)
    const locked = {
      m00: false,
      m0: false,
      m1: false,
      sr1: false,
      sr2: false,
      sr3: false,
    };

    return { supply, locked };
  }

  /**
   * Get GRU indexes
   */
  async getGRUIndexes(): Promise<GRUIndexInfo[]> {
    const indexes = await prisma.gruIndex.findMany({
      where: { status: 'active' },
      include: {
        priceHistory: {
          orderBy: { timestamp: 'desc' },
          take: 100,
        },
      },
    });

    return indexes.map((index) => ({
      indexId: index.indexId,
      indexName: index.indexName,
      indexCode: index.indexCode,
      currentPrice: index.priceHistory.length > 0
        ? parseFloat(index.priceHistory[0].price.toString())
        : 0,
      components: (index.components as Array<{ asset: string; weight: number }>) || [],
      priceHistory: index.priceHistory.map((ph) => ({
        timestamp: ph.timestamp,
        price: parseFloat(ph.price.toString()),
      })),
      circuitBreakers: {
        maxIntradayMove: parseFloat(index.circuitBreakerThreshold?.toString() || '0.1'),
        enabled: index.circuitBreakerEnabled || false,
      },
    }));
  }

  /**
   * Get GRU bonds
   */
  async getGRUBonds(): Promise<GRUBondInfo[]> {
    const bonds = await prisma.gruBond.findMany({
      where: { status: 'active' },
      include: {
        coupons: true,
        pricing: {
          orderBy: { calculatedAt: 'desc' },
          take: 1,
        },
      },
    });

    return bonds.map((bond) => {
      const latestPricing = bond.pricing[0];
      const yieldValue = latestPricing
        ? parseFloat(latestPricing.yield.toString())
        : 0;

      return {
        bondId: bond.bondId,
        bondName: bond.bondName,
        bondCode: bond.bondCode,
        outstanding: parseFloat(bond.outstandingAmount.toString()),
        buyers: bond.numberOfHolders || 0,
        yield: yieldValue,
        issuanceWindow: bond.issuanceWindowOpen ? 'open' : 'closed',
        primaryMarketParams: {
          minPurchase: parseFloat(bond.minPurchaseAmount?.toString() || '0'),
          maxPurchase: parseFloat(bond.maxPurchaseAmount?.toString() || '0'),
        },
      };
    });
  }

  /**
   * Get GRU supranational pools
   */
  async getGRUSupranationalPools(): Promise<GRUSupranationalPool[]> {
    const pools = await prisma.gruReservePool.findMany({
      where: { status: 'active' },
      include: {
        allocations: {
          include: {
            reserveClass: true,
          },
        },
      },
    });

    return pools.map((pool) => ({
      poolId: pool.poolId,
      poolName: pool.poolName,
      totalReserves: parseFloat(pool.totalReserves.toString()),
      allocations: pool.allocations.map((alloc) => ({
        reserveClass: alloc.reserveClass.className,
        amount: parseFloat(alloc.amount.toString()),
      })),
    }));
  }
}

export const gruCommandService = new GRUCommandService();

