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 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
    )
