"""Tests for configuration models."""

from pathlib import Path

import pytest

from repo_sync_kitty.config.models import (
    CommonConfig,
    Manifest,
    ProjectConfig,
    RemoteConfig,
)


class TestRemoteConfig:
    """Tests for RemoteConfig model."""

    def test_init_with_required_fields_only(self) -> None:
        """Test RemoteConfig with only required fields."""
        remote = RemoteConfig(name="ghpub", base_url="https://github.com/")
        assert remote.name == "ghpub"
        assert remote.base_url == "https://github.com/"
        assert remote.branch is None
        assert remote.parallelism is None
        assert remote.timeout is None

    def test_init_with_all_optional_fields(self) -> None:
        """Test RemoteConfig with all optional fields."""
        remote = RemoteConfig(
            name="mine",
            base_url="ssh://git@github.com/",
            branch="develop",
            parallelism=2,
            timeout=600,
        )
        assert remote.branch == "develop"
        assert remote.parallelism == 2
        assert remote.timeout == 600


class TestProjectConfig:
    """Tests for ProjectConfig model."""

    def test_init_with_required_fields_only(self) -> None:
        """Test ProjectConfig with only required fields."""
        project = ProjectConfig(slug="owner/repo", path=Path("libs/repo"))
        assert project.slug == "owner/repo"
        assert project.path == Path("libs/repo")
        assert project.status == "active"
        assert project.remote is None
        assert project.branch is None

    @pytest.mark.parametrize("status", ["active", "archived", "deleted"])
    def test_init_with_valid_status(self, status: str) -> None:
        """Test ProjectConfig accepts valid status values."""
        project = ProjectConfig(
            slug="test/repo",
            path=Path("test"),
            status=status,  # type: ignore[arg-type]
        )
        assert project.status == status


class TestCommonConfig:
    """Tests for CommonConfig model."""

    def test_init_with_required_fields_only(self) -> None:
        """Test CommonConfig with only required fields uses defaults."""
        common = CommonConfig(
            root_path=Path("~/Projects"),
            remote="ghpub",
        )
        assert common.root_path == Path.home() / "Projects"
        assert common.remote == "ghpub"
        assert common.branch == "main"
        assert common.parallelism == 4
        assert common.log_level == "info"
        assert common.timeout == 300
        assert common.ignore_extra == []


def test_root_path_tilde_expansion():
    common = CommonConfig(root_path=Path("~/Projects"), remote="ghpub")
    assert "~" not in str(common.root_path)
    assert common.root_path == Path.home() / "Projects"


def test_root_path_env_var_expansion(monkeypatch):
    monkeypatch.setenv("REPO_SYNC_ROOT", "/opt/repos")
    common = CommonConfig(root_path=Path("$REPO_SYNC_ROOT/team"), remote="ghpub")
    assert common.root_path == Path("/opt/repos/team")


def test_root_path_tilde_and_env_var(monkeypatch):
    monkeypatch.setenv("TEAM", "my-team")
    common = CommonConfig(root_path=Path("~/Projects/$TEAM"), remote="ghpub")
    assert common.root_path == Path.home() / "Projects" / "my-team"


def test_parallelism_from_env_var(monkeypatch):
    monkeypatch.setenv("REPO_SYNC_PARALLELISM", "8")
    common = CommonConfig(
        root_path=Path("/tmp"),
        remote="ghpub",
        parallelism="$REPO_SYNC_PARALLELISM",  # type: ignore[arg-type]
    )
    assert common.parallelism == 8


def test_timeout_from_env_var(monkeypatch):
    monkeypatch.setenv("REPO_SYNC_TIMEOUT", "600")
    common = CommonConfig(
        root_path=Path("/tmp"),
        remote="ghpub",
        timeout="$REPO_SYNC_TIMEOUT",  # type: ignore[arg-type]
    )
    assert common.timeout == 600


def test_parallelism_int_passthrough():
    common = CommonConfig(root_path=Path("/tmp"), remote="ghpub", parallelism=16)
    assert common.parallelism == 16


def test_timeout_int_passthrough():
    common = CommonConfig(root_path=Path("/tmp"), remote="ghpub", timeout=120)
    assert common.timeout == 120


def test_parallelism_invalid_env_var_raises():
    with pytest.raises(ValueError):
        CommonConfig(
            root_path=Path("/tmp"),
            remote="ghpub",
            parallelism="not_a_number",  # type: ignore[arg-type]
        )


class TestManifest:
    """Tests for Manifest model."""

    def test_init_with_all_sections(self) -> None:
        """Test Manifest with common, remotes, and projects."""
        manifest = Manifest(
            common=CommonConfig(root_path=Path("/tmp"), remote="ghpub"),
            remotes=[RemoteConfig(name="ghpub", base_url="https://github.com/")],
            projects=[ProjectConfig(slug="test/repo", path=Path("test"))],
        )
        assert len(manifest.remotes) == 1
        assert len(manifest.projects) == 1
        assert manifest.common.remote == "ghpub"
