# #region GitRepoRoutes [C:3] [TYPE Module] [SEMANTICS fastapi, git, api, search]
# @BRIEF FastAPI endpoints for core Git repository operations (init, binding, branches, checkout).
# @LAYER API


from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session

from src.api.routes.git_schemas import (
    BranchCheckout,
    BranchCreate,
    BranchSchema,
    RepoInitRequest,
    RepositoryBindingSchema,
)
from src.core.database import get_db
from src.core.logger import belief_scope, logger
from src.dependencies import get_config_manager, get_current_user, has_permission
from src.models.auth import User
from src.models.git import GitRepository, GitServerConfig

from ._deps import get_git_service
from ._helpers import (
    _apply_git_identity_from_profile,
    _get_git_config_or_404,
    _handle_unexpected_git_route_error,
)
from ._router import router


# #region init_repository [C:3] [TYPE Function]
# @BRIEF Link a dashboard to a Git repository and perform initial clone/init.
# @RELATION CALLS -> [GitService]
@router.post("/repositories/{dashboard_ref}/init")
async def init_repository(
    dashboard_ref: str,
    init_data: RepoInitRequest,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    db: Session = Depends(get_db),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    _gs = get_git_service()
    with belief_scope("init_repository"):
        from . import _resolve_dashboard_id_from_ref, _resolve_repo_key_from_ref

        dashboard_id = _resolve_dashboard_id_from_ref(
            dashboard_ref, config_manager, env_id
        )
        repo_key = _resolve_repo_key_from_ref(
            dashboard_ref, dashboard_id, config_manager, env_id
        )
        config = (
            db.query(GitServerConfig)
            .filter(GitServerConfig.id == init_data.config_id)
            .first()
        )
        if not config:
            raise HTTPException(status_code=404, detail="Git configuration not found")

        try:
            logger.reason(
                f"Initializing repo for dashboard {dashboard_id}",
                extra={"src": "init_repository"},
            )
            _gs.init_repo(
                dashboard_id,
                init_data.remote_url,
                config.pat,
                repo_key=repo_key,
                default_branch=config.default_branch,
            )

            repo_path = _gs._get_repo_path(dashboard_id, repo_key=repo_key)
            db_repo = (
                db.query(GitRepository)
                .filter(GitRepository.dashboard_id == dashboard_id)
                .first()
            )
            if not db_repo:
                db_repo = GitRepository(
                    dashboard_id=dashboard_id,
                    config_id=config.id,
                    remote_url=init_data.remote_url,
                    local_path=repo_path,
                    current_branch="dev",
                )
                db.add(db_repo)
            else:
                db_repo.config_id = config.id
                db_repo.remote_url = init_data.remote_url
                db_repo.local_path = repo_path
                db_repo.current_branch = "dev"

            db.commit()
            logger.info(
                f"[init_repository][Coherence:OK] Repository initialized for dashboard {dashboard_id}"
            )
            return {"status": "success", "message": "Repository initialized"}
        except Exception as e:
            db.rollback()
            logger.error(
                f"[init_repository][Coherence:Failed] Failed to init repository: {e}"
            )
            if isinstance(e, HTTPException):
                raise
            _handle_unexpected_git_route_error("init_repository", e)
# #endregion init_repository


# #region get_repository_binding [C:2] [TYPE Function]
# @BRIEF Return repository binding with provider metadata for selected dashboard.
@router.get("/repositories/{dashboard_ref}", response_model=RepositoryBindingSchema)
async def get_repository_binding(
    dashboard_ref: str,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    db: Session = Depends(get_db),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    with belief_scope("get_repository_binding"):
        from . import _resolve_dashboard_id_from_ref

        try:
            dashboard_id = _resolve_dashboard_id_from_ref(
                dashboard_ref, config_manager, env_id
            )
            db_repo = (
                db.query(GitRepository)
                .filter(GitRepository.dashboard_id == dashboard_id)
                .first()
            )
            if not db_repo:
                raise HTTPException(
                    status_code=404, detail="Repository not initialized"
                )
            config = _get_git_config_or_404(db, db_repo.config_id)
            return RepositoryBindingSchema(
                dashboard_id=db_repo.dashboard_id,
                config_id=db_repo.config_id,
                provider=config.provider,
                remote_url=db_repo.remote_url,
                local_path=db_repo.local_path,
            )
        except HTTPException:
            raise
        except Exception as e:
            _handle_unexpected_git_route_error("get_repository_binding", e)
# #endregion get_repository_binding


# #region delete_repository [C:2] [TYPE Function]
# @BRIEF Delete local repository workspace and DB binding for selected dashboard.
@router.delete("/repositories/{dashboard_ref}")
async def delete_repository(
    dashboard_ref: str,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    _gs = get_git_service()
    with belief_scope("delete_repository"):
        from . import _resolve_dashboard_id_from_ref

        try:
            dashboard_id = _resolve_dashboard_id_from_ref(
                dashboard_ref, config_manager, env_id
            )
            _gs.delete_repo(dashboard_id)
            return {"status": "success"}
        except HTTPException:
            raise
        except Exception as e:
            _handle_unexpected_git_route_error("delete_repository", e)
# #endregion delete_repository


# #region get_branches [C:2] [TYPE Function]
# @BRIEF List all branches for a dashboard's repository.
@router.get("/repositories/{dashboard_ref}/branches", response_model=list[BranchSchema])
async def get_branches(
    dashboard_ref: str,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    _gs = get_git_service()
    with belief_scope("get_branches"):
        from . import _resolve_dashboard_id_from_ref

        try:
            dashboard_id = _resolve_dashboard_id_from_ref(
                dashboard_ref, config_manager, env_id
            )
            return _gs.list_branches(dashboard_id)
        except HTTPException:
            raise
        except Exception as e:
            _handle_unexpected_git_route_error("get_branches", e)
# #endregion get_branches


# #region create_branch [C:2] [TYPE Function]
# @BRIEF Create a new branch in the dashboard's repository.
@router.post("/repositories/{dashboard_ref}/branches")
async def create_branch(
    dashboard_ref: str,
    branch_data: BranchCreate,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    _gs = get_git_service()
    with belief_scope("create_branch"):
        from . import _resolve_dashboard_id_from_ref

        try:
            dashboard_id = _resolve_dashboard_id_from_ref(
                dashboard_ref, config_manager, env_id
            )
            _apply_git_identity_from_profile(dashboard_id, db, current_user)
            _gs.create_branch(
                dashboard_id, branch_data.name, branch_data.from_branch
            )
            return {"status": "success"}
        except HTTPException:
            raise
        except Exception as e:
            _handle_unexpected_git_route_error("create_branch", e)
# #endregion create_branch


# #region checkout_branch [C:2] [TYPE Function]
# @BRIEF Switch the dashboard's repository to a specific branch.
@router.post("/repositories/{dashboard_ref}/checkout")
async def checkout_branch(
    dashboard_ref: str,
    checkout_data: BranchCheckout,
    env_id: str | None = None,
    config_manager=Depends(get_config_manager),
    _=Depends(has_permission("plugin:git", "EXECUTE")),
):
    _gs = get_git_service()
    with belief_scope("checkout_branch"):
        from . import _resolve_dashboard_id_from_ref

        try:
            dashboard_id = _resolve_dashboard_id_from_ref(
                dashboard_ref, config_manager, env_id
            )
            _gs.checkout_branch(dashboard_id, checkout_data.name)
            return {"status": "success"}
        except HTTPException:
            raise
        except Exception as e:
            _handle_unexpected_git_route_error("checkout_branch", e)
# #endregion checkout_branch
# #endregion GitRepoRoutes
