from __future__ import annotations

import shutil
import subprocess
import textwrap
import unittest
from pathlib import Path


class CaseUploadDialogJavaScriptTest(unittest.TestCase):
    def test_includes_non_persistent_placeholder_for_redacted_identity(self) -> None:
        source = Path("static/js/case-upload-dialog.js").read_text(encoding="utf-8")

        self.assertIn('redactedFields.has("patient_id")', source)
        self.assertIn('redactedFields.has("patient_name")', source)
        self.assertIn("Dato censurado por protección", source)
        self.assertNotIn('value = "Dato censurado por protección"', source)

    def test_projects_external_failure_and_retry_contract(self) -> None:
        node = shutil.which("node") or shutil.which("nodejs")
        if not node:
            self.skipTest("node no está disponible en el entorno de pruebas")

        script = textwrap.dedent(
            """
            const fs = require("node:fs");
            const vm = require("node:vm");
            const source = fs.readFileSync("static/js/case-upload-dialog.js", "utf8");
            vm.runInThisContext(source, { filename: "case-upload-dialog.js" });

            const external = globalThis.CaseUploadDialog._test.describeFailure({
              status: "fallido",
              can_retry: true,
              failure: {
                source: "external_provider",
                public_title: "Servicio externo temporalmente no disponible",
                public_message:
                  "El servicio externo de IA está temporalmente no disponible. " +
                  "El documento fue recibido correctamente y permanece guardado; " +
                  "no necesitas cargarlo nuevamente.",
              },
            });
            if (!external.canRetry) throw new Error("El reintento recuperable debe ser visible.");
            if (external.source !== "external_provider") throw new Error("Fuente externa incorrecta.");
            if (!external.title.includes("Servicio externo")) throw new Error("Título externo incorrecto.");
            if (!external.message.includes("no necesitas cargarlo nuevamente")) {
              throw new Error("El mensaje debe evitar cargas duplicadas.");
            }

            const documentFailure = globalThis.CaseUploadDialog._test.describeFailure({
              status: "fallido",
              can_retry: false,
              error: "El PDF no contiene texto extraíble.",
              failure: { source: "document" },
            });
            if (documentFailure.canRetry) throw new Error("Un error documental no debe reintentarse.");
            if (documentFailure.message !== "El PDF no contiene texto extraíble.") {
              throw new Error("Debe conservarse el mensaje documental.");
            }
            """
        )

        completed = subprocess.run(
            [node, "-e", script],
            cwd=".",
            check=False,
            capture_output=True,
            text=True,
        )

        self.assertEqual(completed.returncode, 0, completed.stderr or completed.stdout)
