"""
link command — generate or redeem cross-channel link codes.

  skilark link          → generate a 6-character code to give to another channel
  skilark link ABC123   → redeem a code received from another channel

The linking system lets users connect their CLI identity to a second Skilark
channel (e.g. the Telegram bot) so progress and streaks are shared across both.
Codes are single-use and expire after 10 minutes.
"""

import re

from rich.console import Console
from rich.markup import escape

from skilark_cli.client import SkilarkClient
from skilark_cli.config_store import ConfigStore

_LINK_CODE_RE = re.compile(r"[A-Z0-9]{6}")

console = Console()


def dispatch(link_args: list[str]) -> None:
    """Entry point called from main.py.

    Handles config loading and client setup, then delegates to ``run()``.
    Exits early with a friendly message if the user has not yet completed
    onboarding.

    Args:
        link_args: Remaining argv after the ``link`` token.  The first element,
                   if present, is the code to redeem.
    """
    config_store = ConfigStore()

    if config_store.is_first_run():
        console.print("[dim]Run 'skilark today' first to get started.[/dim]")
        return

    config = config_store.load()
    client = SkilarkClient(base_url=config["api_url"], user_id=config["user_id"])

    code = link_args[0] if link_args else None
    run(client=client, code=code)


def run(client: SkilarkClient, code: str | None) -> None:
    """Execute the link command.

    Separated from ``dispatch()`` so tests can inject a mock client without
    touching the filesystem or network.

    Args:
        client: Authenticated SkilarkClient instance (user_id already set).
        code:   A 6-character link code to redeem, or None to generate a new
                code instead.
    """
    if code is None:
        _generate(client)
    else:
        _redeem(client, code)


def _generate(client: SkilarkClient) -> None:
    """Request a fresh link code from the API and display it."""
    result = client.create_link_code()
    console.print(f"\n[bold]Your link code:[/bold] [cyan]{escape(result['code'])}[/cyan]")
    console.print("Send this code to your other Skilark channel (e.g. Telegram bot).")
    console.print("[dim]Expires in 10 minutes.[/dim]\n")


def _redeem(client: SkilarkClient, code: str) -> None:
    """Redeem the given code, attaching the current CLI identity to the linked account."""
    normalized_code = code.upper().strip()
    if not _LINK_CODE_RE.fullmatch(normalized_code):
        console.print(
            "[red]Invalid link code. Codes must be exactly 6 uppercase letters or digits "
            "(e.g. ABC123).[/red]"
        )
        return

    channel_id = client.user_id
    if channel_id is None:
        console.print("[red]Not logged in. Run 'skilark today' first to get started.[/red]")
        return

    client.redeem_link_code(
        code=normalized_code,
        channel_type="cli",
        channel_id=channel_id,
    )
    console.print("\n[green]✓[/green] Linked! Your accounts are now connected.\n")
