from pathlib import Path

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field

from mosaygent.logger import get_logger
from mosaygent.services.github import GitHubService

logger = get_logger(__name__)

router = APIRouter(
    prefix='/github',
    tags=['GitHub Routes'],
)

github_service = GitHubService()


class InitRepoRequest(BaseModel):
    """Request model for initializing a new repository from template."""
    parent_dir: str = Field(min_length=1, description="Parent directory where the repo folder will be created")
    repo_name: str = Field(min_length=1, description="Name for the new repository (without owner)")
    owner: str = Field(min_length=1, description="Owner (username or organization) for the repository")
    private: bool = Field(default=True, description="Whether the repository should be private")
    app_name: str = Field(min_length=1, description="Display name for the app")
    slug: str = Field(min_length=1, description="URL-friendly slug for the app (e.g., my-cool-app)")
    bundle_id: str = Field(min_length=1, description="Bundle identifier for the app (e.g., com.example.app)")


@router.get("/auth")
async def check_github_auth() -> dict:
    """Check GitHub CLI installation and auth status."""
    auth_status = await github_service.check_auth()
    return auth_status


@router.get("/accounts")
async def list_accounts() -> dict:
    """List user's personal account and organizations they can create repos in."""
    try:
        return await github_service.get_accounts()
    except PermissionError as e:
        raise HTTPException(status_code=401, detail=str(e))


@router.post("/init-repo")
async def init_repo_from_template(request: InitRepoRequest) -> dict:
    """Initialize a new git repository from the mobile-app template.

    1. Fetches the latest release from the template repo
    2. Downloads and extracts the release
    3. Renames directory to repo_name
    4. Initializes git and makes initial commit
    5. Creates the repo on GitHub if it doesn't exist
    6. Pushes to GitHub
    """
    try:
        return await github_service.init_repo_from_template(
            parent_dir=Path(request.parent_dir),
            repo_name=request.repo_name,
            owner=request.owner,
            private=request.private,
            app_name=request.app_name,
            slug=request.slug,
            bundle_id=request.bundle_id,
        )
    except FileExistsError as e:
        raise HTTPException(status_code=409, detail=str(e))
    except FileNotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.exception(f"Failed to initialize repository: {e}")
        raise HTTPException(status_code=500, detail=str(e))


class InitGitRepoRequest(BaseModel):
    """Request model for initializing a git repo and pushing to GitHub."""
    repo_path: str = Field(min_length=1, description="Path to the directory to initialize as a git repository")
    owner: str = Field(min_length=1, description="Owner (username or organization) for the repository")
    private: bool = Field(default=True, description="Whether the repository should be private")


@router.post("/init-git-repo")
async def init_git_repo(request: InitGitRepoRequest) -> dict:
    """Initialize a git repository and push to GitHub.

    1. Extracts repo name from the provided path
    2. Initializes git in the directory
    3. Adds all files and creates initial commit
    4. Creates the repo on GitHub if it doesn't exist
    5. Pushes to GitHub
    """
    try:
        return await github_service.init_git_and_push(
            repo_path=Path(request.repo_path),
            owner=request.owner,
            private=request.private,
        )
    except FileExistsError as e:
        raise HTTPException(status_code=409, detail=str(e))
    except FileNotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except NotADirectoryError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.exception(f"Failed to initialize git repository: {e}")
        raise HTTPException(status_code=500, detail=str(e))


class SetEnvVariablesRequest(BaseModel):
    """Request to set environment variables in .env.prod.yaml and update eas.json."""
    env_variables: dict[str, str] = Field(description="Dictionary of environment variable names to values")
    working_directory: str = Field(min_length=1, description="Directory where .env.prod.yaml will be created")
    mobile_app_directory: str | None = Field(default=None, description="Mobile app directory containing eas.json to update with Supabase keys")


@router.post("/set-env-variables")
async def set_env_variables(request: SetEnvVariablesRequest) -> dict:
    """Create or update .env.prod.yaml and optionally update eas.json with Supabase keys."""
    logger.info(f"Setting env variables in {request.working_directory}")

    return await github_service.set_env_variables(
        env_variables=request.env_variables,
        working_directory=request.working_directory,
        mobile_app_directory=request.mobile_app_directory
    )


class SetSecretRequest(BaseModel):
    """Request to set a secret in Firebase/GCP and GitHub Actions."""
    secret_name: str = Field(min_length=1, description="Name of the secret (e.g., 'SUPABASE_SERVICE_ROLE_KEY')")
    secret_value: str = Field(min_length=1, description="Value of the secret")
    gh_repo: str = Field(min_length=1, description="GitHub repository in 'owner/repo' format")
    firebase_project_id: str | None = Field(default=None, description="Firebase project ID (uses current gcloud project if not specified)")


@router.post("/set-secret")
async def set_secret(request: SetSecretRequest) -> dict:
    """Set a secret in both Firebase/GCP and GitHub Actions."""
    logger.info(f"Setting secret '{request.secret_name}' in Firebase and GitHub Actions")

    return await github_service.set_secret(
        secret_name=request.secret_name,
        secret_value=request.secret_value,
        gh_repo=request.gh_repo,
        firebase_project_id=request.firebase_project_id
    )


class GetEnvVariablesRequest(BaseModel):
    """Request to read environment variables from .env.prod.yaml."""
    working_directory: str = Field(min_length=1, description="Directory where .env.prod.yaml is located")


@router.post("/get-env-variables")
async def get_env_variables(request: GetEnvVariablesRequest) -> dict:
    """Read environment variables from .env.prod.yaml file."""
    logger.info(f"Getting env variables from {request.working_directory}")

    return await github_service.get_env_variables(
        working_directory=request.working_directory
    )
