import { NextRequest, NextResponse } from 'next/server';
import { getSession } from '@/lib/auth';
import { generateComplianceReportWord, getDefaultComplianceReportData } from '@/lib/compliance-report';

function formatFrameworkLabel(framework: string): string {
  const key = framework.toLowerCase();
  if (key === 'gdpr') return 'GDPR';
  if (key === 'sox') return 'SOX';
  if (key === 'pci') return 'PCI DSS';
  if (key === 'hipaa') return 'HIPAA';
  if (key === 'iso27001') return 'ISO/IEC 27001';
  return framework.toUpperCase();
}

const FRAMEWORK_PROFILES: Record<string, { rationale: string; profile: string }> = {
  gdpr: {
    rationale: 'Application processes or may process personal data of EU/EEA data subjects; GDPR applies to any controller or processor regardless of establishment.',
    profile: 'Regulation (EU) 2016/679 — full text; EDPB guidelines applied where available',
  },
  sox: {
    rationale: 'Organisation is a US-listed public company or subsidiary thereof; migrated system supports financial reporting or IT General Controls (ITGC) relevant to §302/§404.',
    profile: 'Sarbanes-Oxley Act (2002) §302 / §404; PCAOB AS 2201; COSO 2013 framework',
  },
  pci: {
    rationale: 'System stores, processes or transmits cardholder data or is connected to the Cardholder Data Environment (CDE).',
    profile: 'PCI DSS v4.0 (March 2022) — all requirements; SAQ-D scope assumed',
  },
  hipaa: {
    rationale: 'Organisation qualifies as a Covered Entity or Business Associate under 45 CFR §160; system may access, create or transmit ePHI.',
    profile: 'HIPAA Security Rule (45 CFR §164.302–318); HITECH Act amendments; OCR guidance 2023',
  },
  iso27001: {
    rationale: 'Organisation pursues ISO/IEC 27001 certification or contractual alignment; migrated codebase is in scope of the ISMS boundary.',
    profile: 'ISO/IEC 27001:2022 — Annex A controls; ISO/IEC 27002:2022 supplementary guidance',
  },
};

function applyFrameworkScope(reportData: ReturnType<typeof getDefaultComplianceReportData>, selected: string[]) {
  const selectedSet = new Set(selected.map((item) => item.toLowerCase()));

  for (const fwKey of ['gdpr', 'sox', 'pci', 'hipaa', 'iso27001'] as const) {
    const inScope = selectedSet.has(fwKey);
    const fw = reportData.applicability[fwKey];
    fw.in_scope = inScope ? 'Yes' : 'No';
    if (FRAMEWORK_PROFILES[fwKey]) {
      fw.rationale = inScope
        ? FRAMEWORK_PROFILES[fwKey].rationale
        : 'Framework was not selected as in scope for this engagement.';
      fw.profile = inScope ? FRAMEWORK_PROFILES[fwKey].profile : '—';
    }
  }
}

const LANGUAGE_FRAMEWORKS: Record<string, { runtime: string; frameworks: string }> = {
  cobol: {
    runtime: 'COBOL (IBM Enterprise COBOL / Micro Focus)',
    frameworks: 'CICS, JCL batch, VSAM/DB2, MQ Series',
  },
  java: {
    runtime: 'Java 17 (LTS) / JVM',
    frameworks: 'Spring Boot 3.x, Maven/Gradle, JDBC/JPA, SLF4J',
  },
  python: {
    runtime: 'Python 3.11',
    frameworks: 'FastAPI / Django, SQLAlchemy, Pytest',
  },
  csharp: {
    runtime: '.NET 8 / CLR',
    frameworks: 'ASP.NET Core, Entity Framework Core, NUnit',
  },
  typescript: {
    runtime: 'Node.js 20 LTS / TypeScript 5',
    frameworks: 'Express / NestJS, Prisma, Jest',
  },
  javascript: {
    runtime: 'Node.js 20 LTS',
    frameworks: 'Express, Sequelize, Mocha/Jest',
  },
  rpg: {
    runtime: 'IBM RPG IV / ILE',
    frameworks: 'DB2 for i, CL programs, RPGLE service programs',
  },
  pl1: {
    runtime: 'PL/I (IBM Enterprise PL/I)',
    frameworks: 'CICS, JCL batch, VSAM/DB2',
  },
};

function resolveLanguageInfo(lang: string | undefined): { runtime: string; frameworks: string } | null {
  if (!lang) return null;
  const key = lang.toLowerCase().replace(/[^a-z0-9]/g, '');
  return LANGUAGE_FRAMEWORKS[key] ?? null;
}

export async function POST(request: NextRequest) {
  try {
    const accessToken = request.cookies.get('scriba.access_token')?.value;
    const session = await getSession(accessToken);

    if (!session) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const body = await request.json();
    const { projectName, framework, project } = body;

    // Use provided data or generate default, then merge with project info
    const providedData = body.reportData;
    const defaultData = getDefaultComplianceReportData(projectName || 'Default Project');

    // Deep merge helper
    const deepMerge = (target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown> => {
      for (const key in source) {
        if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
          target[key] = deepMerge((target[key] as Record<string, unknown>) || {}, source[key] as Record<string, unknown>);
        } else if (source[key] !== undefined && source[key] !== null) {
          target[key] = source[key];
        }
      }
      return target;
    };

    // Start with defaults, then overlay provided data
    const reportData = deepMerge(
      JSON.parse(JSON.stringify(defaultData)),
      providedData || {}
    ) as unknown as ReturnType<typeof getDefaultComplianceReportData>;

    // Apply project metadata
    if (project) {
      if (project.id) {
        reportData.project.id = project.id;
        reportData.migration.job_id = `MIG-${project.id}`;
      }
      if (project.name) reportData.project.name = project.name;
      if (project.repoUrl && project.repoUrl !== '') {
        reportData.project.repository = project.repoUrl;
      } else if (reportData.project.repository === 'N/A') {
        reportData.project.repository = 'Internal repository (URL not configured)';
      }
      if (project.createdAt) {
        reportData.migration.date = new Date(project.createdAt).toISOString().split('T')[0];
      }
      if (project.sourceLanguage) {
        reportData.migration.source_language = project.sourceLanguage;
        const srcInfo = resolveLanguageInfo(project.sourceLanguage);
        if (srcInfo) {
          reportData.source.language_runtime = srcInfo.runtime;
          if (reportData.source.frameworks === 'N/A') {
            reportData.source.frameworks = srcInfo.frameworks;
          }
        } else {
          reportData.source.language_runtime = project.sourceLanguage;
        }
      }
      if (project.targetLanguage) {
        reportData.migration.target_language = project.targetLanguage;
        const tgtInfo = resolveLanguageInfo(project.targetLanguage);
        if (tgtInfo) {
          reportData.target.language_runtime = tgtInfo.runtime;
          if (reportData.target.frameworks === 'N/A') {
            reportData.target.frameworks = tgtInfo.frameworks;
          }
        } else {
          reportData.target.language_runtime = project.targetLanguage;
        }
      }
      if (project.config && typeof project.config === 'object') {
        const sourceFrameworks = project.config.sourceFrameworks;
        const targetFrameworks = project.config.targetFrameworks;
        if (Array.isArray(sourceFrameworks) && sourceFrameworks.length > 0) {
          reportData.source.frameworks = sourceFrameworks.join(', ');
        }
        if (Array.isArray(targetFrameworks) && targetFrameworks.length > 0) {
          reportData.target.frameworks = targetFrameworks.join(', ');
        }
      }
      if (Array.isArray(project.selectedCompliance) && project.selectedCompliance.length > 0) {
        reportData.frameworks.list = project.selectedCompliance.map(formatFrameworkLabel).join(', ');
        applyFrameworkScope(reportData, project.selectedCompliance);
      }
    }

    // Apply authenticated user as client name when no other source provides it
    if (reportData.client.name === 'N/A' && session.user?.name) {
      reportData.client.name = session.user.name;
    } else if (reportData.client.name === 'N/A' && session.user?.email) {
      reportData.client.name = session.user.email;
    }

    // Generate Word document
    const buffer = await generateComplianceReportWord(reportData);

    // Return as downloadable Word file
    const filename = `Compliance_Report_${framework || 'All'}_${projectName || 'Project'}_${new Date().toISOString().split('T')[0]}.docx`;

    return new NextResponse(new Uint8Array(buffer), {
      status: 200,
      headers: {
        'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'Content-Disposition': `attachment; filename="${filename}"`,
        'Content-Length': buffer.length.toString(),
      },
    });
  } catch (error) {
    console.error('Error generating compliance report:', error);
    return NextResponse.json({ error: 'Failed to generate compliance report' }, { status: 500 });
  }
}
