"""  # pylint: disable=duplicate-code
llmpm push <repo_id>

Uploads a locally installed (or local directory) model to HuggingFace Hub.

Examples:
  llmpm push my-org/my-model
  llmpm push my-org/my-model --path ./my-local-model
  llmpm push my-org/my-model --private
"""

from __future__ import annotations

import os
from pathlib import Path

import click
from huggingface_hub import HfApi, create_repo  # type: ignore

from llmpm import display
from llmpm.core import registry


def _resolve_hf_token(explicit: str | None) -> str | None:
    """Return the best available HuggingFace token, or None."""
    if explicit:
        return explicit
    token = (
        os.environ.get("HF_TOKEN")
        or os.environ.get("HUGGING_FACE_HUB_TOKEN")
    )
    if token:
        return token
    try:
        from huggingface_hub import get_token  # pylint: disable=import-outside-toplevel
        return get_token()
    except ImportError:
        pass
    token_file = Path.home() / ".huggingface" / "token"
    if token_file.exists():
        return token_file.read_text(encoding="utf-8").strip() or None
    return None


@click.command("push")
@click.argument("repo_id")
@click.option(
    "--path", "local_path",
    default=None,
    type=click.Path(exists=True, file_okay=True, dir_okay=True, path_type=Path),
    help="Local model directory or file. Defaults to the installed model path.",
)
@click.option(
    "--private", is_flag=True,
    help="Create a private repository (default: public).",
)
@click.option(
    "--token",
    default=None,
    envvar=["HF_TOKEN", "HUGGING_FACE_HUB_TOKEN"],
    help="HuggingFace API token (or set HF_TOKEN env var).",
)
@click.option(
    "--message", "-m",
    default="Upload via llmpm",
    show_default=True,
    help="Commit message for the upload.",
)
def push(
    repo_id: str,
    local_path: Path | None,
    private: bool,
    token: str | None,
    message: str,
) -> None:
    """Upload a model to HuggingFace Hub."""
    display.header(f"push {repo_id}")
    display.blank()

    # ── resolve token ─────────────────────────────────────────────────────────
    resolved_token = _resolve_hf_token(token)
    if not resolved_token:
        display.error(
            "HuggingFace token not found.\n\n"
            "  Authenticate with:\n\n"
            "    [bold cyan]huggingface-cli login[/]\n\n"
            "  or set the [bold]HF_TOKEN[/] environment variable."
        )
        raise SystemExit(1)

    # ── resolve local path ────────────────────────────────────────────────────
    if local_path is None:
        entry = registry.get_model(repo_id)
        if entry:
            local_path = Path(entry["path"])
        else:
            display.error(
                f"Model [bold]{repo_id}[/] is not installed and "
                f"no --path was provided.\n\n"
                f"  Install first:  [bold cyan]llmpm install {repo_id}[/]\n"
                f"  or specify:      "
                f"[bold cyan]llmpm push {repo_id} --path ./my-model[/]"
            )
            raise SystemExit(1)

    display.step(f"Local path: [dim]{local_path}[/]")

    # ── create repo if needed ─────────────────────────────────────────────────
    display.step(
        f"Creating repository [bold]{repo_id}[/] (if it doesn't exist)…"
    )

    api = HfApi(token=resolved_token)

    try:
        create_repo(
            repo_id,
            token=resolved_token,
            private=private,
            repo_type="model",
            exist_ok=True,
        )
        display.ok("Repository ready")
    except Exception as exc:  # pylint: disable=broad-except
        display.error(f"Failed to create repository: {exc}")
        raise SystemExit(1) from None

    # ── upload ────────────────────────────────────────────────────────────────
    display.blank()
    repo_url = f"https://huggingface.co/{repo_id}"

    if local_path.is_file():
        display.step(f"Uploading file [bold]{local_path.name}[/]…")
        try:
            api.upload_file(
                path_or_fileobj=str(local_path),
                path_in_repo=local_path.name,
                repo_id=repo_id,
                repo_type="model",
                commit_message=message,
                token=resolved_token,
            )
        except Exception as exc:  # pylint: disable=broad-except
            display.error(f"Upload failed: {exc}")
            raise SystemExit(1) from None
    else:
        display.step(f"Uploading directory [bold]{local_path}[/]…")
        try:
            api.upload_folder(
                folder_path=str(local_path),
                repo_id=repo_id,
                repo_type="model",
                commit_message=message,
                token=resolved_token,
            )
        except Exception as exc:  # pylint: disable=broad-except
            display.error(f"Upload failed: {exc}")
            raise SystemExit(1) from None

    display.blank()
    display.push_summary(repo_id, repo_url)
