"""Built-in dataset loaders for DropThe.org open data.

Loads CSV datasets from the companion GitHub repository:
https://github.com/arnaudleroy-studio/dropthe-datasets-public

    >>> import dropthe
    >>> movies = dropthe.movies()
    >>> len(movies)
    154965

Full data hub: https://dropthe.org/data/
"""

from __future__ import annotations

import csv
import io
from pathlib import Path

import httpx

GITHUB_RAW = "https://raw.githubusercontent.com/arnaudleroy-studio/dropthe-datasets/main/datasets"

_DATASETS = {
    "movies": "movies/movies-ratings.csv",
    "crypto": "crypto-mortality/crypto-mortality.csv",
    "companies": "companies/companies.csv",
    "games": "gaming-ratings/gaming-ratings.csv",
    "universities": "universities/universities.csv",
    "streaming": "streaming/streaming-by-service-country.csv",
}

_cache: dict[str, list[dict]] = {}


def _load(name: str, limit: int | None = None) -> list[dict]:
    """Fetch and parse a CSV dataset from GitHub."""
    if name in _cache:
        data = _cache[name]
        return data[:limit] if limit else data

    url = f"{GITHUB_RAW}/{_DATASETS[name]}"
    resp = httpx.get(url, timeout=60, follow_redirects=True)
    resp.raise_for_status()

    reader = csv.DictReader(io.StringIO(resp.text))
    rows = list(reader)
    _cache[name] = rows
    return rows[:limit] if limit else rows


def _to_dataframe(rows: list[dict]):
    try:
        import pandas as pd
        return pd.DataFrame(rows)
    except ImportError:
        raise ImportError(
            "pandas is required for DataFrame output. "
            "Install with: pip install dropthe[pandas]"
        )


def movies(limit: int | None = None, *, as_dataframe: bool = False):
    """154,965 movies with ratings, votes, genres, and runtime.

    Columns: name, slug, rating, vote_count, release_date, language, genres, runtime_min

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Source: https://dropthe.org/data/
    Dataset: https://github.com/arnaudleroy-studio/dropthe-datasets-public
    """
    rows = _load("movies", limit)
    return _to_dataframe(rows) if as_dataframe else rows


def crypto(limit: int | None = None, *, as_dataframe: bool = False):
    """15,261 cryptocurrencies with price, all-time-high, and mortality status.

    Columns: name, slug, symbol, current_price, all_time_high, ath_date, pct_of_ath

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Analysis: https://dropthe.org/crypto/crypto-graveyard-dead-coins-data/
    """
    rows = _load("crypto", limit)
    return _to_dataframe(rows) if as_dataframe else rows


def companies(limit: int | None = None, *, as_dataframe: bool = False):
    """19,181 companies with country, industry, founding year, and employees.

    Columns: name, slug, country, founded, industry, employees

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Analysis: https://dropthe.org/money/sp500-company-turnover-lifespan-data-3/
    """
    rows = _load("companies", limit)
    return _to_dataframe(rows) if as_dataframe else rows


def games(limit: int | None = None, *, as_dataframe: bool = False):
    """19,189 games with IGDB ratings, genres, platforms, and developers.

    Columns: name, slug, rating, release_date, genres, platforms, developers, rating_count

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Analysis: https://dropthe.org/gaming/highest-rated-games-all-time-data/
    """
    rows = _load("games", limit)
    return _to_dataframe(rows) if as_dataframe else rows


def universities(limit: int | None = None, *, as_dataframe: bool = False):
    """27,099 universities with country, city, type, and student count.

    Columns: name, slug, country, city, founded, type, students

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Analysis: https://dropthe.org/tech/universities-most-tech-ceos-ivy-league-premium/
    """
    rows = _load("universities", limit)
    return _to_dataframe(rows) if as_dataframe else rows


def streaming(limit: int | None = None, *, as_dataframe: bool = False):
    """1,938 streaming availability records across 20+ services and 50+ countries.

    Args:
        limit: Max rows to return (None for all).
        as_dataframe: Return pandas DataFrame.

    Analysis: https://dropthe.org/data/statistics/streaming/
    """
    rows = _load("streaming", limit)
    return _to_dataframe(rows) if as_dataframe else rows
