from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path
from string import Template
from typing import Any, Mapping


@dataclass(frozen=True, slots=True)
class RenderedStatus:
    markdown: str
    renderer: str
    template_path: str | None = None


def _build_project_items_table(payload: Mapping[str, Any], *, max_rows: int = 30) -> str:
    items = payload.get("project_items")
    if not isinstance(items, list) or not items:
        return ""

    rows: list[str] = []
    rows.append("| Issue | Status | Assignee | O | M | P | Actual |")
    rows.append("| --- | --- | --- | ---: | ---: | ---: | ---: |")
    n = 0
    for it in items:
        if not isinstance(it, Mapping):
            continue
        if bool(it.get("included_in_forecast")) is False:
            continue

        issue_num = it.get("issue_number")
        status = it.get("status", "")
        assignees = it.get("assignees") or []
        assignee = assignees[0] if isinstance(assignees, list) and assignees else ""
        pert = it.get("pert") or {}
        o = (pert or {}).get("optimistic")
        m = (pert or {}).get("most_likely")
        p = (pert or {}).get("pessimistic")
        actual = (pert or {}).get("actual")
        rows.append(f"| #{issue_num} | {status} | {assignee} | {o} | {m} | {p} | {actual} |")
        n += 1
        if n >= max_rows:
            break

    return "\n".join(rows) + "\n"


def render_status_markdown(
    payload: Mapping[str, Any],
    *,
    template_path: str | None = None,
) -> RenderedStatus:
    """Render the status Markdown.

    If `template_path` is provided, it is treated as a `string.Template` file.
    Available template variables:
      - payload_json
      - project_items_table
      - any top-level scalar field in `payload`
    """
    if template_path:
        path = Path(template_path)
        text = path.read_text(encoding="utf-8")

        flat: dict[str, Any] = {}
        for k, v in payload.items():
            if isinstance(v, (str, int, float, bool)) or v is None:
                flat[str(k)] = v
        flat["payload_json"] = json.dumps(payload, indent=2, sort_keys=True)
        flat["project_items_table"] = _build_project_items_table(payload)

        md = Template(text).safe_substitute({k: "" if v is None else str(v) for k, v in flat.items()})
        if not md.endswith("\n"):
            md += "\n"
        return RenderedStatus(markdown=md, renderer="template", template_path=str(path))

    # Default: let the caller provide a markdown renderer (legacy behavior).
    raise ValueError("render_status_markdown requires template_path or use run_forecast default renderer.")

