#!/usr/bin/env python3
"""Small smoke tests for WordPress transcript parsing.

Run from repo root:
    python3 tests/smoke_publish_parser.py
"""

from __future__ import annotations

import importlib.util
import os
import sys
import types
import unittest
from pathlib import Path
from tempfile import TemporaryDirectory

ROOT = Path(__file__).resolve().parents[1]
PUBLISHER = ROOT / "03_publish_to_wordpress.py"

# The parser tests do not make network calls. Allow them to run on fresh systems
# before optional runtime dependencies are installed.
try:
    import requests  # noqa: F401
except ModuleNotFoundError:  # pragma: no cover - only used on minimal systems
    requests_stub = types.ModuleType("requests")
    requests_stub.request = lambda *args, **kwargs: None
    requests_stub.utils = types.SimpleNamespace(quote=lambda value: value)
    sys.modules["requests"] = requests_stub

spec = importlib.util.spec_from_file_location("publish_to_wordpress", PUBLISHER)
assert spec and spec.loader
publisher = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = publisher
spec.loader.exec_module(publisher)


class PublishParserSmokeTest(unittest.TestCase):
    def test_detects_blog_post_intent_and_strips_footer(self) -> None:
        text = """Meta note: create blog post
Title: Launch Notes
Excerpt: Short summary.
Tags: audio, local tools

This is the post body.

[[TRANSCRIBE_FOOTER_START]]
Word count: 4
Transcribed locally with whisper.cpp (Metal).
[[TRANSCRIBE_FOOTER_END]]
"""
        parsed = publisher.parse_transcript_for_meta(text)
        self.assertTrue(parsed.should_post)
        self.assertEqual(parsed.title, "Launch Notes")
        self.assertEqual(parsed.excerpt, "Short summary.")
        self.assertEqual(parsed.tags, ["audio", "local tools"])
        self.assertEqual(parsed.body, "This is the post body.")

    def test_ignores_transcript_without_spoken_intent(self) -> None:
        parsed = publisher.parse_transcript_for_meta("Just a normal transcript.")
        self.assertFalse(parsed.should_post)

    def test_env_file_loads_quoted_values_and_expands_refs(self) -> None:
        with TemporaryDirectory() as tmp:
            env_path = Path(tmp) / "config.env"
            env_path.write_text(
                "\n".join(
                    [
                        "PROJECT_ROOT=/tmp/myaudio",
                        "WP_SITE_URL='https://example.com'",
                        'WP_USERNAME="local-user"',
                        "WP_APP_PASSWORD=local password with spaces # inline comment",
                        "OUT_DIR=${PROJECT_ROOT}/_02_Transcripts",
                    ]
                ),
                encoding="utf-8",
            )

            keys = ["PROJECT_ROOT", "WP_SITE_URL", "WP_USERNAME", "WP_APP_PASSWORD", "OUT_DIR"]
            old = {key: os.environ.get(key) for key in keys}
            for key in keys:
                os.environ.pop(key, None)
            try:
                publisher.load_env_file(env_path)
                self.assertEqual(os.environ["WP_SITE_URL"], "https://example.com")
                self.assertEqual(os.environ["WP_USERNAME"], "local-user")
                self.assertEqual(os.environ["WP_APP_PASSWORD"], "local password with spaces")
                self.assertEqual(os.environ["OUT_DIR"], "/tmp/myaudio/_02_Transcripts")
            finally:
                for key in keys:
                    os.environ.pop(key, None)
                    old_value = old[key]
                    if old_value is not None:
                        os.environ[key] = old_value

    def test_existing_env_wins_over_env_file(self) -> None:
        with TemporaryDirectory() as tmp:
            env_path = Path(tmp) / "config.env"
            env_path.write_text("WP_USERNAME=file-user\n", encoding="utf-8")
            old = os.environ.get("WP_USERNAME")
            try:
                os.environ["WP_USERNAME"] = "shell-user"
                publisher.load_env_file(env_path)
                self.assertEqual(os.environ["WP_USERNAME"], "shell-user")
            finally:
                os.environ.pop("WP_USERNAME", None)
                if old is not None:
                    os.environ["WP_USERNAME"] = old

    def test_env_file_can_override_stale_process_env(self) -> None:
        with TemporaryDirectory() as tmp:
            env_path = Path(tmp) / "config.env"
            env_path.write_text("WP_USERNAME=fresh-file-user\n", encoding="utf-8")
            old = os.environ.get("WP_USERNAME")
            try:
                os.environ["WP_USERNAME"] = "stale-shell-user"
                publisher.load_env_file(env_path, override=True)
                self.assertEqual(os.environ["WP_USERNAME"], "fresh-file-user")
            finally:
                os.environ.pop("WP_USERNAME", None)
                if old is not None:
                    os.environ["WP_USERNAME"] = old

    def test_resolves_generic_wp_credentials(self) -> None:
        keys = [
            "WP_SITE_URL",
            "WP_USERNAME",
            "WP_APP_PASSWORD",
            "WP_SITE_KEY",
            "WP_PROFILE",
            "WP_SITE_PREFIX",
            "BERTMAHONEY_WP_URL",
            "BERTMAHONEY_WP_USER",
            "BERTMAHONEY_WP_APP_PASSWORD",
        ]
        old = {key: os.environ.get(key) for key in keys}
        try:
            for key in keys:
                os.environ.pop(key, None)
            os.environ["WP_SITE_URL"] = "https://generic.example"
            os.environ["WP_USERNAME"] = "generic-user"
            os.environ["WP_APP_PASSWORD"] = "generic-password"
            site_url, username, app_password, source = publisher.resolve_wp_credentials()
            self.assertEqual(site_url, "https://generic.example")
            self.assertEqual(username, "generic-user")
            self.assertEqual(app_password, "generic-password")
            self.assertEqual(source, "generic WP_*")
        finally:
            for key, old_value in old.items():
                os.environ.pop(key, None)
                if old_value is not None:
                    os.environ[key] = old_value

    def test_resolves_site_prefixed_wp_credentials(self) -> None:
        keys = [
            "WP_SITE_URL",
            "WP_USERNAME",
            "WP_APP_PASSWORD",
            "WP_SITE_KEY",
            "WP_PROFILE",
            "WP_SITE_PREFIX",
            "BERTMAHONEY_WP_URL",
            "BERTMAHONEY_WP_USER",
            "BERTMAHONEY_WP_APP_PASSWORD",
        ]
        old = {key: os.environ.get(key) for key in keys}
        try:
            for key in keys:
                os.environ.pop(key, None)
            os.environ["WP_SITE_KEY"] = "bertmahoney"
            os.environ["BERTMAHONEY_WP_URL"] = "https://bertmahoney.com"
            os.environ["BERTMAHONEY_WP_USER"] = "bertmahoney-login"
            os.environ["BERTMAHONEY_WP_APP_PASSWORD"] = "site-password"
            site_url, username, app_password, source = publisher.resolve_wp_credentials()
            self.assertEqual(site_url, "https://bertmahoney.com")
            self.assertEqual(username, "bertmahoney-login")
            self.assertEqual(app_password, "site-password")
            self.assertEqual(source, "BERTMAHONEY_WP_*")
        finally:
            for key, old_value in old.items():
                os.environ.pop(key, None)
                if old_value is not None:
                    os.environ[key] = old_value

    def test_missing_required_env_fails_without_value(self) -> None:
        old = os.environ.get("WP_APP_PASSWORD")
        try:
            os.environ.pop("WP_APP_PASSWORD", None)
            with self.assertRaises(SystemExit) as ctx:
                publisher.get_env_required("WP_APP_PASSWORD")
            self.assertIn("Missing required environment variable: WP_APP_PASSWORD", str(ctx.exception))
        finally:
            if old is not None:
                os.environ["WP_APP_PASSWORD"] = old


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