"""Per-tool manifest registry.

Single source of truth for what tools exist, their display strings, the
left-nav section they belong to, and the tier (which controls whether a
tool ships in a given build SKU). The home-page sidebar consumes this
list; future per-tool packaging will filter it via the ``tier`` field.

Adding a tool: append one ``Tool`` entry. Page filenames must match the
``page_slug`` so Streamlit's automatic page discovery picks them up.

Selling subsets: builds can filter ``TOOLS`` by tier or tool_id at
import time — no other code changes required, since pages key off
``tool_id`` for findings badges and the home grid renders whatever's in
the filtered list.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal


Tier = Literal["core", "pro", "enterprise"]
Status = Literal["Ready", "Coming Soon"]
# Sidebar grouping. Tools are bucketed by what the user is trying to
# accomplish rather than by implementation detail.
Section = Literal[
    "cleaners", "transformations", "automations",
    "finance", "coming_soon",
]


@dataclass(frozen=True)
class Tool:
    """One tool's manifest entry."""

    tool_id: str           # Stable identifier matching the analyzer's tool field.
    icon: str              # Single-glyph icon for the home grid card.
    name: str              # Display name (sidebar + card title).
    description: str       # One-sentence card body.
    page_slug: str         # Streamlit page filename without ".py" (e.g. "1_Deduplicator").
    status: Status         # "Ready" or "Coming Soon" — drives the card badge color.
    section: Section       # Sidebar group this tool belongs to.
    tier: Tier = "core"    # Build-time gating hook; every tool is "core" today.


# Order in this list IS the order shown in each sidebar section, so
# arranging it carefully matters. Within "cleaners" the order is the
# recommended PIPELINE order (Clean Text → Standardize → Fix Missing →
# Find Duplicates) so a user running tools by hand follows the sequence
# the orchestrator would. "Coming Soon" tools are grouped at the end in
# their own section so they never interleave with working tools, and the
# finance-oriented tools (Reconcile, PDF to CSV) live in their own group
# (see DECISIONS.md 2026-06-08).
TOOLS: list[Tool] = [
    Tool(
        tool_id="02_text_cleaner",
        icon=":material/text_format:",
        name="Clean Text",
        description=(
            "Trim extra spaces and strip out odd characters that copy-paste "
            "leaves behind."
        ),
        page_slug="2_Text_Cleaner",
        status="Ready",
        section="cleaners",
    ),
    Tool(
        tool_id="03_format_standardizer",
        icon=":material/format_list_bulleted:",
        name="Standardize Formats",
        description=(
            "Make dates, phone numbers, currency, names, and addresses look "
            "the same throughout."
        ),
        page_slug="3_Format_Standardizer",
        status="Ready",
        section="cleaners",
    ),
    Tool(
        tool_id="04_missing_handler",
        icon=":material/help_outline:",
        name="Fix Missing Values",
        description=(
            "Find blank cells (even ones written as 'N/A' or '?') and fill "
            "them in or remove them."
        ),
        page_slug="4_Missing_Values",
        status="Ready",
        section="cleaners",
    ),
    Tool(
        tool_id="01_deduplicator",
        icon=":material/search:",
        name="Find Duplicates",
        description=(
            "Find rows that repeat — exact and similar — and remove the extras."
        ),
        page_slug="1_Deduplicator",
        status="Ready",
        section="cleaners",
    ),
    Tool(
        tool_id="05_column_mapper",
        icon=":material/view_column:",
        name="Map Columns",
        description=(
            "Rename columns, change their order, and set each one as text, "
            "number, or date."
        ),
        page_slug="5_Column_Mapper",
        status="Ready",
        section="transformations",
    ),
    Tool(
        tool_id="09_pipeline_runner",
        icon=":material/auto_awesome:",
        name="Automated Workflows",
        description=(
            "Run several tools in a row — save the steps once, reuse them "
            "anytime."
        ),
        page_slug="9_Pipeline_Runner",
        status="Ready",
        section="automations",
    ),
    Tool(
        tool_id="11_reconciler",
        icon=":material/compare_arrows:",
        name="Reconcile Two Files",
        description=(
            "Compare two lists of transactions (e.g. bank vs. ledger) and "
            "flag what doesn't match."
        ),
        page_slug="11_Reconciler",
        status="Ready",
        section="finance",
    ),
    Tool(
        tool_id="10_pdf_extractor",
        icon=":material/picture_as_pdf:",
        name="PDF to CSV",
        description=(
            "Pull transactions out of bank-statement PDFs into a clean CSV file."
        ),
        page_slug="10_PDF_Extractor",
        status="Ready",
        section="finance",
    ),
    Tool(
        tool_id="06_outlier_detector",
        icon=":material/insights:",
        name="Find Unusual Values",
        description=(
            "Spot values that look wrong — way too high, way too low, or "
            "breaking your rules."
        ),
        page_slug="6_Outlier_Detector",
        status="Coming Soon",
        section="coming_soon",
    ),
    Tool(
        tool_id="08_validator_reporter",
        icon=":material/check_circle:",
        name="Quality Check",
        description=(
            "Check your file against rules you set, and export a PDF or "
            "Excel report."
        ),
        page_slug="8_Validator_Reporter",
        status="Coming Soon",
        section="coming_soon",
    ),
    Tool(
        tool_id="07_multi_file_merger",
        icon=":material/account_tree:",
        name="Combine Files",
        description=(
            "Combine several CSV or Excel files into one — even if their "
            "columns don't match."
        ),
        page_slug="7_Multi_File_Merger",
        status="Coming Soon",
        section="coming_soon",
    ),
]


# Display labels for each sidebar section. Kept here so i18n falls back
# to a sensible English string if a translation pack is missing the key.
SECTION_LABELS: dict[Section, str] = {
    "cleaners": "Data Cleaners",
    "transformations": "Transformations",
    "automations": "Automations",
    "finance": "Finance",
    "coming_soon": "Coming soon",
}


def tools_for_tier(*tiers: Tier) -> list[Tool]:
    """Subset filter for build-time slicing.

    Empty *tiers* returns every tool. Used by per-tool packaging to ship
    only the relevant subset of pages and home-grid cards.
    """
    if not tiers:
        return list(TOOLS)
    keep = set(tiers)
    return [t for t in TOOLS if t.tier in keep]


def tools_in_section(section: Section) -> list[Tool]:
    """Return the tools in *section*, preserving registry order."""
    return [t for t in TOOLS if t.section == section]


def tool_by_id(tool_id: str) -> Tool | None:
    return next((t for t in TOOLS if t.tool_id == tool_id), None)


def display_name(tool_id: str) -> str:
    """Return the human-readable name; fall back to the id when unknown."""
    t = tool_by_id(tool_id)
    return t.name if t else tool_id


def tool_name(tool_id: str) -> str:
    """Return the localized tool name, falling back to the registry default."""
    from src.i18n import t as _t
    fallback = display_name(tool_id)
    translated = _t(f"tools.{tool_id}.name")
    return translated if translated != f"tools.{tool_id}.name" else fallback


def tool_description(tool_id: str) -> str:
    """Return the localized tool description, falling back to the registry default."""
    from src.i18n import t as _t
    tool = tool_by_id(tool_id)
    fallback = tool.description if tool else ""
    translated = _t(f"tools.{tool_id}.description")
    return translated if translated != f"tools.{tool_id}.description" else fallback


def section_label(section: Section) -> str:
    """Return the localized sidebar section header."""
    from src.i18n import t as _t
    fallback = SECTION_LABELS[section]
    key = f"nav.section_{section}"
    translated = _t(key)
    return translated if translated != key else fallback
