"""Slack Block Kit helpers for Autopilot approvals."""

from __future__ import annotations

import json
from typing import Any, Dict, List

from pathlib import Path

from g_gremlin.scout.models import ScoutScanResult

from .contracts import PlanStep, PlanV1


def _step_summary(step: PlanStep) -> str:
    return f"{step.tool} (risk {step.risk_level})"


def _render_diff_preview(step: PlanStep) -> str:
    if not step.diff_preview:
        return "Diff preview unavailable."
    try:
        return json.dumps(step.diff_preview, indent=2)
    except Exception:
        return "Diff preview unavailable."


def _truncate_text(text: str, limit: int = 2800) -> str:
    if len(text) <= limit:
        return text
    return text[: limit - 3] + "..."


def build_plan_approval_blocks(
    plan: PlanV1,
    approve_token: str,
    *,
    include_diff_preview: bool = True,
) -> Dict[str, Any]:
    blocks: List[Dict[str, Any]] = []
    blocks.append({
        "type": "header",
        "text": {"type": "plain_text", "text": "Autopilot Approval"},
    })
    blocks.append({
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": f"*Plan:* {plan.summary or plan.run_id}\n*Steps:* {len(plan.steps)}",
        },
    })

    if plan.risk:
        blocks.append({
            "type": "context",
            "elements": [
                {"type": "mrkdwn", "text": f"Max risk: {plan.risk.max_risk_level}"},
                {"type": "mrkdwn", "text": f"Blast radius: {plan.risk.blast_radius or 'unknown'}"},
            ],
        })

    if include_diff_preview and plan.steps:
        blocks.append({
            "type": "section",
            "text": {"type": "mrkdwn", "text": "*Diff Preview (best effort)*"},
        })
        for step in plan.steps[:3]:
            preview_text = _truncate_text(_render_diff_preview(step))
            blocks.append({
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": f"*{_step_summary(step)}*\n```{preview_text}```",
                },
            })

    value_payload = json.dumps({
        "run_id": plan.run_id,
        "plan_hash": plan.plan_hash or "",
        "policy_hash": plan.policy_hash or "",
        "approve_token": approve_token,
    })

    blocks.append({
        "type": "actions",
        "elements": [
            {
                "type": "button",
                "text": {"type": "plain_text", "text": "Approve & Run"},
                "style": "primary",
                "action_id": "autopilot_approve_run",
                "value": value_payload,
            },
            {
                "type": "button",
                "text": {"type": "plain_text", "text": "Reject"},
                "style": "danger",
                "action_id": "autopilot_reject",
                "value": value_payload,
            },
            {
                "type": "button",
                "text": {"type": "plain_text", "text": "Snooze 7d"},
                "action_id": "autopilot_snooze_7d",
                "value": value_payload,
            },
            {
                "type": "button",
                "text": {"type": "plain_text", "text": "Always Allow"},
                "action_id": "autopilot_always_allow",
                "value": value_payload,
            },
        ],
    })

    return {"blocks": blocks}

def build_notify_blocks(
    *,
    title: str,
    message: str,
    severity: str = "info",
    details: List[str] | None = None,
) -> Dict[str, Any]:
    header = title.strip() if title else "Autopilot Alert"
    sev = severity.strip().upper() if severity else "INFO"
    blocks: List[Dict[str, Any]] = [
        {
            "type": "header",
            "text": {"type": "plain_text", "text": f"{header} ({sev})"},
        },
        {
            "type": "section",
            "text": {"type": "mrkdwn", "text": message},
        },
    ]
    if details:
        blocks.append({
            "type": "context",
            "elements": [
                {"type": "mrkdwn", "text": " | ".join(details)},
            ],
        })
    return {"blocks": blocks}

def _load_close_packet_index(index_path: Path | None) -> dict:
    if not index_path:
        return {}
    try:
        with open(index_path, encoding="utf-8") as handle:
            return json.load(handle) or {}
    except Exception:
        return {}


def _dealdesk_rows(scan_result: ScoutScanResult) -> list[dict[str, Any]]:
    rows: list[dict[str, Any]] = []
    for finding in scan_result.findings:
        if not finding.scout_name.startswith("dealdesk"):
            continue
        for row in finding.evidence:
            fields = row.fields or {}
            fields["record_id"] = row.record_id
            rows.append(fields)
    return rows


def build_dealdesk_digest_blocks(
    scan_result: ScoutScanResult,
    *,
    plan: PlanV1 | None = None,
    approve_token: str | None = None,
    index_path: Path | None = None,
    safety_cap: int = 25,
) -> Dict[str, Any]:
    rows = _dealdesk_rows(scan_result)
    failures = [r for r in rows if (r.get("overall_status") or "") == "fail"]
    passes = [r for r in rows if (r.get("overall_status") or "") != "fail"]

    blocks: List[Dict[str, Any]] = []
    blocks.append({
        "type": "header",
        "text": {"type": "plain_text", "text": "Deal Desk Digest"},
    })
    blocks.append({
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": f"*Close Packets:* {len(rows)}\n*Failures:* {len(failures)}\n*Passed:* {len(passes)}",
        },
    })

    if failures:
        blocks.append({
            "type": "section",
            "text": {"type": "mrkdwn", "text": "*Top Failures*"},
        })
        for row in failures[:5]:
            name = row.get("Name") or row.get("opportunity_name") or row.get("record_id")
            band = row.get("band") or "unknown"
            missing = row.get("missing_fields") or []
            missing_text = ", ".join(missing) if missing else "See packet"
            blocks.append({
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": f"*{name}* — band: {band}\nMissing: {missing_text}",
                },
            })

    index = _load_close_packet_index(index_path)
    index_url = index.get("index_url") or ""

    has_auto_fixes = any(bool(row.get("proposed_diffs")) for row in failures)
    auto_fix_count = sum(1 for row in failures if row.get("proposed_diffs"))
    can_auto_apply = has_auto_fixes and auto_fix_count <= safety_cap

    action_payload = json.dumps({
        "run_id": plan.run_id if plan else scan_result.run_id,
        "plan_hash": plan.plan_hash if plan else "",
        "policy_hash": plan.policy_hash if plan else "",
        "approve_token": approve_token or "",
    })

    snooze_items = []
    for row in failures:
        record_id = row.get("record_id")
        reason_codes = row.get("reason_codes") or []
        if record_id:
            snooze_items.append({"record_id": record_id, "reason_codes": reason_codes})

    snooze_payload = json.dumps({
        "run_id": plan.run_id if plan else scan_result.run_id,
        "snooze_items": snooze_items,
    })

    view_payload = json.dumps({
        "run_id": plan.run_id if plan else scan_result.run_id,
        "index_url": index_url,
        "index_path": str(index_path) if index_path else "",
    })

    actions: List[Dict[str, Any]] = [
        {
            "type": "button",
            "text": {"type": "plain_text", "text": "View Close Packets"},
            "action_id": "dealdesk_view_packets",
            "value": view_payload,
        },
    ]

    if can_auto_apply:
        actions.append({
            "type": "button",
            "text": {"type": "plain_text", "text": "Approve & Apply"},
            "style": "primary",
            "action_id": "dealdesk_approve_apply",
            "value": action_payload,
        })
    else:
        task_button = {
            "type": "button",
            "text": {"type": "plain_text", "text": "Create Tasks"},
            "action_id": "dealdesk_create_tasks",
            "value": action_payload,
        }
        if not has_auto_fixes:
            task_button["style"] = "primary"
        actions.append(task_button)

    actions.append({
        "type": "button",
        "text": {"type": "plain_text", "text": "Snooze 7d"},
        "action_id": "dealdesk_snooze",
        "value": snooze_payload,
    })

    blocks.append({"type": "actions", "elements": actions})
    return {"blocks": blocks}


__all__ = ["build_plan_approval_blocks", "build_notify_blocks", "build_dealdesk_digest_blocks"]
