#!/usr/bin/env python3
"""Test configuration downloads in a temporary home without network access."""

import os
from pathlib import Path
import subprocess
import tempfile
import unittest


ROOT = Path(__file__).resolve().parent
TARGETS = (
    ".alias", ".func", ".pathrc", ".sourcerc", ".vimrc", ".zshrc",
    ".config/starship.toml", ".config/ai-commit-prompt.txt",
    ".config/ai-commit-split-prompt.txt",
    ".config/opencode/agents/ai-commit.md",
    ".config/opencode/agents/ai-commit-plan.md",
)


class ConfigTests(unittest.TestCase):
    def setUp(self):
        temp = tempfile.TemporaryDirectory(prefix="config-test-")
        self.addCleanup(temp.cleanup)
        self.root = Path(temp.name)
        self.home = self.root / "home"
        self.home.mkdir()
        self.env = {
            **os.environ, "HOME": str(self.home),
            "GIST_RAW_BASE": ROOT.as_uri() + "/",
            "TMPDIR": str(self.root),
        }

    def run_bash(self, *args):
        return subprocess.run(
            ["bash", *args], env=self.env, capture_output=True, text=True,
        )

    def assert_installed(self):
        for target in TARGETS:
            source = ROOT / Path(target).name.lstrip(".")
            self.assertEqual((self.home / target).read_bytes(), source.read_bytes())
        self.assertEqual(list(self.home.rglob("*.tmp.*")), [])

    def test_standalone_and_inline_entry_points(self):
        for args in ((str(ROOT / "config.sh"),), ("-c", (ROOT / "config.sh").read_text())):
            with self.subTest(args=args[:1]):
                result = self.run_bash(*args)
                self.assertEqual(result.returncode, 0, result.stderr)
                self.assert_installed()

    def test_source_has_no_download_side_effects(self):
        result = self.run_bash("-c", 'source "$1"', "test", str(ROOT / "config.sh"))
        self.assertEqual(result.returncode, 0, result.stderr)
        self.assertEqual(list(self.home.iterdir()), [])

    def test_failed_and_empty_downloads_preserve_existing_files(self):
        remote = self.root / "remote"
        remote.mkdir()
        self.env["GIST_RAW_BASE"] = remote.as_uri()
        for target in TARGETS:
            path = self.home / target
            path.parent.mkdir(parents=True, exist_ok=True)
            path.write_text("existing config\n")
        # One empty response, one successful response, all others missing.
        (remote / "zshrc").touch()
        (remote / "alias").write_text("new aliases\n")
        result = self.run_bash(str(ROOT / "config.sh"))
        self.assertNotEqual(result.returncode, 0)
        self.assertNotIn("Done!", result.stdout)
        for target in TARGETS:
            expected = "new aliases\n" if target == ".alias" else "existing config\n"
            self.assertEqual((self.home / target).read_text(), expected)
        self.assertEqual(list(self.home.rglob("*.tmp.*")), [])

    def test_platform_loaders_local_and_remote(self):
        for name in ("zsh_ubuntu.sh", "zsh_wsl.sh", "zsh_macos.sh"):
            for local in (True, False):
                with self.subTest(platform=name, local=local):
                    script = ROOT / name
                    if not local:
                        # An isolated script has no adjacent config.sh, just like
                        # the curl entry point, and must fetch the shared code.
                        script = self.root / name
                        script.write_text((ROOT / name).read_text())
                    result = self.run_bash(
                        "-c", 'source "$1"; load_config_installer; download_configs',
                        "test", str(script),
                    )
                    self.assertEqual(result.returncode, 0, result.stderr)
                    self.assert_installed()

    def test_zshrc_only_uses_canonical_file(self):
        result = self.run_bash(
            "-c", 'source "$1"; configure_zshrc', "test", str(ROOT / "config.sh"),
        )
        self.assertEqual(result.returncode, 0, result.stderr)
        self.assertEqual((self.home / ".zshrc").read_bytes(), (ROOT / "zshrc").read_bytes())
        self.assertEqual(list(self.home.iterdir()), [self.home / ".zshrc"])


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