import type { AuditSimulationSectionStatus } from "@prisma/client";
import { AUDIT_SECTION_KEYS, type AuditScoreOutput, type AuditSectionKey } from "@/lib/audits/types";

type AnswerRow = {
  questionKey: string;
  answer: string;
};

type QuestionDefinition = {
  key: string;
  section: AuditSectionKey;
  prompt: string;
};

export const AUDIT_QUESTIONNAIRE: QuestionDefinition[] = [
  {
    key: "fiscal_obligaciones_al_dia",
    section: "cumplimiento_fiscal",
    prompt: "La empresa tiene cumplimiento fiscal actualizado?",
  },
  {
    key: "fiscal_opinion_positiva_sat",
    section: "cumplimiento_fiscal",
    prompt: "Cuenta con opinion positiva del SAT vigente?",
  },
  {
    key: "laboral_imss_infonavit",
    section: "cumplimiento_laboral",
    prompt: "Existen evidencias de cumplimiento IMSS/INFONAVIT?",
  },
  {
    key: "laboral_expedientes_personal",
    section: "cumplimiento_laboral",
    prompt: "Se mantienen expedientes laborales completos?",
  },
  {
    key: "legal_contratos_resguardados",
    section: "documentacion_legal",
    prompt: "Los contratos y anexos se encuentran resguardados?",
  },
  {
    key: "legal_actas_poderes",
    section: "documentacion_legal",
    prompt: "Las actas/poderes estan actualizados y disponibles?",
  },
  {
    key: "operativo_control_entregables",
    section: "control_operativo",
    prompt: "Existe control formal de entregables y evidencias?",
  },
  {
    key: "operativo_seguimiento_pagos",
    section: "control_operativo",
    prompt: "Se monitorean pagos y facturacion con trazabilidad?",
  },
  {
    key: "finanzas_conciliaciones",
    section: "transparencia_financiera",
    prompt: "Hay conciliaciones y soporte de movimientos financieros?",
  },
  {
    key: "finanzas_reportes_riesgo",
    section: "transparencia_financiera",
    prompt: "Se generan reportes de riesgo y controles preventivos?",
  },
];

const ANSWER_SCORE_MAP: Record<string, number> = {
  si: 100,
  yes: 100,
  parcial: 60,
  partial: 60,
  en_proceso: 60,
  no: 20,
};

function normalizeAnswer(answer: string) {
  return answer
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .trim()
    .replace(/\s+/g, "_");
}

function scoreAnswer(answer: string) {
  const normalized = normalizeAnswer(answer);
  return ANSWER_SCORE_MAP[normalized] ?? 40;
}

function scoreToStatus(score: number): AuditSimulationSectionStatus {
  if (score >= 80) {
    return "READY";
  }

  if (score >= 50) {
    return "WARNING";
  }

  return "CRITICAL";
}

export function scoreAuditResponses(rows: AnswerRow[]): AuditScoreOutput {
  const answersByQuestion = new Map(rows.map((row) => [row.questionKey, row.answer]));
  const sectionAccumulator = new Map<AuditSectionKey, { total: number; count: number; missing: number }>();

  for (const key of AUDIT_SECTION_KEYS) {
    sectionAccumulator.set(key, { total: 0, count: 0, missing: 0 });
  }

  for (const question of AUDIT_QUESTIONNAIRE) {
    const answer = answersByQuestion.get(question.key);
    const bucket = sectionAccumulator.get(question.section);

    if (!bucket) {
      continue;
    }

    if (!answer) {
      bucket.missing += 1;
      continue;
    }

    bucket.total += scoreAnswer(answer);
    bucket.count += 1;
  }

  const sections = AUDIT_SECTION_KEYS.map((sectionKey) => {
    const bucket = sectionAccumulator.get(sectionKey) ?? { total: 0, count: 0, missing: 0 };
    const score = bucket.count > 0 ? Math.round(bucket.total / bucket.count) : 0;
    const status = scoreToStatus(score);

    const findings: string[] = [];
    const recommendations: string[] = [];

    if (bucket.missing > 0) {
      findings.push(`${bucket.missing} reactivos sin respuesta en esta seccion.`);
    }

    if (status === "CRITICAL") {
      findings.push("Riesgo critico de incumplimiento en esta seccion.");
      recommendations.push("Implementar plan correctivo inmediato y evidencia documental.");
    } else if (status === "WARNING") {
      findings.push("Se identifican brechas relevantes de control.");
      recommendations.push("Cerrar brechas operativas con responsables y fechas.");
    } else {
      findings.push("Seccion con nivel operativo favorable.");
      recommendations.push("Mantener controles y actualizar evidencia periodicamente.");
    }

    return {
      key: sectionKey,
      score,
      status,
      findings,
      recommendations,
    };
  });

  const overallScore = sections.length > 0 ? Math.round(sections.reduce((sum, item) => sum + item.score, 0) / sections.length) : 0;

  return {
    overallScore,
    sections,
  };
}
