from __future__ import annotations

import json
import os
from pathlib import Path
import stat
import subprocess
import sys
import tempfile
import textwrap
import unittest


REPO_ROOT = Path(__file__).resolve().parents[2]
SCRIPT_PATH = REPO_ROOT / "tools" / "configure_workstation.sh"
BUNDLE_PYTHON = Path.home() / ".local" / "share" / "ffx.venv" / "bin" / "python"


class ConfigureWorkstationScriptTests(unittest.TestCase):
    def setUp(self):
        self.tempdir = tempfile.TemporaryDirectory()
        self.home_dir = Path(self.tempdir.name) / "home"
        self.home_dir.mkdir()
        self.stub_bin_dir = Path(self.tempdir.name) / "bin"
        self.stub_bin_dir.mkdir()

        for command_name in ("git", "python3", "ffmpeg", "ffprobe", "cpulimit"):
            self.write_stub_command(command_name)

    def tearDown(self):
        self.tempdir.cleanup()

    def write_stub_command(self, name: str, body: str = "") -> None:
        script_path = self.stub_bin_dir / name
        script_path.write_text(
            "#!/usr/bin/env bash\n"
            + body
            + "\n",
            encoding="utf-8",
        )
        script_path.chmod(script_path.stat().st_mode | stat.S_IXUSR)

    def run_script(self, **env_overrides: str) -> subprocess.CompletedProcess[str]:
        if not BUNDLE_PYTHON.is_file():
            self.skipTest(f"Missing bundle Python at {BUNDLE_PYTHON}")

        env = {
            **os.environ,
            "HOME": str(self.home_dir),
            "PATH": f"{self.stub_bin_dir}:{os.environ.get('PATH', '')}",
            "FFX_PYTHON": str(BUNDLE_PYTHON),
            **env_overrides,
        }

        return subprocess.run(
            ["bash", str(SCRIPT_PATH)],
            capture_output=True,
            cwd=REPO_ROOT,
            env=env,
            text=True,
        )

    def test_script_seeds_default_config_from_template(self):
        completed = self.run_script()

        self.assertEqual(
            0,
            completed.returncode,
            f"STDOUT:\n{completed.stdout}\nSTDERR:\n{completed.stderr}",
        )

        config_path = self.home_dir / ".local" / "etc" / "ffx.json"
        self.assertTrue(config_path.exists())

        config_data = json.loads(config_path.read_text(encoding="utf-8"))
        self.assertEqual(
            {
                "databasePath": str(self.home_dir / ".local" / "var" / "ffx" / "ffx.db"),
                "logDirectory": str(self.home_dir / ".local" / "var" / "log"),
                "subtitlesDirectory": str(
                    self.home_dir / ".local" / "var" / "sync" / "subtitles"
                ),
                "defaultIndexSeasonDigits": 2,
                "defaultIndexEpisodeDigits": 2,
                "defaultIndicatorSeasonDigits": 2,
                "defaultIndicatorEpisodeDigits": 2,
                "metadata": {
                    "signature": {"RECODED_WITH": "FFX"},
                    "remove": [
                        "VERSION-eng",
                        "creation_time",
                        "NAME",
                    ],
                    "streams": {
                        "remove": [
                            "BPS",
                            "NUMBER_OF_FRAMES",
                            "NUMBER_OF_BYTES",
                            "_STATISTICS_WRITING_APP",
                            "_STATISTICS_WRITING_DATE_UTC",
                            "_STATISTICS_TAGS",
                            "BPS-eng",
                            "DURATION-eng",
                            "NUMBER_OF_FRAMES-eng",
                            "NUMBER_OF_BYTES-eng",
                            "_STATISTICS_WRITING_APP-eng",
                            "_STATISTICS_WRITING_DATE_UTC-eng",
                            "_STATISTICS_TAGS-eng",
                        ]
                    },
                },
            },
            config_data,
        )

    def test_script_honors_custom_template_override(self):
        custom_template_path = Path(self.tempdir.name) / "custom-config.j2"
        custom_template_path.write_text(
            textwrap.dedent(
                """
                {
                  "databasePath": {{ database_path_json }},
                  "marker": "from-template",
                  "subtitlesDirectory": {{ subtitles_directory_json }}
                }
                """
            ).lstrip(),
            encoding="utf-8",
        )

        completed = self.run_script(FFX_CONFIG_TEMPLATE=str(custom_template_path))

        self.assertEqual(
            0,
            completed.returncode,
            f"STDOUT:\n{completed.stdout}\nSTDERR:\n{completed.stderr}",
        )

        config_path = self.home_dir / ".local" / "etc" / "ffx.json"
        config_data = json.loads(config_path.read_text(encoding="utf-8"))

        self.assertEqual("from-template", config_data["marker"])
        self.assertEqual(
            str(self.home_dir / ".local" / "var" / "ffx" / "ffx.db"),
            config_data["databasePath"],
        )


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