// Limits & Velocity Service
// Manages per-user/account/merchant limits and time-windowed controls

import { v4 as uuidv4 } from 'uuid';
import prisma from '@/shared/database/prisma';
import { Decimal } from '@prisma/client/runtime/library';
import { DbisError, ErrorCode } from '@/shared/types';
import { logger } from '@/infrastructure/monitoring/logger';

export interface Limit {
  id: string;
  entityType: 'user' | 'account' | 'merchant' | 'tenant';
  entityId: string;
  limitType: 'daily' | 'weekly' | 'monthly' | 'transaction' | 'velocity';
  amount: string; // Decimal as string
  currencyCode: string;
  windowStart: Date;
  windowEnd: Date;
  currentUsage: string;
  status: 'active' | 'suspended' | 'exceeded';
  createdAt: Date;
  updatedAt: Date;
}

export interface CreateLimitRequest {
  entityType: 'user' | 'account' | 'merchant' | 'tenant';
  entityId: string;
  limitType: 'daily' | 'weekly' | 'monthly' | 'transaction' | 'velocity';
  amount: string;
  currencyCode: string;
  windowStart?: Date;
  windowEnd?: Date;
}

export interface CheckLimitRequest {
  entityType: 'user' | 'account' | 'merchant' | 'tenant';
  entityId: string;
  limitType: 'daily' | 'weekly' | 'monthly' | 'transaction' | 'velocity';
  amount: string;
  currencyCode: string;
}

// Note: This would use a separate limits table in production
// For now, using a simplified in-memory approach with Prisma
// In production, create a solacenet_limits table

export class LimitsService {
  /**
   * Create a limit
   */
  async createLimit(request: CreateLimitRequest): Promise<Limit> {
    const windowStart = request.windowStart || new Date();
    const windowEnd = request.windowEnd || this.calculateWindowEnd(windowStart, request.limitType);

    // In production, store in database
    // For now, return a mock limit
    const limit: Limit = {
      id: uuidv4(),
      entityType: request.entityType,
      entityId: request.entityId,
      limitType: request.limitType,
      amount: request.amount,
      currencyCode: request.currencyCode,
      windowStart,
      windowEnd,
      currentUsage: '0',
      status: 'active',
      createdAt: new Date(),
      updatedAt: new Date(),
    };

    logger.info(`Limit created`, {
      entityType: request.entityType,
      entityId: request.entityId,
      limitType: request.limitType,
    });

    return limit;
  }

  /**
   * Check if a transaction would exceed limits
   */
  async checkLimit(request: CheckLimitRequest): Promise<{ allowed: boolean; reason?: string }> {
    const amount = new Decimal(request.amount);
    const currentUsage = new Decimal('0'); // In production, fetch from database

    // In production, query limits from database
    // For now, return allowed
    // This is a placeholder - implement proper limit checking

    return { allowed: true };
  }

  /**
   * Record usage (increment limit usage)
   */
  async recordUsage(
    entityType: 'user' | 'account' | 'merchant' | 'tenant',
    entityId: string,
    limitType: 'daily' | 'weekly' | 'monthly' | 'transaction' | 'velocity',
    amount: string,
    currencyCode: string
  ): Promise<void> {
    // In production, update limit usage in database
    logger.info(`Limit usage recorded`, {
      entityType,
      entityId,
      limitType,
      amount,
      currencyCode,
    });
  }

  /**
   * Calculate window end based on limit type
   */
  private calculateWindowEnd(start: Date, limitType: string): Date {
    const end = new Date(start);
    switch (limitType) {
      case 'daily':
        end.setDate(end.getDate() + 1);
        break;
      case 'weekly':
        end.setDate(end.getDate() + 7);
        break;
      case 'monthly':
        end.setMonth(end.getMonth() + 1);
        break;
      default:
        end.setDate(end.getDate() + 1);
    }
    return end;
  }
}

export const limitsService = new LimitsService();
