"""Report writer: JSON + self-contained HTML dashboard, with run-over-run diffs."""
from __future__ import annotations
import json
import re
import datetime
from pathlib import Path

from . import remediate


def overall_score(report: dict, weights: dict) -> float:
    parts = {
        "technical": report.get("technical", {}).get("avg_score", 0),
        "ai_readiness": report.get("geo", {}).get("avg_score", 0),
        "content": report.get("content", {}).get("avg_score", 0),
        "lead_gen": report.get("lead_gen", {}).get("avg_score", 0),
    }
    return round(sum(parts[k] * weights.get(k, 0) for k in parts), 1)


def save_reports(report: dict, out_dir: str, formats: list[str], keep: int = 30) -> list[str]:
    out = Path(out_dir)
    out.mkdir(parents=True, exist_ok=True)
    stamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    site_slug = report["site"]["name"].lower().replace(" ", "-")
    written = []

    if "json" in formats:
        p = out / f"{site_slug}_{stamp}.json"
        p.write_text(json.dumps(report, indent=2, default=str), encoding="utf-8")
        written.append(str(p))

    if "html" in formats:
        p = out / f"{site_slug}_{stamp}.html"
        p.write_text(render_html(report), encoding="utf-8")
        written.append(str(p))

    # prune history
    history = sorted(out.glob(f"{site_slug}_*.json"))
    for old in history[:-keep]:
        old.unlink(missing_ok=True)
    return written


def load_previous(out_dir: str, site_name: str) -> dict | None:
    out = Path(out_dir)
    slug = site_name.lower().replace(" ", "-")
    history = sorted(out.glob(f"{slug}_*.json"))
    if len(history) >= 2:
        return json.loads(history[-2].read_text(encoding="utf-8"))
    return None


def diff_reports(prev: dict, curr: dict) -> dict:
    d = {}
    for section in ("technical", "geo", "content", "lead_gen"):
        p = prev.get(section, {}).get("avg_score", 0)
        c = curr.get(section, {}).get("avg_score", 0)
        d[section] = {"previous": p, "current": c, "delta": round(c - p, 1)}
    d["overall"] = {"previous": prev.get("overall_score", 0),
                    "current": curr.get("overall_score", 0),
                    "delta": round(curr.get("overall_score", 0)
                                   - prev.get("overall_score", 0), 1)}
    return d


def render_html(r: dict) -> str:
    def bar(label, val, color):
        return (f"<div class='m'><span>{label}</span>"
                f"<div class='track'><div class='fill' style='width:{val}%;"
                f"background:{color}'></div></div><b>{val}</b></div>")

    def badge(tag: str) -> str:
        is_auto = tag.startswith("auto-fixable") or tag.startswith("partly auto-fixable")
        is_broken = tag.startswith("your call")
        color = "#9c7830" if is_auto else "#b23b32" if is_broken else "#6b6f78"
        bg = "#f6ecd8" if is_auto else "#fbe9e7" if is_broken else "#eee"
        return (f"<span style='font-size:.72rem;padding:.15rem .55rem;border-radius:10px;"
               f"background:{bg};color:{color};border:1px solid {color};"
               f"margin-left:.4rem;white-space:nowrap'>{tag}</span>")

    def split_tag(text: str) -> tuple[str, str | None]:
        m = re.match(r"^(.*?)\s*\[(.*?)\]\s*$", text)
        return (m.group(1), m.group(2)) if m else (text, None)

    recs = []
    for sec in ("geo", "lead_gen"):
        for page in r.get(sec, {}).get("pages", []):
            recs.extend(page.get("recommendations", []))
    recs = list(dict.fromkeys(recs))[:12]
    recs_html = "".join(
        f"<li>{txt}{badge(tag) if tag else ''}</li>"
        for txt, tag in (split_tag(x) for x in recs)
    ) or "<li>All good!</li>"

    issues = []
    for page in r.get("technical", {}).get("pages", []):
        for i in page.get("issues", []):
            issues.append((page["url"], i, remediate.classify_issue(i)))
    issues_html = "".join(
        f"<li>{url} \u2014 {issue}{badge(tag)}</li>"
        for url, issue, tag in issues[:20]
    ) or "<li>None \U0001F389</li>"

    diff_html = ""
    if r.get("diff"):
        rows = "".join(
            f"<tr><td>{k}</td><td>{v['previous']}</td><td>{v['current']}</td>"
            f"<td style='color:{'#2e7d32' if v['delta']>=0 else '#c62828'}'>"
            f"{'+' if v['delta']>=0 else ''}{v['delta']}</td></tr>"
            for k, v in r["diff"].items())
        diff_html = (f"<h2>Change since last audit</h2><table><tr><th>Area</th>"
                     f"<th>Prev</th><th>Now</th><th>Δ</th></tr>{rows}</table>")

    return f"""<!doctype html><html><head><meta charset="utf-8">
<title>{r['site']['name']} — SEO+AI Report</title>
<style>
body{{font-family:system-ui,sans-serif;max-width:880px;margin:2rem auto;padding:0 1rem;color:#222}}
h1{{font-size:1.5rem}} .score{{font-size:3rem;font-weight:700}}
.m{{display:flex;align-items:center;gap:.75rem;margin:.5rem 0}}
.m span{{width:140px}} .track{{flex:1;background:#eee;border-radius:6px;height:14px}}
.fill{{height:14px;border-radius:6px}}
table{{border-collapse:collapse;width:100%}} td,th{{border:1px solid #ddd;padding:6px 10px;text-align:left}}
li{{margin:.5rem 0}} .issues li{{color:#333}}
.legend{{font-size:.82rem;color:#666;margin:.6rem 0 1.2rem}}
footer{{margin-top:2rem;color:#888;font-size:.85rem}}
</style></head><body>
<h1>{r['site']['name']} — SEO + AI Search Report</h1>
<p>Generated {r['generated_at']} · {r['site']['url']}</p>
<div class="score">{r['overall_score']}/100</div>
{bar('Technical SEO', r['technical']['avg_score'], '#1565c0')}
{bar('AI Readiness (GEO)', r['geo']['avg_score'], '#6a1b9a')}
{bar('Content', r['content']['avg_score'], '#00838f')}
{bar('Lead Generation', r['lead_gen']['avg_score'], '#ef6c00')}
{diff_html}
<h2>Top recommendations</h2>
<p class="legend">Gold badge = the tool can apply this automatically once you approve it.
Gray badge = needs a real content/design decision only you can make. Red badge = a broken
link needing your call on whether to restore or remove it.</p>
<ol>{recs_html}</ol>
<h2>Technical issues found</h2>
<ul class="issues">{issues_html}</ul>
<footer>SEO-AI-Optimizer — white-hat automated audit. Scores are heuristics, not guarantees.</footer>
</body></html>"""
