"""Reusable ipywidgets for CxO notebook interactivity (runbooks PyPI).

Loads AWS profiles from ~/.aws/config, builds interactive forms
for runbooks CLI commands. No code changes needed by CxO.

Install: pip install runbooks[jupyter]

Usage in notebooks:
    from runbooks.notebooks.widgets import build_config_form
"""

import configparser
from pathlib import Path

import ipywidgets as widgets
from IPython.display import display

# ━━━ Landing Zone profiles (pinned at top of every dropdown) ━━━━━━━━━━━━━
LZ_PROFILES = {
    "ams-admin-Billing-ReadOnly-Access": "FinOps / Billing (READ-ONLY)",
    "ams-admin-ReadOnlyAccess": "Management Account (Organizations)",
    "ams-centralised-ops-ReadOnlyAccess": "Centralized Operations (Config Aggregator)",
}

# ━━━ Known dropdown options (sourced from runbooks CLI --help output) ━━━━━━━
KNOWN_DROPDOWNS: dict[str, list[tuple[str, str]]] = {
    "MODE": [
        ("Executive (board summary)", "executive"),
        ("Architect (technical detail)", "architect"),
        ("CTO (technical overview)", "cto"),
        ("SRE (operational detail)", "sre"),
        ("CloudOps (full technical)", "cloudops"),
    ],
    "EXPORT": [
        ("CSV", "csv"),
        ("JSON", "json"),
        ("HTML", "html"),
        ("Excel", "xlsx"),
        ("Markdown", "markdown"),
        ("PDF", "pdf"),
    ],
    "COST_METRIC": [
        ("Unblended Cost", "UnblendedCost"),
        ("Amortized Cost", "AmortizedCost"),
        ("Net Amortized Cost", "NetAmortizedCost"),
        ("Blended Cost", "BlendedCost"),
    ],
    "SORT_BY": [
        ("By Cost (highest first)", "cost"),
        ("By Name (alphabetical)", "name"),
        ("By Count (most resources)", "count"),
        ("By Change (largest delta)", "change"),
    ],
    "PERSONA": [
        ("CFO", "cfo"),
        ("CTO", "cto"),
        ("CloudOps", "cloudops"),
        ("FinOps", "finops"),
        ("All", "all"),
    ],
    "VALIDATION_LEVEL": [
        ("Basic", "basic"),
        ("MCP Cross-Validation", "mcp"),
        ("Strict", "strict"),
    ],
    "TIMEFRAME": [
        ("Daily", "daily"),
        ("Weekly", "weekly"),
        ("Monthly", "monthly"),
        ("Quarterly", "quarterly"),
    ],
    "SUMMARY_MODE": [
        ("Table", "table"),
        ("Tree", "tree"),
        ("Both", "both"),
        ("None", "none"),
    ],
    "RESOURCE_TYPE": [
        ("EC2 Instances", "ec2"),
        ("RDS Databases", "rds"),
        ("S3 Buckets", "s3"),
        ("Lambda Functions", "lambda"),
        ("WorkSpaces", "workspaces"),
        ("EBS Snapshots", "snapshots"),
        ("EBS Volumes", "ebs"),
    ],
    "OLDER_THAN_DAYS": [
        ("30 days", "30"),
        ("60 days", "60"),
        ("90 days", "90"),
        ("180 days", "180"),
        ("1 year", "365"),
    ],
    "FRAMEWORK": [
        ("SOC2", "soc2"),
        ("PCI-DSS", "pci-dss"),
        ("HIPAA", "hipaa"),
        ("ISO 27001", "iso27001"),
        ("Well-Architected", "well-architected"),
    ],
}


def load_aws_profiles() -> list[str]:
    """Read all profile names from ~/.aws/config, pinned LZ profiles first."""
    config = configparser.ConfigParser()
    aws_config = Path.home() / ".aws" / "config"
    if aws_config.exists():
        config.read(aws_config)

    all_profiles = sorted(
        section.replace("profile ", "") for section in config.sections() if section.startswith("profile ")
    )

    # Pin LZ profiles at top, then the rest
    pinned = [p for p in LZ_PROFILES if p in all_profiles]
    others = [p for p in all_profiles if p not in LZ_PROFILES]
    return pinned + others


def build_cert_triage_form(
    profile: str = "ams-centralised-ops-ReadOnlyAccess",
    days: int = 90,
    mode: str = "executive",
    all_accounts: bool = True,
    email: bool = True,
    outpath: str = "tmp/security",
) -> dict:
    """Build interactive certificate triage configuration form.

    Returns dict of widget references. Access values via result["profile"].value etc.
    """
    profiles = load_aws_profiles()
    # Ensure default profile is in the list
    if profile not in profiles:
        profiles.insert(0, profile)

    # Build descriptive options: "profile-name — Description" for pinned, plain for others
    profile_options = []
    for p in profiles:
        if p in LZ_PROFILES:
            profile_options.append((f"{p}  —  {LZ_PROFILES[p]}", p))
        else:
            profile_options.append((p, p))

    w = {
        "profile": widgets.Dropdown(
            options=profile_options,
            value=profile,
            description="AWS Profile:",
            style={"description_width": "120px"},
            layout=widgets.Layout(width="600px"),
        ),
        "days": widgets.IntSlider(
            value=days,
            min=7,
            max=365,
            step=7,
            description="Days ahead:",
            style={"description_width": "120px"},
        ),
        "mode": widgets.Dropdown(
            options=[
                ("Executive (board summary)", "executive"),
                ("CTO (technical overview)", "cto"),
                ("SRE (operational detail)", "sre"),
                ("CloudOps (full technical)", "cloudops"),
            ],
            value=mode,
            description="Report mode:",
            style={"description_width": "120px"},
        ),
        "all_accounts": widgets.Checkbox(
            value=all_accounts,
            description="Scan all Landing Zone accounts",
            style={"description_width": "initial"},
        ),
        "email": widgets.Checkbox(
            value=email,
            description="Generate stakeholder email",
            style={"description_width": "initial"},
        ),
        "outpath": widgets.Text(
            value=outpath,
            description="Output dir:",
            style={"description_width": "120px"},
            layout=widgets.Layout(width="500px"),
        ),
    }

    form = widgets.VBox(
        [
            widgets.HTML("<h3>Certificate Triage Configuration</h3>"),
            widgets.HTML("<p>Select your AWS profile and report settings, then run the cells below.</p>"),
            w["profile"],
            widgets.HBox([w["days"], w["mode"]]),
            widgets.HBox([w["all_accounts"], w["email"]]),
            w["outpath"],
            widgets.HTML("<hr/><p><em>Press <b>Shift+Enter</b> to run each cell below</em></p>"),
        ]
    )
    display(form)
    return w


def _profile_dropdown(default: str = "default") -> widgets.Dropdown:
    """AWS profile dropdown with 72 profiles, top 3 LZ pinned."""
    profiles = load_aws_profiles()
    if default not in profiles:
        profiles.insert(0, default)
    options = []
    for p in profiles:
        if p in LZ_PROFILES:
            options.append((f"{p}  —  {LZ_PROFILES[p]}", p))
        else:
            options.append((p, p))
    return widgets.Dropdown(
        options=options,
        value=default,
        description="AWS Profile:",
        style={"description_width": "120px"},
        layout=widgets.Layout(width="600px"),
    )


def build_config_form(params: dict, title: str = "Configuration") -> dict:
    """Build interactive form from a notebook's parameters dict.

    Args:
        params: Dict of {name: value} from the notebook's parameters cell.
                Supported types: str, int, float, bool.
                Keys matching KNOWN_DROPDOWNS get a Dropdown widget automatically.
        title: HTML heading for the form.

    Returns:
        Dict of {name: widget} — access values via result["name"].value

    Usage in any notebook:
        from runbooks.notebooks.widgets import build_config_form
        w = build_config_form({
            "PROFILE": PROFILE, "DAYS": DAYS, "MODE": MODE,
            "ALL_ACCOUNTS": ALL_ACCOUNTS, "OUTPATH": OUTPATH,
        })
        PROFILE = w["PROFILE"].value
    """
    w = {}
    form_items = [widgets.HTML(f"<h3>{title}</h3>")]

    # Profile fields get the special AWS dropdown
    profile_keys = [k for k in params if "PROFILE" in k.upper()]
    other_keys = [
        k for k in params if k not in profile_keys and k.upper() not in ("DRY_RUN", "VALIDATE_AUTH")
    ]  # Hide tech params

    # AWS profile dropdowns first
    for key in profile_keys:
        w[key] = _profile_dropdown(default=str(params[key]))
        w[key].description = key.replace("_", " ").title() + ":"
        form_items.append(w[key])

    # Then other params based on type
    for key in other_keys:
        val = params[key]
        label = key.replace("_", " ").title() + ":"
        style = {"description_width": "140px"}

        # Check KNOWN_DROPDOWNS first
        if key.upper() in KNOWN_DROPDOWNS:
            options = KNOWN_DROPDOWNS[key.upper()]
            valid_values = [v for _, v in options]
            w[key] = widgets.Dropdown(
                options=options,
                value=val if val in valid_values else valid_values[0],
                description=label,
                style=style,
            )
        elif isinstance(val, bool):
            w[key] = widgets.Checkbox(value=val, description=label, style={"description_width": "initial"})
        elif isinstance(val, int):
            w[key] = widgets.IntSlider(value=val, min=0, max=max(val * 3, 365), step=1, description=label, style=style)
        elif isinstance(val, float):
            w[key] = widgets.FloatText(value=val, description=label, style=style)
        elif "PATH" in key.upper() or "DIR" in key.upper():
            w[key] = widgets.Text(value=str(val), description=label, style=style, layout=widgets.Layout(width="500px"))
        else:
            w[key] = widgets.Text(value=str(val), description=label, style=style, layout=widgets.Layout(width="500px"))
        form_items.append(w[key])

    form_items.append(widgets.HTML("<hr/><p><em>Adjust values, then <b>Shift+Enter</b> through cells below</em></p>"))
    display(widgets.VBox(form_items))
    return w


def build_finops_form(
    profile: str = "ams-admin-Billing-ReadOnly-Access",
    mode: str = "executive",
    top_n: int = 10,
    export: str = "html",
    cost_metric: str = "UnblendedCost",
    outpath: str = "tmp/finops",
) -> dict:
    """FinOps analysis configuration form with cost-optimized defaults."""
    return build_config_form(
        {
            "AWS_PROFILE": profile,
            "MODE": mode,
            "TOP_N": top_n,
            "EXPORT": export,
            "COST_METRIC": cost_metric,
            "OUTPATH": outpath,
        },
        title="FinOps Analysis Configuration",
    )


def build_inventory_form(
    profile: str = "ams-centralised-ops-ReadOnlyAccess",
    resources: str = "ec2,rds,s3,lambda",
    all_accounts: bool = True,
    persona: str = "cloudops",
    outpath: str = "tmp/inventory",
) -> dict:
    """Inventory discovery configuration form."""
    return build_config_form(
        {
            "AWS_PROFILE": profile,
            "RESOURCES": resources,
            "ALL_ACCOUNTS": all_accounts,
            "PERSONA": persona,
            "OUTPATH": outpath,
        },
        title="Inventory Discovery Configuration",
    )


def build_security_form(
    profile: str = "ams-centralised-ops-ReadOnlyAccess",
    days: int = 90,
    mode: str = "executive",
    all_accounts: bool = True,
    outpath: str = "tmp/security",
) -> dict:
    """Security assessment configuration form."""
    return build_config_form(
        {
            "AWS_PROFILE": profile,
            "DAYS": days,
            "MODE": mode,
            "ALL_ACCOUNTS": all_accounts,
            "OUTPATH": outpath,
        },
        title="Security Assessment Configuration",
    )
