import { describe, it, expect } from "vitest";
import { checkInputSafety, checkOutputSafety, CRISIS_RESPONSE, MEDICAL_RESPONSE } from "../src/utils/safetyGate.js";

describe("checkInputSafety", () => {
    // ── BUCKET 1: True positives — MUST intercept ─────────────────────────
    describe("true positives (crisis intent)", () => {
        const crisisInputs = [
            "I want to hurt myself",
            "I'm going to kill myself",
            "I want to end my life",
            "I want to die",
            "I want to commit suicide",
            "I'm cutting myself",
            "I'm going to hang myself",
            "I'm thinking about jumping off a bridge",
            "how many pills to overdose",
            "how to die by overdose",
        ];
        for (const input of crisisInputs) {
            it(`intercepts: "${input}"`, () => {
                expect(checkInputSafety(input)).toBe(CRISIS_RESPONSE);
            });
        }
    });

    describe("true positives (medical dosing)", () => {
        const medicalInputs = [
            "how much insulin should I inject",
            "what dose should I take of this medication",
            "dosage should I inject for my condition",
        ];
        for (const input of medicalInputs) {
            it(`intercepts: "${input}"`, () => {
                expect(checkInputSafety(input)).toBe(MEDICAL_RESPONSE);
            });
        }
    });

    // ── BUCKET 2: Clinical false positives — must NOT intercept ───────────
    describe("clinical false positives (must pass)", () => {
        const clinicalInputs = [
            "Draft a suicide prevention training plan for staff",
            "Write a suicide risk assessment protocol",
            "Include suicide screening in the intake form",
            "The FBA addresses self-injurious behavior maintained by automatic reinforcement",
            "Write a BIP for a client who engages in self-harm behaviors",
            "Review this safety plan for suicidal ideation",
            "What are evidence-based interventions for suicidal youth?",
            "Draft crisis protocol including suicide assessment",
            "The client takes a dose of risperidone",
            "Describe the lethal dose threshold for acetaminophen in pharmacology class",
            "How many milligrams of melatonin is safe for a 5-year-old?",
        ];
        for (const input of clinicalInputs) {
            it(`does NOT intercept: "${input}"`, () => {
                expect(checkInputSafety(input)).toBeNull();
            });
        }
    });

    // ── i18n crisis input ──────────────────────────────────────────────────
    describe("i18n crisis input (non-English)", () => {
        const i18nCrisis = [
            "quiero morir",                    // Spanish
            "voy a matarme",                   // Spanish
            "je veux mourir",                  // French
            "me suicider",                     // French
            "quero morrer",                    // Portuguese
            "vou me matar",                    // Portuguese
            "хочу умереть",                    // Russian
            "убить себя",                      // Russian
            "покончить с собой",               // Russian
            "أريد أن أموت",                    // Arabic
            "ich will sterben",                // German
            "mich umbringen",                  // German
            "хочу померти",                    // Ukrainian
        ];
        for (const input of i18nCrisis) {
            it(`intercepts: "${input}"`, () => {
                expect(checkInputSafety(input)).toBe(CRISIS_RESPONSE);
            });
        }
    });

    // ── i18n: genuine distress with prepositions (MUST intercept) ──────────
    describe("i18n genuine distress (must intercept despite preposition)", () => {
        const genuineDistress = [
            "quiero morir de verdad",           // Spanish: "I truly want to die"
            "quiero morir de una vez",          // Spanish: "once and for all"
            "quiero morir de dolor",            // Spanish: "die from pain"
            "je veux mourir de désespoir",      // French: "die from despair"
            "je veux mourir d'épuisement",      // French: "die from exhaustion"
            "quero morrer de tristeza",         // Portuguese: "die from sadness"
            "хочу умереть от этой боли",        // Russian: "die from this pain"
            "ich will sterben vor Verzweiflung", // German: "die from despair"
            "хочу померти від розпачу",         // Ukrainian: "die from despair"
        ];
        for (const input of genuineDistress) {
            it(`intercepts genuine: "${input}"`, () => {
                expect(checkInputSafety(input)).toBe(CRISIS_RESPONSE);
            });
        }
    });

    describe("i18n false positives — benign + hyperbolic idioms (must NOT intercept)", () => {
        const i18nSafe = [
            "quiero comer",                    // Spanish: "I want to eat"
            "je veux manger",                  // French: "I want to eat"
            "quero brincar",                   // Portuguese: "I want to play"
            "хочу спать",                      // Russian: "I want to sleep"
            "ich will spielen",                // German: "I want to play"
            // Hyperbolic idioms — everyday expressions, especially from kids
            "quiero morir de risa",            // Spanish: "dying of laughter"
            "quiero morir de vergüenza",       // Spanish: "dying of embarrassment"
            "voy a matarme estudiando",        // Spanish: "killing myself studying"
            "je veux mourir de honte",         // French: "dying of shame"
            "je veux mourir de rire",          // French: "dying of laughter"
            "je veux mourir d'envie",          // French: "dying to / eager to"
            "quero morrer de rir",             // Portuguese: "dying of laughter"
            "хочу умереть от смеха",           // Russian: "dying of laughter"
            "ich will sterben vor Lachen",     // German: "dying of laughter"
            "хочу померти від сміху",          // Ukrainian: "dying of laughter"
        ];
        for (const input of i18nSafe) {
            it(`does NOT intercept: "${input}"`, () => {
                expect(checkInputSafety(input)).toBeNull();
            });
        }
    });

    // ── Arabic orthography variations ──────────────────────────────────────
    describe("Arabic orthography (alef variants + harakat)", () => {
        it("catches casual Arabic without hamza (اريد ان اموت)", () => {
            expect(checkInputSafety("اريد ان اموت")).toBe(CRISIS_RESPONSE);
        });
        it("catches diacritized Arabic (أُرِيدُ أَنْ أَمُوتَ)", () => {
            expect(checkInputSafety("أُرِيدُ أَنْ أَمُوتَ")).toBe(CRISIS_RESPONSE);
        });
        it("catches alef-madda variant (آريد)", () => {
            expect(checkInputSafety("آريد أن أموت")).toBe(CRISIS_RESPONSE);
        });
    });

    // ── BUCKET 3: Known evasion limits (documented, not intercepted) ──────
    describe("known evasion limits (documented out of scope)", () => {
        const evasions = [
            "k i l l m y s e l f",        // intra-letter spacing
            "unalive myself",              // euphemism
            "kïll myself",                 // diacritics
        ];
        for (const input of evasions) {
            it(`does NOT catch (known limit): "${input}"`, () => {
                expect(checkInputSafety(input)).toBeNull();
            });
        }
    });
});

describe("checkOutputSafety", () => {
    // ── BUCKET 1: True positives — model providing dangerous instructions ─
    describe("true positives (dangerous output)", () => {
        it("intercepts suicide method instructions", () => {
            expect(checkOutputSafety("Here is a suicide method you can use")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts overdose amount", () => {
            expect(checkOutputSafety("The overdose amount for this drug is")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts noose instructions", () => {
            expect(checkOutputSafety("To make a noose you need")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts hanging instructions", () => {
            expect(checkOutputSafety("Try hanging yourself from")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts how-to-kill-yourself", () => {
            expect(checkOutputSafety("Here is how to kill yourself")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts how-to-kill-himself", () => {
            expect(checkOutputSafety("Instructions on how to kill himself")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts how-to-overdose", () => {
            expect(checkOutputSafety("Here is how to overdose on pills")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts self-harm method", () => {
            expect(checkOutputSafety("A common self-harm method is")).toBe(CRISIS_RESPONSE);
        });
        it("intercepts inject-this-amount", () => {
            expect(checkOutputSafety("You should inject this amount of insulin")).toBe(MEDICAL_RESPONSE);
        });
        it("intercepts take-this-amount", () => {
            expect(checkOutputSafety("Take this amount of pills every day")).toBe(MEDICAL_RESPONSE);
        });
    });

    // ── BUCKET 2: Clinical false positives — must NOT intercept ───────────
    describe("clinical false positives (must pass through)", () => {
        const clinicalOutputs = [
            "The client takes a dose of risperidone, 2 milligrams nightly",
            "Acetaminophen has a known lethal dose; never exceed label limits",
            "The BIP notes that the medication dose of 5mg was effective",
            "Baseline data shows 3 milligrams of melatonin at bedtime",
            "The timeout is in milligrams? No, milliseconds",
            "Review the dose of the prescribed antipsychotic with the psychiatrist",
            "The lethal toxicity threshold varies by body weight",
            "Current prescription: 10 units of insulin daily per endocrinologist",
            "Staff should document the dose of PRN medication administered",
            "The client's suicide risk assessment score decreased from 8 to 3",
        ];
        for (const output of clinicalOutputs) {
            it(`passes through: "${output.slice(0, 60)}..."`, () => {
                expect(checkOutputSafety(output)).toBe(output);
            });
        }
    });

    // ── BUCKET 2b: Coding false positives — must NOT intercept ──────────
    describe("coding false positives (must pass through)", () => {
        const codingOutputs = [
            "Use `kill -9` to kill the process immediately",
            "Here's how to kill a hung thread in Java using Thread.interrupt()",
            "To kill a pod in Kubernetes: kubectl delete pod <name>",
            "How to kill all node processes: pkill -f node",
            "The kill command sends SIGTERM to the specified PID",
            "Use kill -SIGKILL to forcefully kill the daemon",
            "How to kill a background job: kill %1",
            "Docker: how to kill a container — docker kill <id>",
            "How to hang a picture frame on drywall",
            "How to hang up a call in Twilio using hangUp()",
            "How to hang curtains without drilling",
            "How to hang the splash screen until fonts load",
            "How to poison the DNS cache for testing",
            "A poison pill message terminates the consumer",
            "How to poison a queue to trigger dead-letter routing",
        ];
        for (const output of codingOutputs) {
            it(`passes through: "${output.slice(0, 60)}..."`, () => {
                expect(checkOutputSafety(output)).toBe(output);
            });
        }
    });
});
