"""PAT resolution and storage for GitLab forge authentication."""

from __future__ import annotations

import configparser
import json
import os
from dataclasses import dataclass
from pathlib import Path

AUTH_FILE = Path.home() / ".config" / "project-hub" / "auth.json"
PYTHON_GITLAB_CFG = Path.home() / ".python-gitlab.cfg"


@dataclass
class AuthInfo:
    """Authentication status for a single forge instance."""
    instance: str
    token: str | None
    authenticated: bool


def resolve_token(instance: str) -> str | None:
    """Return a PAT for *instance*, or None if nothing is found.

    Resolution order:
    1. AUTH_FILE  (~/.config/project-hub/auth.json)
    2. GITLAB_TOKEN env var  — only for "gitlab.com"
    3. ~/.python-gitlab.cfg  (INI, configparser)
    """
    # 1. auth.json
    if AUTH_FILE.exists():
        try:
            data = json.loads(AUTH_FILE.read_text())
            if instance in data:
                return data[instance]
        except (json.JSONDecodeError, OSError):
            pass

    # 2. env var — gitlab.com only
    if instance == "gitlab.com":
        token = os.environ.get("GITLAB_TOKEN")
        if token:
            return token

    # 3. ~/.python-gitlab.cfg
    if PYTHON_GITLAB_CFG.exists():
        cfg = configparser.ConfigParser()
        cfg.read(PYTHON_GITLAB_CFG)

        target_url = f"https://{instance}"

        # Search all sections for a matching url
        for section in cfg.sections():
            if section == "global":
                continue
            if cfg.get(section, "url", fallback=None) == target_url:
                token = cfg.get(section, "private_token", fallback=None)
                if token:
                    return token

        # Fall back to global.default -> that section
        default_section = cfg.get("global", "default", fallback=None)
        if default_section and cfg.has_section(default_section):
            if cfg.get(default_section, "url", fallback=None) == target_url:
                token = cfg.get(default_section, "private_token", fallback=None)
                if token:
                    return token

    return None


def store_token(instance: str, token: str) -> None:
    """Persist *token* for *instance* in AUTH_FILE, creating it if needed."""
    AUTH_FILE.parent.mkdir(parents=True, exist_ok=True)

    data: dict[str, str] = {}
    if AUTH_FILE.exists():
        try:
            data = json.loads(AUTH_FILE.read_text())
        except (json.JSONDecodeError, OSError):
            pass

    data[instance] = token
    AUTH_FILE.write_text(json.dumps(data, indent=2))
    AUTH_FILE.chmod(0o600)


def auth_status() -> list[AuthInfo]:
    """Return an AuthInfo entry for every instance recorded in AUTH_FILE."""
    if not AUTH_FILE.exists():
        return []

    try:
        data = json.loads(AUTH_FILE.read_text())
    except (json.JSONDecodeError, OSError):
        return []

    return [
        AuthInfo(instance=inst, token=tok, authenticated=bool(tok))
        for inst, tok in data.items()
    ]
