"""Tests for import_manifest command."""

from pathlib import Path

from typer.testing import CliRunner

from repo_sync_kitty.cli import app
from repo_sync_kitty.commands.import_manifest import (
    _generate_toml,
    _parse_repo_manifest,
)

SAMPLE_XML = """\
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="origin" fetch="https://github.com/"/>
  <remote name="gitlab" fetch="https://gitlab.com"/>
  <default remote="origin" revision="main"/>
  <project name="owner/repo1" path="libs/repo1"/>
  <project name="owner/repo2.git" path="tools/repo2" remote="gitlab" revision="develop"/>
</manifest>
"""


class TestParseRepoManifest:
    """Tests for _parse_repo_manifest."""

    def test_parses_remotes(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        assert "origin" in result["remotes"]
        assert result["remotes"]["origin"] == "https://github.com/"

    def test_normalizes_remote_url_trailing_slash(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        # gitlab URL had no trailing slash, should be added
        assert result["remotes"]["gitlab"] == "https://gitlab.com/"

    def test_parses_default_settings(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        assert result["default_remote"] == "origin"
        assert result["default_revision"] == "main"

    def test_parses_projects(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        assert len(result["projects"]) == 2

    def test_strips_git_suffix_from_name(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        repo2 = [p for p in result["projects"] if p["path"] == "tools/repo2"][0]
        assert repo2["slug"] == "owner/repo2"

    def test_preserves_project_remote_override(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        result = _parse_repo_manifest(xml)
        repo2 = [p for p in result["projects"] if p["path"] == "tools/repo2"][0]
        assert repo2["remote"] == "gitlab"

    def test_no_default_element(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text("""\
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="origin" fetch="https://github.com/"/>
  <project name="owner/repo" path="repo"/>
</manifest>
""")
        result = _parse_repo_manifest(xml)
        assert result["default_remote"] == "origin"
        assert result["default_revision"] == "main"

    def test_skips_empty_project(self, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text("""\
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="origin" fetch="https://github.com/"/>
  <default remote="origin" revision="main"/>
  <project name="" path=""/>
  <project name="owner/real" path="real"/>
</manifest>
""")
        result = _parse_repo_manifest(xml)
        assert len(result["projects"]) == 1


class TestGenerateToml:
    """Tests for _generate_toml."""

    def test_generates_common_section(self) -> None:
        parsed = {
            "remotes": {"origin": "https://github.com/"},
            "default_remote": "origin",
            "default_revision": "main",
            "projects": [],
        }
        result = _generate_toml(parsed, "/home/user/repos")
        assert 'root_path = "/home/user/repos"' in result
        assert 'branch = "main"' in result

    def test_generates_remotes(self) -> None:
        parsed = {
            "remotes": {
                "origin": "https://github.com/",
                "gitlab": "https://gitlab.com/",
            },
            "default_remote": "origin",
            "default_revision": "main",
            "projects": [],
        }
        result = _generate_toml(parsed, "/tmp")
        assert "origin" in result
        assert "gitlab" in result

    def test_generates_projects_with_slug_override(self) -> None:
        parsed = {
            "remotes": {"origin": "https://github.com/"},
            "default_remote": "origin",
            "default_revision": "main",
            "projects": [
                {
                    "slug": "owner/repo",
                    "path": "libs/repo",
                    "remote": None,
                    "revision": None,
                },
            ],
        }
        result = _generate_toml(parsed, "/tmp")
        assert '"libs/repo"' in result
        assert 'slug = "owner/repo"' in result

    def test_generates_empty_project_entry(self) -> None:
        parsed = {
            "remotes": {"origin": "https://github.com/"},
            "default_remote": "origin",
            "default_revision": "main",
            "projects": [
                {"slug": "myrepo", "path": "myrepo", "remote": None, "revision": None},
            ],
        }
        result = _generate_toml(parsed, "/tmp")
        assert '"myrepo" = { }' in result

    def test_includes_non_default_remote_and_branch(self) -> None:
        parsed = {
            "remotes": {"origin": "https://github.com/"},
            "default_remote": "origin",
            "default_revision": "main",
            "projects": [
                {
                    "slug": "owner/repo",
                    "path": "repo",
                    "remote": "gitlab",
                    "revision": "develop",
                },
            ],
        }
        result = _generate_toml(parsed, "/tmp")
        assert 'remote = "gitlab"' in result
        assert 'branch = "develop"' in result


class TestImportManifestCommand:
    """Tests for import-manifest CLI command."""

    def test_source_not_found(self, cli_runner: CliRunner, tmp_path: Path) -> None:
        result = cli_runner.invoke(
            app, ["import-repo", str(tmp_path / "nonexistent.xml")]
        )
        assert result.exit_code == 2

    def test_output_exists_without_force(
        self, cli_runner: CliRunner, tmp_path: Path
    ) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        output = tmp_path / "manifest.toml"
        output.write_text("existing")
        result = cli_runner.invoke(app, ["import-repo", str(xml), "-o", str(output)])
        assert result.exit_code == 1

    def test_successful_import(self, cli_runner: CliRunner, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        output = tmp_path / "manifest.toml"
        result = cli_runner.invoke(app, ["import-repo", str(xml), "-o", str(output)])
        assert result.exit_code == 0
        assert output.exists()
        content = output.read_text()
        assert "origin" in content

    def test_import_with_root_path(self, cli_runner: CliRunner, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        output = tmp_path / "manifest.toml"
        result = cli_runner.invoke(
            app, ["import-repo", str(xml), "-o", str(output), "-r", "/custom/root"]
        )
        assert result.exit_code == 0
        content = output.read_text()
        assert "/custom/root" in content

    def test_force_overwrite(self, cli_runner: CliRunner, tmp_path: Path) -> None:
        xml = tmp_path / "manifest.xml"
        xml.write_text(SAMPLE_XML)
        output = tmp_path / "manifest.toml"
        output.write_text("existing")
        result = cli_runner.invoke(
            app, ["import-repo", str(xml), "-o", str(output), "--force"]
        )
        assert result.exit_code == 0
        assert "existing" not in output.read_text()
