from __future__ import annotations

from dataclasses import dataclass
from types import SimpleNamespace
from typing import List, Optional, Sequence

from . import dao


@dataclass(frozen=True)
class TaxonSummary:
    taxon_id: str
    label: str
    rank: Optional[str]
    status: Optional[str]
    authorship: Optional[str] = None
    vernacular: Optional[str] = None
    children_count: int = 0
    descendant_count: int = 0


def get_taxon_detail(taxon_id: str, *, order_by: str = "rank") -> Optional[dict]:
    taxon = dao.get_taxon_by_id(taxon_id)
    if not taxon:
        return None

    # For synonyms, use the accepted_taxon_id; for accepted taxa, use the taxon_id itself
    accepted_id = taxon.get('accepted_taxon_id') or taxon_id

    return {
        "taxon": taxon,
        "lineage": dao.get_lineage_up(taxon_id),
        "children": dao.get_children(taxon_id, order_by=order_by),
        "synonyms": dao.get_synonyms_for(accepted_id),
        "vernaculars": dao.get_vernaculars_for(taxon_id),
    }


def browse_roots(*, order_by: str = "rank") -> Sequence[TaxonSummary]:
    nodes = dao.get_children(parent_taxon_id=None, order_by=order_by)
    return [
        TaxonSummary(
            taxon_id=node["taxon_id"],
            label=node["scientific_name"],
            rank=node.get("taxon_rank"),
            status=node.get("taxonomic_status"),
            authorship=node.get("authorship"),
            children_count=node.get("children_count", 0),
            descendant_count=node.get("descendant_count", 0),
        )
        for node in nodes
    ]


def browse_children(parent_taxon_id: Optional[str], *, order_by: str = "rank") -> Sequence[TaxonSummary]:
    nodes = dao.get_children(parent_taxon_id, order_by=order_by)
    return [
        TaxonSummary(
            taxon_id=node["taxon_id"],
            label=node["scientific_name"],
            rank=node.get("taxon_rank"),
            status=node.get("taxonomic_status"),
            authorship=node.get("authorship"),
            children_count=node.get("children_count", 0),
            descendant_count=node.get("descendant_count", 0),
        )
        for node in nodes
    ]


def search(query: str, *, limit: int = 50, order_by: str = "rank") -> dict:
    taxa_matches = [
        TaxonSummary(
            taxon_id=row["taxon_id"],
            label=row["scientific_name"],
            rank=row.get("taxon_rank"),
            status=row.get("taxonomic_status"),
            authorship=row.get("authorship"),
        )
        for row in dao.search_taxa(query, limit=limit, order_by=order_by)
    ]

    vernacular_matches = [
        TaxonSummary(
            taxon_id=row["taxon_id"],
            label=row["scientific_name"],
            rank=row.get("taxon_rank"),
            status=row.get("taxonomic_status"),
            vernacular=row.get("vernacular_name"),
        )
        for row in dao.search_by_vernacular(query, limit=limit)
    ]

    fuzzy_matches = [
        TaxonSummary(
            taxon_id=row["taxon_id"],
            label=row["scientific_name"],
            rank=row.get("taxon_rank"),
            status=None,
            authorship=row.get("authorship"),
        )
        for row in dao.fuzzy_candidates(query, limit=limit // 2)
    ]

    return SimpleNamespace(
        query=query,
        taxa_matches=taxa_matches,
        vernacular_matches=vernacular_matches,
        fuzzy_matches=fuzzy_matches,
    )
