"""Git control operations with repo validation.""" import logging import os import uuid from fastapi import HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from src.models.git_repository import GitRepository from src.models.user import User from src.schemas.git_repository import ( BranchCreateRequest, CheckoutRequest, CommitRequest, FetchResponse, MergeRequest, MergeResponse, PullResponse, PushResponse, StatusResponse, ) from src.services.git.repository import ensure_repo_on_disk, get_repo_and_validate from src.utils.git_control import ( checkout_branch, commit_changes, create_branch, delete_branch, fetch, get_status, merge, pull, push, ) logger = logging.getLogger(__name__) async def get_status_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, ) -> StatusResponse: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: result = get_status(repo.path) return StatusResponse( branch=result.branch, modified=result.modified, added=result.added, deleted=result.deleted, untracked=result.untracked, renamed=result.renamed, ahead=result.ahead, behind=result.behind, ) except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def create_branch_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, data: BranchCreateRequest, ) -> dict: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: create_branch(repo.path, data.name, data.base_branch) return {"message": f"Branch '{data.name}' created", "branch": data.name} except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def delete_branch_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, branch_name: str, force: bool = False, ) -> dict: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: delete_branch(repo.path, branch_name, force) return {"message": f"Branch '{branch_name}' deleted"} except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def checkout_branch_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, data: CheckoutRequest, ) -> dict: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: checkout_branch(repo.path, data.branch) return {"message": f"Checked out branch '{data.branch}'", "branch": data.branch} except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def commit_changes_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, data: CommitRequest, user: User, ) -> dict: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) author_name = user.name or "Unknown" author_email = user.email or "unknown@example.com" try: commit_hash = commit_changes( repo_path=repo.path, message=data.message, author_name=author_name, author_email=author_email, files=data.files, ) return {"commit_hash": commit_hash, "message": data.message} except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def fetch_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, ) -> FetchResponse: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: fetch(repo.path) return FetchResponse(message="Fetched from remote") except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def pull_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, branch: str | None = None, ) -> PullResponse: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: pull(repo.path, branch) return PullResponse(message="Pulled from remote") except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def push_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, branch: str | None = None, ) -> PushResponse: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: push(repo.path, branch) return PushResponse(message="Pushed to remote") except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) async def merge_with_validation( session: AsyncSession, project_id: uuid.UUID, repo_id: uuid.UUID, data: MergeRequest, ) -> MergeResponse: repo = await get_repo_and_validate(session, repo_id, project_id) ensure_repo_on_disk(repo) try: commit_hash = merge( repo_path=repo.path, source_branch=data.source_branch, target_branch=data.target_branch, message=data.message, ) return MergeResponse( commit_hash=commit_hash, message=data.message or f"Merge {data.source_branch}", ) except RuntimeError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))