// IRU Marketplace Service
// Business logic for Sankofa Phoenix Marketplace

import { randomBytes } from 'crypto';
import prisma from '@/shared/database/prisma';
import { v4 as uuidv4 } from 'uuid';
import { DbisError, ErrorCode } from '@/shared/types';
import { logger } from '@/infrastructure/monitoring/logger';

export interface MarketplaceOffering {
  id: string;
  offeringId: string;
  name: string;
  description?: string;
  capacityTier: number;
  institutionalType: string;
  pricingModel: string;
  basePrice?: number;
  currency: string;
  features?: any;
  technicalSpecs?: any;
  legalFramework?: any;
  regulatoryPosition?: any;
  documents?: any;
  status: string;
  displayOrder: number;
}

export interface InquiryRequest {
  offeringId: string;
  organizationName: string;
  institutionalType: string;
  jurisdiction: string;
  contactEmail: string;
  contactPhone?: string;
  contactName: string;
  estimatedVolume?: string;
  expectedGoLive?: Date;
}

export interface InquiryResponse {
  inquiryId: string;
  status: string;
  message: string;
}

export class MarketplaceService {
  /**
   * Get all active IRU offerings
   */
  async getOfferings(filters?: {
    capacityTier?: number;
    institutionalType?: string;
    status?: string;
  }): Promise<MarketplaceOffering[]> {
    const where: any = {
      status: 'active',
    };

    if (filters?.capacityTier) {
      where.capacityTier = filters.capacityTier;
    }

    if (filters?.institutionalType) {
      where.institutionalType = filters.institutionalType;
    }

    if (filters?.status) {
      where.status = filters.status;
    }

    const offerings = await prisma.iruOffering.findMany({
      where,
      orderBy: [
        { displayOrder: 'asc' },
        { capacityTier: 'asc' },
        { name: 'asc' },
      ],
    });

    return offerings.map((offering) => ({
      id: offering.id,
      offeringId: offering.offeringId,
      name: offering.name,
      description: offering.description || undefined,
      capacityTier: offering.capacityTier,
      institutionalType: offering.institutionalType,
      pricingModel: offering.pricingModel,
      basePrice: offering.basePrice ? Number(offering.basePrice) : undefined,
      currency: offering.currency,
      features: offering.features,
      technicalSpecs: offering.technicalSpecs,
      legalFramework: offering.legalFramework,
      regulatoryPosition: offering.regulatoryPosition,
      documents: offering.documents,
      status: offering.status,
      displayOrder: offering.displayOrder,
    }));
  }

  /**
   * Get offering by ID
   */
  async getOfferingById(offeringId: string): Promise<MarketplaceOffering | null> {
    const offering = await prisma.iruOffering.findUnique({
      where: { offeringId },
    });

    if (!offering) {
      return null;
    }

    return {
      id: offering.id,
      offeringId: offering.offeringId,
      name: offering.name,
      description: offering.description || undefined,
      capacityTier: offering.capacityTier,
      institutionalType: offering.institutionalType,
      pricingModel: offering.pricingModel,
      basePrice: offering.basePrice ? Number(offering.basePrice) : undefined,
      currency: offering.currency,
      features: offering.features,
      technicalSpecs: offering.technicalSpecs,
      legalFramework: offering.legalFramework,
      regulatoryPosition: offering.regulatoryPosition,
      documents: offering.documents,
      status: offering.status,
      displayOrder: offering.displayOrder,
    };
  }

  /**
   * Submit initial inquiry
   */
  async submitInquiry(request: InquiryRequest): Promise<InquiryResponse> {
    // Validate offering exists
    const offering = await prisma.iruOffering.findUnique({
      where: { offeringId: request.offeringId },
    });

    if (!offering) {
      throw new DbisError(ErrorCode.NOT_FOUND, `Offering ${request.offeringId} not found`);
    }

    if (offering.status !== 'active') {
      throw new DbisError(ErrorCode.VALIDATION_ERROR, `Offering ${request.offeringId} is not active`);
    }

    // Check for duplicate inquiry from same email
    const existingInquiry = await prisma.iruInquiry.findFirst({
      where: {
        contactEmail: request.contactEmail,
        offeringId: offering.id,
        status: {
          in: ['submitted', 'acknowledged', 'in_review'],
        },
      },
    });

    if (existingInquiry) {
      throw new DbisError(
        ErrorCode.VALIDATION_ERROR,
        'An active inquiry already exists for this email and offering'
      );
    }

    // Unpredictable public id (INQ- + 32 hex) for unauthenticated status lookups
    const inquiryId = `INQ-${randomBytes(16).toString('hex').toUpperCase()}`;
    const inquiry = await prisma.iruInquiry.create({
      data: {
        id: uuidv4(),
        inquiryId,
        offeringId: offering.id,
        organizationName: request.organizationName,
        institutionalType: request.institutionalType,
        jurisdiction: request.jurisdiction,
        contactEmail: request.contactEmail,
        contactPhone: request.contactPhone,
        contactName: request.contactName,
        estimatedVolume: request.estimatedVolume,
        expectedGoLive: request.expectedGoLive,
        status: 'submitted',
        submittedAt: new Date(),
      },
    });

    // Send notification to DBIS sales team
    try {
      const { notificationService } = await import('@/core/iru/notifications/notification.service');
      await notificationService.sendNotification({
        recipient: process.env.DBIS_SALES_EMAIL || 'sales@dbis.org',
        recipientType: 'email',
        template: 'inquiry-submitted',
        variables: {
          inquiryId: inquiry.inquiryId,
          organizationName: inquiry.organizationName,
          offeringId: offering.offeringId,
        },
        priority: 'high',
      });
    } catch (error) {
      // Log but don't fail inquiry submission
      const { logger } = await import('@/infrastructure/monitoring/logger');
      logger.warn('Failed to send inquiry notification to sales team', {
        inquiryId: inquiry.inquiryId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }

    // Send acknowledgment email to participant
    try {
      const { notificationService } = await import('@/core/iru/notifications/notification.service');
      await notificationService.sendNotification({
        recipient: inquiry.contactEmail,
        recipientType: 'email',
        template: 'inquiry-acknowledged',
        variables: {
          inquiryId: inquiry.inquiryId,
          organizationName: inquiry.organizationName,
        },
      });
    } catch (error) {
      // Log but don't fail inquiry submission
      const { logger } = await import('@/infrastructure/monitoring/logger');
      logger.warn('Failed to send acknowledgment email to participant', {
        inquiryId: inquiry.inquiryId,
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }

    return {
      inquiryId: inquiry.inquiryId,
      status: inquiry.status,
      message: 'Inquiry submitted successfully. You will receive an acknowledgment within 24 hours.',
    };
  }

  /**
   * Public inquiry status (unauthenticated). No org/contact, qualification, risk, or notes.
   */
  async getInquiryStatusPublic(inquiryId: string): Promise<{
    inquiryId: string;
    status: string;
    offering: { name: string; capacityTier: number };
    submittedAt: Date;
    acknowledgedAt: Date | null;
    reviewedAt: Date | null;
    completedAt: Date | null;
  }> {
    const inquiry = await prisma.iruInquiry.findUnique({
      where: { inquiryId },
      include: { offering: true },
    });

    if (!inquiry) {
      throw new DbisError(ErrorCode.NOT_FOUND, `Inquiry ${inquiryId} not found`);
    }

    return {
      inquiryId: inquiry.inquiryId,
      status: inquiry.status,
      offering: {
        name: inquiry.offering.name,
        capacityTier: inquiry.offering.capacityTier,
      },
      submittedAt: inquiry.submittedAt,
      acknowledgedAt: inquiry.acknowledgedAt,
      reviewedAt: inquiry.reviewedAt,
      completedAt: inquiry.completedAt,
    };
  }

  /**
   * Full inquiry row (operators / legacy). Prefer getInquiryStatusPublic for public HTTP.
   */
  async getInquiryStatus(inquiryId: string): Promise<any> {
    const inquiry = await prisma.iruInquiry.findUnique({
      where: { inquiryId },
      include: {
        offering: true,
      },
    });

    if (!inquiry) {
      throw new DbisError(ErrorCode.NOT_FOUND, `Inquiry ${inquiryId} not found`);
    }

    return {
      inquiryId: inquiry.inquiryId,
      status: inquiry.status,
      organizationName: inquiry.organizationName,
      offering: {
        name: inquiry.offering.name,
        capacityTier: inquiry.offering.capacityTier,
      },
      submittedAt: inquiry.submittedAt,
      acknowledgedAt: inquiry.acknowledgedAt,
      reviewedAt: inquiry.reviewedAt,
      completedAt: inquiry.completedAt,
      qualificationResult: inquiry.qualificationResult,
      capacityTier: inquiry.capacityTier,
      riskScore: inquiry.riskScore ? Number(inquiry.riskScore) : undefined,
      notes: inquiry.notes,
    };
  }

  /**
   * Calculate pricing for an offering
   */
  async calculatePricing(offeringId: string, usageProfile?: any): Promise<any> {
    const offering = await prisma.iruOffering.findUnique({
      where: { offeringId },
    });

    if (!offering) {
      throw new DbisError(ErrorCode.NOT_FOUND, `Offering ${offeringId} not found`);
    }

    const basePrice = offering.basePrice ? Number(offering.basePrice) : 0;

    // Dynamic pricing: base + usage-based when usage profile available
    logger.debug('Calculating pricing for offering', { offeringId, basePrice, capacityTier: offering.capacityTier });
    return {
      offeringId: offering.offeringId,
      capacityTier: offering.capacityTier,
      basePrice,
      currency: offering.currency,
      pricingModel: offering.pricingModel,
      estimatedMonthlyFee: basePrice, // Placeholder
      estimatedAnnualFee: basePrice * 12, // Placeholder
      breakdown: {
        iruGrantFee: basePrice,
        ongoingFees: {
          infrastructure: basePrice * 0.3,
          capacity: basePrice * 0.2,
          support: basePrice * 0.3,
          compliance: basePrice * 0.2,
        },
      },
    };
  }
}

export const marketplaceService = new MarketplaceService();
