"""Project discovery and API helpers, extracted from init.py."""

import json

from pathlib import Path

import httpx
from rich.prompt import Confirm, Prompt
from rich.table import Table

from gjalla_precommit.display.output import console, success, error, warning, info

# API timeout in seconds
API_TIMEOUT = 30.0


def _make_api_headers(api_key: str) -> dict:
    """Create headers for API requests."""
    return {
        "x-api-key": api_key,
        "Content-Type": "application/json",
        "Accept": "application/json",
    }


def verify_api_key(api_key: str, api_url: str) -> tuple[bool, str]:
    """Verify API key with the cloud service by listing projects.

    Returns:
        (success, detail) — detail contains the error reason on failure.
    """
    url = f"{api_url}/api/agent/projects"
    try:
        response = httpx.get(
            url,
            headers=_make_api_headers(api_key),
            timeout=API_TIMEOUT,
        )
        if response.status_code == 200:
            return True, ""
        if response.status_code == 401:
            return False, "API key was rejected by the server (HTTP 401 Unauthorized). API keys must have explicit access to projects — you can configure project access in the API key tab."
        if response.status_code == 403:
            return False, "API key lacks permission to access projects (HTTP 403 Forbidden)."
        # Try to extract a message from the response body
        try:
            body = response.json()
            detail = body.get("error", body.get("message", ""))
        except Exception:
            detail = response.text[:200] if response.text else ""
        suffix = f": {detail}" if detail else ""
        return False, f"Server returned HTTP {response.status_code}{suffix}."
    except httpx.ConnectError:
        return False, f"Could not connect to {api_url}. Check your network and API URL."
    except httpx.TimeoutException:
        return False, f"Request to {api_url} timed out after {API_TIMEOUT}s."
    except httpx.RequestError as exc:
        return False, f"Network error: {exc}"


def list_projects(api_key: str, api_url: str) -> list[dict] | None:
    """List all accessible projects.

    Returns:
        List of project dicts with 'id', 'title', 'description', or None on error.
    """
    try:
        response = httpx.get(
            f"{api_url}/api/agent/projects",
            headers=_make_api_headers(api_key),
            timeout=API_TIMEOUT,
        )
        if response.status_code != 200:
            return None

        data = response.json()
        return data.get("projects", [])
    except (httpx.RequestError, json.JSONDecodeError):
        return None


def discover_project(remote_url: str, api_key: str, api_url: str) -> dict | None:
    """Discover project from git remote URL by matching against accessible projects."""
    repo_name = None

    if remote_url.startswith("git@"):
        parts = remote_url.split(":")
        if len(parts) == 2:
            repo_name = parts[1].replace(".git", "").split("/")[-1]
    elif remote_url.startswith("https://"):
        repo_name = remote_url.replace(".git", "").split("/")[-1]

    if not repo_name:
        return None

    projects = list_projects(api_key, api_url)
    if not projects:
        return None

    # Try exact match first
    for project in projects:
        if project.get("title", "").lower() == repo_name.lower():
            return {"id": project["id"], "name": project["title"]}

    # Try partial match
    for project in projects:
        if repo_name.lower() in project.get("title", "").lower():
            return {"id": project["id"], "name": project["title"]}

    return None


def select_project_interactively(api_key: str, api_url: str) -> dict | None:
    """Show list of projects and let user select one."""
    projects = list_projects(api_key, api_url)
    if projects is None:
        error("Could not fetch projects from server. Check your API key and network connection.")
        return None

    if not projects:
        console.print()
        warning("No projects found in your gjalla account.")
        console.print()
        info("To add a project:")
        info("  1. Go to your gjalla dashboard at https://gjalla.io")
        info("  2. Click 'New Project' to create a project")
        info("  3. Run 'gjalla init' again to connect this repository")
        console.print()
        return None

    console.print()
    table = Table(title="Available Projects")
    table.add_column("#", justify="right", style="cyan")
    table.add_column("Name", style="bold")
    table.add_column("Description")

    for i, project in enumerate(projects, 1):
        desc = project.get("description", "")
        if len(desc) > 50:
            desc = desc[:47] + "..."
        table.add_row(str(i), project.get("title", ""), desc)

    console.print(table)
    console.print()

    choice = Prompt.ask(
        "[bold]Select project number[/bold]",
        default="1",
    )

    try:
        index = int(choice) - 1
        if 0 <= index < len(projects):
            selected = projects[index]
            return {"id": selected["id"], "name": selected["title"]}
    except ValueError:
        pass

    error("Invalid selection")
    return None


def discover_or_select_project(
    repo_root: Path,
    api_key: str,
    api_url: str,
    project_id: int | None = None,
) -> dict | None:
    """Discover project from git remote or prompt for interactive selection.

    Returns:
        {"id": ..., "name": ...} dict, or None if selection failed.
    """
    if project_id:
        info(f"Using provided project ID: {project_id}")
        return {"id": project_id, "name": "unknown"}

    from ..tools.git_tools import get_remote_url

    project_info = None
    remote_url = get_remote_url(repo_root)
    if remote_url and not remote_url.startswith("Error:"):
        info(f"Found git remote: {remote_url}")
        discovered = discover_project(remote_url, api_key, api_url)
        if discovered:
            info(f"Discovered project: {discovered['name']}")
            if Confirm.ask("Is this the correct project?", default=True):
                project_info = discovered

    if not project_info:
        info("Select your project from the available options:")
        project_info = select_project_interactively(api_key, api_url)

    return project_info
