"""CLI entry point for mdash — unified data explorer."""

from __future__ import annotations

import os
import shlex
import sys
import webbrowser

import click
import httpx


def _collect_env_args() -> list[str]:
    """Collect CLI args from MDASH_* environment variables.

    Scans for env vars with the MDASH_ prefix, parses each value
    using shell-like splitting (handles quoting and multi-line values),
    and returns the combined argument list sorted by variable name.
    """
    env_vars = sorted(
        (k, v) for k, v in os.environ.items() if k.startswith("MDASH_") and v.strip()
    )
    if not env_vars:
        return []

    args: list[str] = []
    loaded: list[str] = []
    for key, value in env_vars:
        try:
            parsed = shlex.split(value)
            args.extend(parsed)
            loaded.append(key)
        except ValueError as e:
            click.echo(f"  warning: failed to parse {key}: {e}", err=True)

    if loaded:
        click.echo(f"  env: loaded args from {', '.join(loaded)}")

    return args


def _parse_labeled_entry(entry: str, default_label_fn):
    """Parse 'label=url' or plain 'url' format. Returns (label, url)."""
    if "=" in entry:
        eq_pos = entry.index("=")
        potential_label = entry[:eq_pos]
        # If the part before = doesn't contain ://, treat as label=url
        if "://" not in potential_label:
            return potential_label.strip(), entry[eq_pos + 1 :].strip()
    return default_label_fn(entry), entry


def _pg_label(url: str) -> str:
    from urllib.parse import urlparse

    try:
        parsed = urlparse(url)
        return parsed.path.lstrip("/") or parsed.hostname or "postgres"
    except Exception:
        return "postgres"


def _redis_label(url: str) -> str:
    from urllib.parse import urlparse

    try:
        parsed = urlparse(url)
        host = parsed.hostname or "redis"
        port = parsed.port or 6379
        return f"{host}:{port}"
    except Exception:
        return "redis"


def _s3_label_from_endpoint(url: str) -> str:
    from urllib.parse import urlparse

    try:
        parsed = urlparse(url)
        return parsed.hostname or "s3"
    except Exception:
        return "s3"


def _bq_label(ref: str) -> str:
    return ref


@click.command()
@click.option("--db", multiple=True, help="PostgreSQL connection (label=url or url). Repeatable.")
@click.option("--redis-url", multiple=True, help="Redis connection (label=url or url). Repeatable.")
@click.option("--s3-endpoint", envvar="S3_ENDPOINT_URL", help="S3 endpoint URL")
@click.option("--s3-access-key", envvar="AWS_ACCESS_KEY_ID", help="AWS access key")
@click.option("--s3-secret-key", envvar="AWS_SECRET_ACCESS_KEY", help="AWS secret key")
@click.option("--s3-region", default="us-east-1", help="AWS region (default: us-east-1)")
@click.option("--s3-profile", multiple=True, help="AWS profile name. Repeatable.")
@click.option("--bigquery", multiple=True, help="BigQuery connection (label=project/dataset or project/dataset). Repeatable.")
@click.option("--bigquery-credentials", default=None, help="Path to BigQuery service account JSON file")
@click.option("--port", default=8430, type=int, help="Backend port")
@click.option("--page-size", default=100, type=int, help="Rows per page (default: 100)")
@click.option("--no-open", is_flag=True, help="Don't auto-open browser")
def main(
    db: tuple[str, ...],
    redis_url: tuple[str, ...],
    s3_endpoint: str | None,
    s3_access_key: str | None,
    s3_secret_key: str | None,
    s3_region: str,
    s3_profile: tuple[str, ...],
    bigquery: tuple[str, ...],
    bigquery_credentials: str | None,
    port: int,
    page_size: int,
    no_open: bool,
):
    """Launch mdash — a unified browser-based explorer for PostgreSQL, BigQuery, Redis, and S3."""
    url = f"http://localhost:{port}"

    try:
        resp = httpx.get(f"{url}/api/health", timeout=2)
        if resp.status_code == 200:
            click.echo(f"  mdash already running on {url}")
            if not no_open:
                webbrowser.open(url)
            return
    except Exception:
        pass

    # Parse --db entries (support label=url or plain url)
    # Also check DATABASE_URL env var as fallback if no --db given
    pg_instances: list[tuple[str, str]] = []
    db_entries = list(db)
    if not db_entries:
        env_db = os.environ.get("DATABASE_URL")
        if env_db:
            db_entries = [env_db]
    for entry in db_entries:
        label, conn_url = _parse_labeled_entry(entry, _pg_label)
        pg_instances.append((label, conn_url))

    # Parse --redis-url entries
    redis_instances: list[tuple[str, str]] = []
    redis_entries = list(redis_url)
    if not redis_entries:
        env_redis = os.environ.get("REDIS_URL")
        if env_redis:
            redis_entries = [env_redis]
    for entry in redis_entries:
        label, conn_url = _parse_labeled_entry(entry, _redis_label)
        redis_instances.append((label, conn_url))

    # Build S3 instances from --s3-profile and/or explicit credentials
    s3_instances: list[dict] = []
    for profile_name in s3_profile:
        s3_instances.append({"label": profile_name, "profile": profile_name})
    if s3_endpoint or s3_access_key:
        label = _s3_label_from_endpoint(s3_endpoint) if s3_endpoint else "s3"
        s3_instances.append({
            "label": label,
            "endpoint_url": s3_endpoint or None,
            "access_key": s3_access_key or None,
            "secret_key": s3_secret_key or None,
            "region": s3_region,
        })

    # Parse --bigquery entries (format: project/dataset or project.dataset)
    bq_instances: list[tuple[str, str, str, str | None]] = []
    for entry in bigquery:
        label, bq_ref = _parse_labeled_entry(entry, _bq_label)
        if "/" in bq_ref:
            project, dataset = bq_ref.split("/", 1)
        elif "." in bq_ref:
            project, dataset = bq_ref.split(".", 1)
        else:
            click.echo(f"  warning: invalid BigQuery format (expected project/dataset): {bq_ref}", err=True)
            continue
        if label == bq_ref:
            label = f"{project}/{dataset}"
        bq_instances.append((label, project, dataset, bigquery_credentials))

    click.echo(f"  mdash ● listening on {url}")
    sources = []
    if pg_instances:
        labels = [l for l, _ in pg_instances]
        sources.append(f"postgres ({', '.join(labels)})")
    if bq_instances:
        labels = [l for l, _, _, _ in bq_instances]
        sources.append(f"bigquery ({', '.join(labels)})")
    if redis_instances:
        labels = [l for l, _ in redis_instances]
        sources.append(f"redis ({', '.join(labels)})")
    if s3_instances:
        labels = [c["label"] for c in s3_instances]
        sources.append(f"s3 ({', '.join(labels)})")
    if sources:
        click.echo(f"  sources: {', '.join(sources)}")
    else:
        click.echo("  no sources configured — connect via the UI")
    click.echo("  press Ctrl+C to stop")

    if not no_open:
        import threading

        threading.Timer(1.5, lambda: webbrowser.open(url)).start()

    import uvicorn

    from .server import create_app

    app = create_app(
        pg_instances=pg_instances,
        redis_instances=redis_instances,
        s3_instances=s3_instances,
        bq_instances=bq_instances,
        page_size=page_size,
    )
    uvicorn.run(app, host="0.0.0.0", port=port, log_level="warning")


def cli():
    """Entry point that loads MDASH_* env vars before invoking Click."""
    env_args = _collect_env_args()
    if env_args:
        # Prepend env args so explicit CLI args take precedence (appended after)
        sys.argv = [sys.argv[0]] + env_args + sys.argv[1:]
    main()


if __name__ == "__main__":
    cli()
