from __future__ import annotations

import json
import unittest
from pathlib import Path
from types import SimpleNamespace
import sys

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
sys.path.insert(0, str(ROOT / "scripts"))

import build
import translate_site

from scisiteforge.content import SiteContent, cards_from_config, load_citegeist_cards, load_didactopus_cards, load_doclift_cards, load_groundrecall_cards
from scisiteforge.notebook import load_notebooks, render_notebooks
from scisiteforge.themes import get_theme, materialize_theme
from scisiteforge.translations import GenieHiveTranslator, TranslationConfig


class SciSiteForgeTests(unittest.TestCase):
    def test_theme_materialization_copies_theme_assets(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            theme = get_theme("talkorigins-modern")
            payload = materialize_theme(theme, tmp_path)

            self.assertTrue((tmp_path / "theme" / "style.css").exists())
            self.assertTrue((tmp_path / "theme" / "main.js").exists())
            self.assertTrue((tmp_path / "theme" / "assets" / "toa.ico").exists())
            self.assertTrue((tmp_path / "theme" / "assets" / "toa_logo_001_edit_001.png").exists())
            self.assertEqual(payload["theme_name"], "talkorigins-modern")

    def test_content_loaders_parse_local_repo_artifacts(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)

            doclift_root = tmp_path / "doclift"
            doclift_root.mkdir()
            (doclift_root / "manifest.json").write_text(
                json.dumps(
                    {
                        "documents": [
                            {
                                "document_id": "doc-1",
                                "title": "Legacy Document",
                                "document_kind": "article",
                                "markdown_path": "documents/doc-1/document.md",
                                "source_path": "source/doc-1.html",
                            }
                        ]
                    }
                ),
                encoding="utf-8",
            )
            (doclift_root / "documents" / "doc-1").mkdir(parents=True)
            (doclift_root / "documents" / "doc-1" / "document.md").write_text("First paragraph.\n\nSecond.", encoding="utf-8")

            groundrecall_root = tmp_path / "groundrecall"
            groundrecall_root.mkdir()
            (groundrecall_root / "groundrecall_query_bundle.json").write_text(
                json.dumps(
                    {
                        "concept": {"concept_id": "concept::topic", "title": "GroundRecall Topic"},
                        "summary": "Grounded summary.",
                        "claims": [{"claim_id": "clm-1", "claim_text": "Claim one", "claim_kind": "summary"}],
                    }
                ),
                encoding="utf-8",
            )

            didactopus_root = tmp_path / "didactopus"
            didactopus_root.mkdir()
            (didactopus_root / "pack.yaml").write_text("name: test-pack\ndisplay_name: Test Pack\n", encoding="utf-8")
            (didactopus_root / "concepts.yaml").write_text(
                "concepts:\n  - id: prior\n    title: Prior\n    description: Previous knowledge.\n    prerequisites: []\n",
                encoding="utf-8",
            )

            citegeist_root = tmp_path / "citegeist"
            citegeist_root.mkdir()
            (citegeist_root / "refs.bib").write_text(
                """@article{smith2024,\n  title = {A Study},\n  author = {Smith, Jane and Roe, John},\n  year = {2024}\n}\n""",
                encoding="utf-8",
            )

            doclift_cards = load_doclift_cards(doclift_root)
            groundrecall_cards = load_groundrecall_cards(groundrecall_root)
            didactopus_cards = load_didactopus_cards(didactopus_root)
            citegeist_cards = load_citegeist_cards(citegeist_root)

            self.assertEqual(doclift_cards[0].title, "Legacy Document")
            self.assertEqual(doclift_cards[0].body, "First paragraph.")
            self.assertEqual(groundrecall_cards[0].title, "GroundRecall Topic")
            self.assertEqual(groundrecall_cards[1].title, "Claim one")
            self.assertEqual(didactopus_cards[0].title, "Prior")
            self.assertEqual(citegeist_cards[0].title, "A Study")

    def test_inline_config_cards_can_seed_example_content(self) -> None:
        cards = cards_from_config(
            [
                {
                    "title": "Foundation Search",
                    "body": "Corpus-aware search entry point.",
                    "href": "/search/",
                    "meta": "workbench",
                }
            ],
            default_kind="feature",
        )

        self.assertEqual(cards[0].title, "Foundation Search")
        self.assertEqual(cards[0].kind, "feature")
        self.assertEqual(cards[0].href, "/search/")
        self.assertEqual(cards[0].meta, "workbench")

    def test_build_site_renders_selected_theme_and_content(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            content_root = tmp_path / "content"
            content_root.mkdir()

            doclift_root = content_root / "doclift"
            doclift_root.mkdir()
            (doclift_root / "manifest.json").write_text(
                json.dumps({"documents": [{"document_id": "doc-1", "title": "Legacy Document", "markdown_path": "documents/doc-1/document.md"}]}),
                encoding="utf-8",
            )
            (doclift_root / "documents" / "doc-1").mkdir(parents=True)
            (doclift_root / "documents" / "doc-1" / "document.md").write_text("Doclift content.", encoding="utf-8")

            didactopus_root = content_root / "didactopus"
            didactopus_root.mkdir()
            (didactopus_root / "pack.yaml").write_text("name: test-pack\ndisplay_name: Test Pack\n", encoding="utf-8")
            (didactopus_root / "concepts.yaml").write_text(
                "concepts:\n  - id: prior\n    title: Prior\n    description: Previous knowledge.\n    prerequisites: []\n",
                encoding="utf-8",
            )

            groundrecall_root = content_root / "groundrecall"
            groundrecall_root.mkdir()
            (groundrecall_root / "groundrecall_query_bundle.json").write_text(
                json.dumps({"concept": {"concept_id": "concept::topic", "title": "GroundRecall Topic"}, "summary": "Grounded summary."}),
                encoding="utf-8",
            )

            citegeist_root = content_root / "citegeist"
            citegeist_root.mkdir()
            (citegeist_root / "refs.bib").write_text(
                """@article{smith2024,\n  title = {A Study},\n  author = {Smith, Jane and Roe, John},\n  year = {2024}\n}\n""",
                encoding="utf-8",
            )

            config = {
                "lang": "en",
                "title": "TalkOrigins Preview",
                "site_title": "TalkOrigins Archive",
                "license": "CC BY-SA 4.0",
                "github_url": "https://example.invalid",
                "contact_email": "admin@example.invalid",
                "theme": "talkorigins-modern",
                "languages": [{"code": "en", "name": "English"}],
                "navigation": [{"label": "Home", "href": "/"}],
                "hero": {
                    "kicker": "Archive Preview",
                    "title": "Modernized, reviewable, and still archive-first.",
                    "lede": "Proof-of-concept output from SciSiteForge.",
                    "actions": [{"label": "Open", "href": "#overview", "primary": True}],
                },
                "content_sources": {
                    "doclift_bundle": str(doclift_root),
                    "groundrecall_bundle": str(groundrecall_root),
                    "didactopus_pack": str(didactopus_root),
                    "bibliography": str(citegeist_root),
                },
            }
            config_path = tmp_path / "site.json"
            config_path.write_text(json.dumps(config), encoding="utf-8")

            out_dir = tmp_path / "out"
            result = build.build_site(config_path, out_dir)

            html = (out_dir / "index.html").read_text(encoding="utf-8")
            self.assertEqual(result["theme"], "talkorigins-modern")
            self.assertIn("TalkOrigins Preview", html)
            self.assertIn("Legacy Document", html)
            self.assertIn("GroundRecall Topic", html)
            self.assertIn("Prior", html)
            self.assertIn("A Study", html)
            self.assertTrue((out_dir / "theme" / "assets" / "toa.ico").exists())

    def test_build_site_filters_languages_by_coverage_and_shows_planned_list(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            config = {
                "lang": "en",
                "title": "TalkOrigins Preview",
                "site_title": "TalkOrigins Archive",
                "license": "CC BY-SA 4.0",
                "github_url": "https://example.invalid",
                "contact_email": "admin@example.invalid",
                "theme": "talkorigins-modern",
                "languages": [
                    {"code": "en", "name": "English", "coverage": True},
                    {"code": "es", "name": "Español", "coverage": False},
                    {"code": "fr", "name": "Français", "coverage": False},
                ],
                "language_policy": {
                    "planned_languages": [
                        {"code": "es", "name": "Español"},
                        {"code": "fr", "name": "Français"},
                    ]
                },
                "navigation": [{"label": "Home", "href": "/"}],
                "hero": {
                    "kicker": "Archive Preview",
                    "title": "Modernized, reviewable, and still archive-first.",
                    "lede": "Proof-of-concept output from SciSiteForge.",
                    "actions": [{"label": "Open", "href": "#overview", "primary": True}],
                },
                "content_sources": {},
            }
            config_path = tmp_path / "site.json"
            config_path.write_text(json.dumps(config), encoding="utf-8")

            out_dir = tmp_path / "out"
            build.build_site(config_path, out_dir)

            html = (out_dir / "index.html").read_text(encoding="utf-8")
            self.assertIn('<option value="en" selected>English</option>', html)
            self.assertNotIn('value="es"', html)
            self.assertNotIn('value="fr"', html)
            self.assertIn("Planned languages: Español, Français", html)

    def test_notebook_pattern_groups_goals_apps_and_source_cards(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            doclift_root = tmp_path / "doclift"
            doclift_root.mkdir()
            (doclift_root / "manifest.json").write_text(
                json.dumps(
                    {
                        "documents": [
                            {
                                "document_id": "doc-1",
                                "title": "Legacy Reading",
                                "document_kind": "article",
                                "markdown_path": "documents/doc-1/document.md",
                            }
                        ]
                    }
                ),
                encoding="utf-8",
            )
            (doclift_root / "documents" / "doc-1").mkdir(parents=True)
            (doclift_root / "documents" / "doc-1" / "document.md").write_text("Recovered source paragraph.", encoding="utf-8")

            config = {
                "notebooks": [
                    {
                        "id": "digital-evolution",
                        "title": "Digital Evolution Notebook",
                        "summary": "Lab plus source-grounded study path.",
                        "audience": "self-learners",
                        "goals": ["Connect simulation output to evolutionary concepts"],
                        "apps": [{"title": "Avida-ED", "href": "/app4/", "description": "Digital evolution lab"}],
                        "source_kinds": ["notebook"],
                    }
                ]
            }
            notebooks = load_notebooks(config)
            content = SiteContent(section_cards=load_doclift_cards(doclift_root))
            html = render_notebooks(notebooks, content)

            self.assertIn("Digital Evolution Notebook", html)
            self.assertIn("Avida-ED", html)
            self.assertIn("Legacy Reading", html)
            self.assertIn("Recovered source paragraph.", html)

    def test_geniehive_translator_uses_openai_compatible_chat_payload(self) -> None:
        translator = GenieHiveTranslator(
            TranslationConfig(base_url="http://geniehive.local:8800", model="translation-role", api_key="abc123")
        )
        captured: dict[str, object] = {}

        def fake_post_json(path: str, payload: dict) -> dict:
            captured["path"] = path
            captured["payload"] = payload
            return {"choices": [{"message": {"content": "Hola"}}]}

        translator._post_json = fake_post_json  # type: ignore[method-assign]
        result = translator.translate("Hello world", "Spanish", {"evolution": "evolución"})

        self.assertEqual(result, "Hola")
        self.assertEqual(captured["path"], "/v1/chat/completions")
        payload = captured["payload"]
        self.assertEqual(payload["model"], "translation-role")
        user_text = payload["messages"][1]["content"]
        self.assertIn("Spanish", user_text)
        self.assertIn("evolución", user_text)

    def test_translate_site_builds_translator_from_config(self) -> None:
        from tempfile import TemporaryDirectory

        with TemporaryDirectory() as tmp:
            tmp_path = Path(tmp)
            config_path = tmp_path / "site.json"
            config_path.write_text(
                json.dumps(
                    {
                        "translation": {
                            "base_url": "http://geniehive.local:8800",
                            "model": "translation-role",
                            "api_key": "abc123",
                            "timeout": 33,
                            "system_prompt": "Translate carefully.",
                        }
                    }
                ),
                encoding="utf-8",
            )
            args = SimpleNamespace(base_url=None, model=None, api_key=None, timeout=None)
            translator = translate_site.build_translator(config_path, args)

            self.assertEqual(translator.config.provider, "geniehive")
            self.assertEqual(translator.config.base_url, "http://geniehive.local:8800")
            self.assertEqual(translator.config.model, "translation-role")
            self.assertEqual(translator.config.api_key, "abc123")
            self.assertEqual(translator.config.timeout, 33)


if __name__ == "__main__":
    unittest.main()
