#!/bin/bash
# detect-platform.sh - Detect git platform (Gitea or GitHub) for current repo
# Usage: source detect-platform.sh && detect_platform
#        or: ./detect-platform.sh (prints platform name)

detect_platform() {
    local remote_url
    remote_url=$(git remote get-url origin 2>/dev/null)

    if [[ -z "$remote_url" ]]; then
        echo "error: not a git repository or no origin remote" >&2
        return 1
    fi

    # Check for GitHub
    if [[ "$remote_url" == *"github.com"* ]]; then
        PLATFORM="github"
        export PLATFORM
        echo "github"
        return 0
    fi

    # Check for common Gitea indicators
    # Gitea URLs typically don't contain github.com, gitlab.com, bitbucket.org
    if [[ "$remote_url" != *"gitlab.com"* ]] && \
       [[ "$remote_url" != *"bitbucket.org"* ]]; then
        # Assume Gitea for self-hosted repos
        PLATFORM="gitea"
        export PLATFORM
        echo "gitea"
        return 0
    fi

    PLATFORM="unknown"
    export PLATFORM
    echo "unknown"
    return 1
}

get_repo_info() {
    local remote_url
    remote_url=$(git remote get-url origin 2>/dev/null)

    if [[ -z "$remote_url" ]]; then
        echo "error: not a git repository or no origin remote" >&2
        return 1
    fi

    # Extract owner/repo from URL
    # Handles: git@host:owner/repo.git, https://host/owner/repo.git, https://host/owner/repo
    local repo_path
    if [[ "$remote_url" == git@* ]]; then
        repo_path="${remote_url#*:}"
    else
        repo_path="${remote_url#*://}"
        repo_path="${repo_path#*/}"
    fi

    # Remove .git suffix if present
    repo_path="${repo_path%.git}"

    echo "$repo_path"
}

get_repo_owner() {
    local repo_info
    repo_info=$(get_repo_info)
    echo "${repo_info%%/*}"
}

get_repo_name() {
    local repo_info
    repo_info=$(get_repo_info)
    echo "${repo_info##*/}"
}

get_repo_slug() {
    get_repo_info
}

gitea_url_matches_host() {
    local url="${1:-}" host="${2:-}"
    [[ -n "$url" && -n "$host" ]] || return 1
    [[ "${url%/}" == "https://$host" || "${url%/}" == "http://$host" || "${url%/}" == *"//$host" ]]
}

get_gitea_service_for_host() {
    local host="$1"
    local cred_file="${MOSAIC_CREDENTIALS_FILE:-}"
    if [[ -z "$cred_file" ]]; then
        # Same resolution chain as _lib/credentials.sh: profile HOME, then
        # host-level /etc only if it exists; neither existing keeps the
        # $HOME default (matches the lib's final := fallback).
        cred_file="$HOME/.config/mosaic/credentials.json"
        if [[ ! -f "$cred_file" && -f /etc/mosaic/credentials.json ]]; then
            cred_file="/etc/mosaic/credentials.json"
        fi
    fi

    case "$host" in
        git.mosaicstack.dev)
            echo "mosaicstack"
            return 0
            ;;
        git.uscllc.com)
            echo "usc"
            return 0
            ;;
    esac

    [[ -f "$cred_file" ]] || return 1
    command -v jq >/dev/null 2>&1 || return 1

    jq -r --arg host "$host" '
        .gitea // {}
        | to_entries[]
        | select((.value.url // "" | sub("/+$"; "")) | test("https?://" + $host + "$"))
        | .key
    ' "$cred_file" | head -n 1
}

find_tea_login_for_host() {
    local host="$1"
    local logins_json

    command -v tea >/dev/null 2>&1 || return 1
    logins_json=$(tea login list --output json 2>/dev/null) || return 1
    TEA_LOGINS_JSON="$logins_json" python3 - "$host" <<'PY'
import json
import os
import sys
from urllib.parse import urlparse

host = sys.argv[1]
try:
    logins = json.loads(os.environ.get("TEA_LOGINS_JSON", "[]"))
except Exception:
    raise SystemExit(1)

for login in logins if isinstance(logins, list) else []:
    url = str(login.get("url") or login.get("URL") or "")
    name = str(login.get("name") or login.get("Name") or "")
    parsed = urlparse(url)
    if parsed.hostname == host and name:
        print(name)
        raise SystemExit(0)

raise SystemExit(1)
PY
}

tea_login_matches_host() {
    local login_name="$1" host="$2"
    local logins_json

    command -v tea >/dev/null 2>&1 || return 1
    logins_json=$(tea login list --output json 2>/dev/null) || return 1
    TEA_LOGINS_JSON="$logins_json" python3 - "$login_name" "$host" <<'PY'
import json
import os
import sys
from urllib.parse import urlparse

login_name, host = sys.argv[1], sys.argv[2]
try:
    logins = json.loads(os.environ.get("TEA_LOGINS_JSON", "[]"))
except Exception:
    raise SystemExit(1)

for login in logins if isinstance(logins, list) else []:
    url = str(login.get("url") or login.get("URL") or "")
    name = str(login.get("name") or login.get("Name") or "")
    parsed = urlparse(url)
    if name == login_name and parsed.hostname == host:
        raise SystemExit(0)

raise SystemExit(1)
PY
}

# Emit an actionable diagnostic to stderr when no tea login resolves for a host.
# Callers that have a working API fallback may ignore the non-zero return of
# get_gitea_login_for_host; this turns the previously SILENT failure into a loud,
# greppable hint (available logins + override + add-login instructions). Printed to
# stderr only, so it never contaminates stdout (the resolved login name) or log
# assertions that capture tea/curl invocations.
print_gitea_login_diagnostic() {
    local host="${1:-<unknown>}"
    local available
    available=$(
        command -v tea >/dev/null 2>&1 || { echo "(tea CLI not installed)"; exit 0; }
        logins_json=$(tea login list --output json 2>/dev/null) || { echo "(could not query tea login list)"; exit 0; }
        TEA_LOGINS_JSON="$logins_json" python3 - <<'PY'
import json, os
from urllib.parse import urlparse
try:
    logins = json.loads(os.environ.get("TEA_LOGINS_JSON", "[]"))
except Exception:
    logins = []
rows = []
for login in logins if isinstance(logins, list) else []:
    name = str(login.get("name") or login.get("Name") or "")
    url = str(login.get("url") or login.get("URL") or "")
    host = urlparse(url).hostname or "?"
    if name:
        rows.append(f"{name} (host: {host})")
print("; ".join(rows) if rows else "(none configured)")
PY
    )
    {
        echo "Error: no Gitea tea login matches host '$host'."
        echo "  Available tea logins: ${available}"
        echo "  Fix: set GITEA_LOGIN to a login whose URL host is '$host',"
        echo "       or add one: tea login add --name <name> --url https://$host --token <token>"
    } >&2
}

get_gitea_login_for_host() {
    local host="${1:-}"
    local login

    if [[ -z "$host" ]]; then
        host=$(get_remote_host) || return 1
    fi

    if [[ -n "${GITEA_LOGIN:-}" ]]; then
        if tea_login_matches_host "$GITEA_LOGIN" "$host"; then
            echo "$GITEA_LOGIN"
            return 0
        fi
    fi

    login=$(find_tea_login_for_host "$host" || true)
    if [[ -n "$login" ]]; then
        echo "$login"
        return 0
    fi

    print_gitea_login_diagnostic "$host"
    return 1
}

# Validate the current authenticated Gitea user for a resolved Tea login.
# Tea stores a user name with each login which can become stale after user rename,
# token rotation, or server migration. Querying /user derives the identity from the
# active credential instead of trusting that saved name. Callers fall back to the
# host-scoped API path when this validation fails.
get_gitea_authenticated_user() {
    local login_name="$1" response

    command -v tea >/dev/null 2>&1 || return 1
    response=$(tea api --login "$login_name" /user 2>/dev/null) || return 1
    TEA_AUTHENTICATED_USER_JSON="$response" python3 - <<'PY'
import json
import os

try:
    user = json.loads(os.environ["TEA_AUTHENTICATED_USER_JSON"])
except (KeyError, json.JSONDecodeError):
    raise SystemExit(1)

login = user.get("login") if isinstance(user, dict) else None
if isinstance(login, str) and login:
    print(login)
    raise SystemExit(0)
raise SystemExit(1)
PY
}

get_default_tea_login() {
    local logins_json

    command -v tea >/dev/null 2>&1 || return 1
    logins_json=$(tea login list --output json 2>/dev/null) || return 1
    TEA_LOGINS_JSON="$logins_json" python3 - <<'PY'
import json
import os

try:
    logins = json.loads(os.environ.get("TEA_LOGINS_JSON", "[]"))
except Exception:
    raise SystemExit(1)

if not isinstance(logins, list) or not logins:
    raise SystemExit(1)

for login in logins:
    if not isinstance(login, dict):
        continue
    is_default = str(login.get("default") or login.get("Default") or "").lower()
    name = str(login.get("name") or login.get("Name") or "")
    if name and is_default == "true":
        print(name)
        raise SystemExit(0)

for login in logins:
    if not isinstance(login, dict):
        continue
    name = str(login.get("name") or login.get("Name") or "")
    if name:
        print(name)
        raise SystemExit(0)

raise SystemExit(1)
PY
}

get_gitea_login_for_repo_override() {
    local login

    if [[ -n "${GITEA_LOGIN:-}" ]]; then
        echo "$GITEA_LOGIN"
        return 0
    fi

    login=$(get_default_tea_login || true)
    if [[ -n "$login" ]]; then
        echo "$login"
        return 0
    fi

    return 1
}

get_host_from_url() {
    local url="${1:-}"
    [[ -n "$url" ]] || return 1

    python3 - "$url" <<'PY'
import sys
from urllib.parse import urlparse

parsed = urlparse(sys.argv[1])
if parsed.hostname:
    print(parsed.hostname)
    raise SystemExit(0)
raise SystemExit(1)
PY
}

get_gitea_api_host_for_repo_override() {
    if [[ -n "${GITEA_HOST:-}" ]]; then
        echo "$GITEA_HOST"
        return 0
    fi

    get_host_from_url "${GITEA_URL:-}"
}

get_gitea_repo_args() {
    local repo host login
    repo=$(get_repo_slug) || return 1
    host=$(get_remote_host) || return 1
    login=$(get_gitea_login_for_host "$host") || return 1
    printf -- '--repo %q --login %q' "$repo" "$login"
}

get_gitea_login() {
    get_gitea_login_for_host "$(get_remote_host)"
}

get_remote_host() {
    local remote_url
    remote_url=$(git remote get-url origin 2>/dev/null || true)
    if [[ -z "$remote_url" ]]; then
        return 1
    fi
    if [[ "$remote_url" =~ ^https?://([^/]+)/ ]]; then
        local host="${BASH_REMATCH[1]}"
        echo "${host##*@}"
        return 0
    fi
    if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
        echo "${BASH_REMATCH[1]}"
        return 0
    fi
    return 1
}

# Resolve a Gitea API token for the given host.
# Priority: Mosaic credential loader → GITEA_TOKEN env → ~/.git-credentials
get_gitea_token() {
    local host="$1"
    local script_dir
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local cred_loader="$script_dir/../_lib/credentials.sh"

    # 1. Mosaic credential loader (host → service mapping, run in subshell to avoid polluting env)
    if [[ -f "$cred_loader" ]]; then
        local token
        token=$(
            # shellcheck source=/dev/null
            source "$cred_loader"
            # Host-specific wrapper resolution must not inherit caller/global GITEA_*.
            # load_credentials intentionally preserves existing env vars for interactive use,
            # but metadata/merge wrappers need credentials matching the remote host.
            unset GITEA_TOKEN GITEA_URL
            case "$host" in
                git.mosaicstack.dev) load_credentials gitea-mosaicstack 2>/dev/null ;;
                git.uscllc.com)      load_credentials gitea-usc 2>/dev/null ;;
                *)
                    local matched=false
                    for svc in gitea-mosaicstack gitea-usc; do
                        unset GITEA_TOKEN GITEA_URL
                        load_credentials "$svc" 2>/dev/null || continue
                        if [[ "${GITEA_URL:-}" == "https://$host" || "${GITEA_URL:-}" == "http://$host" || "${GITEA_URL:-}" == *"//$host" ]]; then
                            matched=true
                            break
                        fi
                    done
                    if [[ "$matched" != true ]]; then
                        unset GITEA_TOKEN GITEA_URL
                    fi
                    ;;
            esac
            echo "${GITEA_TOKEN:-}"
        )
        if [[ -n "$token" ]]; then
            echo "$token"
            return 0
        fi
    fi

    # 2. GITEA_TOKEN env var (only when GITEA_URL, if present, matches the remote host)
    if [[ -n "${GITEA_TOKEN:-}" ]]; then
        if [[ -z "${GITEA_URL:-}" || "${GITEA_URL:-}" == "https://$host" || "${GITEA_URL:-}" == "http://$host" || "${GITEA_URL:-}" == *"//$host" ]]; then
            echo "$GITEA_TOKEN"
            return 0
        fi
    fi

    # 3. ~/.git-credentials file
    local creds="$HOME/.git-credentials"
    if [[ -f "$creds" ]]; then
        local token
        token=$(grep -F "$host" "$creds" 2>/dev/null | sed -n 's#https\?://[^@]*:\([^@/]*\)@.*#\1#p' | head -n 1)
        if [[ -n "$token" ]]; then
            echo "$token"
            return 0
        fi
    fi

    return 1
}

# Resolve HTTPS basic auth credentials for a Gitea host from ~/.git-credentials.
# Prints "username:password" for direct curl -u consumption. Callers must not log it.
get_gitea_basic_auth() {
    local host="$1"
    local creds="$HOME/.git-credentials"
    if [[ ! -f "$creds" ]]; then
        return 1
    fi

    python3 - "$host" "$creds" <<'PY'
import sys
from pathlib import Path
from urllib.parse import unquote, urlparse

host = sys.argv[1]
creds = Path(sys.argv[2])

for line in creds.read_text(encoding="utf-8").splitlines():
    parsed = urlparse(line.strip())
    if parsed.hostname != host:
        continue
    username = unquote(parsed.username or "")
    password = unquote(parsed.password or "")
    if username and password:
        print(f"{username}:{password}")
        raise SystemExit(0)

raise SystemExit(1)
PY
}

# If script is run directly (not sourced), output the platform
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    detect_platform
fi
