// Jurisdictional Law Review Service
// Integrates with jurisdictional law database for compliance

import prisma from '@/shared/database/prisma';
import { logger } from '@/infrastructure/monitoring/logger';
import { retryWithBackoff } from '@/shared/utils/retry';

export interface JurisdictionalLaw {
  jurisdiction: string; // ISO 3166-1 alpha-2 country code
  lawName: string;
  lawType: 'banking' | 'securities' | 'payment' | 'data_protection' | 'sanctions' | 'other';
  requirements: string[];
  restrictions: string[];
  complianceNotes?: string;
  lastUpdated: Date;
}

export interface LawReviewResult {
  jurisdiction: string;
  compliant: boolean;
  applicableLaws: JurisdictionalLaw[];
  requirements: string[];
  restrictions: string[];
  recommendations: string[];
  riskLevel: 'low' | 'medium' | 'high';
}

export class JurisdictionalLawService {
  /**
   * Review jurisdictional laws for compliance
   */
  async reviewJurisdictionalLaws(
    jurisdiction: string,
    institutionalType: string,
    activityType: string
  ): Promise<LawReviewResult> {
    // Load laws from database
    const laws = await this.loadJurisdictionalLaws(jurisdiction);

    // Filter applicable laws
    const applicableLaws = laws.filter((law) => this.isLawApplicable(law, institutionalType, activityType));

    // Extract requirements and restrictions
    const requirements: string[] = [];
    const restrictions: string[] = [];

    for (const law of applicableLaws) {
      requirements.push(...law.requirements);
      restrictions.push(...law.restrictions);
    }

    // Assess compliance
    const compliant = restrictions.length === 0;
    const riskLevel = this.assessRiskLevel(applicableLaws, restrictions);

    // Generate recommendations
    const recommendations = this.generateRecommendations(applicableLaws, restrictions);

    return {
      jurisdiction,
      compliant,
      applicableLaws,
      requirements,
      restrictions,
      recommendations,
      riskLevel,
    };
  }

  /**
   * Load jurisdictional laws from database
   */
  private async loadJurisdictionalLaws(jurisdiction: string): Promise<JurisdictionalLaw[]> {
    try {
      const dbLaws = await prisma.iruJurisdictionalLaw.findMany({
        where: {
          jurisdiction,
          status: 'active',
        },
      });

      return dbLaws.map((law) => ({
        jurisdiction: law.jurisdiction,
        lawName: law.lawName,
        lawType: law.lawType as JurisdictionalLaw['lawType'],
        requirements: (law.requirements as string[]) || [],
        restrictions: (law.restrictions as string[]) || [],
        complianceNotes: law.complianceNotes || undefined,
        lastUpdated: law.lastUpdated,
      }));
    } catch (error) {
      logger.warn('Failed to load jurisdictional laws from database', {
        jurisdiction,
        error: error instanceof Error ? error.message : 'Unknown error',
      });

      // Fallback to default laws
      return this.getDefaultLaws(jurisdiction);
    }
  }

  /**
   * Get default laws (fallback)
   */
  private getDefaultLaws(jurisdiction: string): JurisdictionalLaw[] {
    // Default laws for common jurisdictions
    const defaultLaws: Record<string, JurisdictionalLaw[]> = {
      US: [
        {
          jurisdiction: 'US',
          lawName: 'Bank Secrecy Act',
          lawType: 'banking',
          requirements: ['AML compliance', 'KYC verification', 'Transaction reporting'],
          restrictions: [],
          lastUpdated: new Date(),
        },
      ],
      EU: [
        {
          jurisdiction: 'EU',
          lawName: 'GDPR',
          lawType: 'data_protection',
          requirements: ['Data protection', 'Privacy by design', 'Right to erasure'],
          restrictions: [],
          lastUpdated: new Date(),
        },
      ],
    };

    return defaultLaws[jurisdiction] || [];
  }

  /**
   * Check if law is applicable
   */
  private isLawApplicable(
    law: JurisdictionalLaw,
    institutionalType: string,
    activityType: string
  ): boolean {
    // Simple applicability check
    // In production, this would be more sophisticated
    if (law.lawType === 'banking' && institutionalType.includes('Bank')) {
      return true;
    }
    if (law.lawType === 'payment' && activityType.includes('payment')) {
      return true;
    }
    return true; // Default to applicable
  }

  /**
   * Assess risk level
   */
  private assessRiskLevel(laws: JurisdictionalLaw[], restrictions: string[]): 'low' | 'medium' | 'high' {
    if (restrictions.length > 3) {
      return 'high';
    }
    if (restrictions.length > 0) {
      return 'medium';
    }
    if (laws.length > 5) {
      return 'medium';
    }
    return 'low';
  }

  /**
   * Generate recommendations
   */
  private generateRecommendations(laws: JurisdictionalLaw[], restrictions: string[]): string[] {
    const recommendations: string[] = [];

    if (restrictions.length > 0) {
      recommendations.push('Review restrictions with legal counsel');
    }

    if (laws.some((law) => law.lawType === 'data_protection')) {
      recommendations.push('Ensure GDPR/data protection compliance');
    }

    if (laws.some((law) => law.lawType === 'sanctions')) {
      recommendations.push('Conduct sanctions screening');
    }

    return recommendations;
  }

  /**
   * Update jurisdictional law database
   */
  async updateLawDatabase(laws: JurisdictionalLaw[]): Promise<void> {
    for (const law of laws) {
      await prisma.iruJurisdictionalLaw.upsert({
        where: {
          jurisdiction_lawName: {
            jurisdiction: law.jurisdiction,
            lawName: law.lawName,
          },
        },
        create: {
          id: `law-${Date.now()}`,
          jurisdiction: law.jurisdiction,
          lawName: law.lawName,
          lawType: law.lawType,
          requirements: law.requirements,
          restrictions: law.restrictions,
          complianceNotes: law.complianceNotes,
          status: 'active',
          lastUpdated: law.lastUpdated,
          createdAt: new Date(),
          updatedAt: new Date(),
        },
        update: {
          lawType: law.lawType,
          requirements: law.requirements,
          restrictions: law.restrictions,
          complianceNotes: law.complianceNotes,
          lastUpdated: law.lastUpdated,
          updatedAt: new Date(),
        },
      });
    }
  }
}

export const jurisdictionalLawService = new JurisdictionalLawService();
