# #region Test.Api.GitGiteaRoutes [C:3] [TYPE Module] [SEMANTICS test,git,gitea,routes]
# @BRIEF Unit tests for Gitea-specific Git API routes — list, create, delete repos.
# @RELATION BINDS_TO -> [GitGiteaRoutes]
# @TEST_EDGE: config_not_found -> 404
# @TEST_EDGE: wrong_provider -> 400
# @TEST_EDGE: unsupported_provider -> 501

import os

os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:")
os.environ.setdefault("SECRET_KEY", "test-secret-key-for-tests")

import sys
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock, patch

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

_src = str(Path(__file__).resolve().parent.parent.parent / "src")
if _src not in sys.path:
    sys.path.insert(0, _src)


def _make_mock_config(provider: str = "GITEA", pat: str = "pat-123"):
    cfg = MagicMock()
    cfg.id = "cfg-1"
    cfg.url = "https://gitea.example.com"
    cfg.pat = pat
    cfg.provider = provider
    return cfg


def _make_mock_gitea_repo(name: str = "my-repo") -> dict:
    return {
        "name": name,
        "full_name": f"org/{name}",
        "private": False,
        "clone_url": f"https://gitea.example.com/org/{name}.git",
        "html_url": f"https://gitea.example.com/org/{name}",
        "ssh_url": f"git@gitea.example.com:org/{name}.git",
        "default_branch": "main",
    }


def _make_client(overrides: dict | None = None) -> TestClient:
    from src.api.routes.git._gitea_routes import router
    from src.api.routes.git._router import router as parent_router
    from src.core.database import get_db
    from src.dependencies import get_current_user, has_permission
    from src.schemas.auth import User, RoleSchema

    app = FastAPI()
    app.include_router(parent_router)
    app.include_router(router)

    mock_user = User(
        id="admin-1", username="admin", email="admin@x.com",
        auth_source="LOCAL",
        created_at=__import__("datetime").datetime.now(),
        roles=[RoleSchema(id="r1", name="Admin", description="", permissions=[])],
    )

    defaults = {
        get_db: lambda: MagicMock(),
        get_current_user: lambda: mock_user,
    }
    if overrides:
        defaults.update(overrides)
    for dep, mock_fn in defaults.items():
        app.dependency_overrides[dep] = mock_fn
    return TestClient(app)


# ── list_gitea_repositories ──

class TestListGiteaRepositories:
    """GET /config/{config_id}/gitea/repos"""

    def test_list_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config()
        mock_gs = MagicMock()
        mock_gs.list_gitea_repositories = AsyncMock(return_value=[_make_mock_gitea_repo()])

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.get("/config/cfg-1/gitea/repos")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        assert data[0]["name"] == "my-repo"

    def test_list_config_not_found(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = None

        from src.core.database import get_db
        client = _make_client({get_db: lambda: mock_db})
        resp = client.get("/config/cfg-999/gitea/repos")
        assert resp.status_code == 404

    def test_list_wrong_provider(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB")

        from src.core.database import get_db
        client = _make_client({get_db: lambda: mock_db})
        resp = client.get("/config/cfg-1/gitea/repos")
        assert resp.status_code == 400
        assert "GITEA provider only" in resp.text


# ── create_gitea_repository ──

class TestCreateGiteaRepository:
    """POST /config/{config_id}/gitea/repos"""

    def test_create_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config()
        mock_gs = MagicMock()
        mock_gs.create_gitea_repository = AsyncMock(return_value=_make_mock_gitea_repo())

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.post("/config/cfg-1/gitea/repos", json={
                "name": "new-repo", "private": True, "auto_init": True,
            })
        assert resp.status_code == 200
        data = resp.json()
        assert data["name"] == "my-repo"

    def test_create_wrong_provider(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITLAB")

        from src.core.database import get_db
        client = _make_client({get_db: lambda: mock_db})
        resp = client.post("/config/cfg-1/gitea/repos", json={
            "name": "new-repo", "private": True,
        })
        assert resp.status_code == 400


# ── delete_gitea_repository ──

class TestDeleteGiteaRepository:
    """DELETE /config/{config_id}/gitea/repos/{owner}/{repo_name}"""

    def test_delete_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config()
        mock_gs = MagicMock()
        mock_gs.delete_gitea_repository = AsyncMock(return_value=None)

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.delete("/config/cfg-1/gitea/repos/org/my-repo")
        assert resp.status_code == 200
        assert resp.json()["status"] == "success"

    def test_delete_wrong_provider(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB")

        from src.core.database import get_db
        client = _make_client({get_db: lambda: mock_db})
        resp = client.delete("/config/cfg-1/gitea/repos/org/my-repo")
        assert resp.status_code == 400


# ── create_remote_repository ──

class TestCreateRemoteRepository:
    """POST /config/{config_id}/repositories"""

    def test_create_gitea_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config()
        mock_gs = MagicMock()
        mock_gs.create_gitea_repository = AsyncMock(return_value=_make_mock_gitea_repo())

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.post("/config/cfg-1/repositories", json={
                "name": "remote-repo", "private": False,
            })
        assert resp.status_code == 200
        data = resp.json()
        assert data["name"] == "my-repo"
        assert data["provider"] == "GITEA"

    def test_create_github_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITHUB")
        mock_gs = MagicMock()
        mock_gs.create_github_repository = AsyncMock(return_value=_make_mock_gitea_repo(name="gh-repo"))

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.post("/config/cfg-1/repositories", json={
                "name": "gh-repo", "private": False,
            })
        assert resp.status_code == 200
        assert resp.json()["provider"] == "GITHUB"

    def test_create_gitlab_success(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="GITLAB")
        mock_gs = MagicMock()
        mock_gs.create_gitlab_repository = AsyncMock(return_value=_make_mock_gitea_repo(name="gl-repo"))

        with patch("src.api.routes.git._gitea_routes.get_git_service", return_value=mock_gs):
            from src.core.database import get_db
            client = _make_client({get_db: lambda: mock_db})
            resp = client.post("/config/cfg-1/repositories", json={
                "name": "gl-repo", "private": False,
            })
        assert resp.status_code == 200
        assert resp.json()["provider"] == "GITLAB"

    def test_create_unsupported_provider(self):
        mock_db = MagicMock()
        mock_db.query.return_value.filter.return_value.first.return_value = _make_mock_config(provider="UNKNOWN")

        from src.core.database import get_db
        client = _make_client({get_db: lambda: mock_db})
        resp = client.post("/config/cfg-1/repositories", json={
            "name": "repo", "private": False,
        })
        assert resp.status_code == 501
# #endregion Test.Api.GitGiteaRoutes
