"""
D2 — Support report flow.

Transparent "here's exactly what we'd send to support" screen. Reproduces
the Claude Design handoff (D2-support-report.html):

  status bar : back chevron + "Support report" · battery · clock
  hero       : file-text glyph + intent line + "~ 1.4 MB estimated"
  bundle     : "What's inside" card — 7 line items w/ icon, label+subline,
               size (last item = optional screenshot, a toggle, off)
  privacy    : cyan strip naming exactly what gets stripped before zipping
  dest       : save-to path + "Open folder" affordance
  CTA row    : Cancel · "Make report · ~ 3 s" (focused by default)
  footer     : A make report · X browse before zip · B back

Navigation: left/right hop between Cancel and Make report. X toggles the
optional screenshot line. A runs the report (toast stub); B cancels.
"""

from __future__ import annotations

import pygame

from ..design import tokens as t
from ..shared import widgets as w
from ..shared import fonts, icons, render
from ..shared import backend

# focusable buttons
Z_CANCEL, Z_MAKE = 0, 1

# ── icon tint classes from HTML (.ic.cy/.rs/.pe/.ok / default) ────────
_TINT = {
    "cy": t.Color.ACCENT_CYAN, "rs": t.Color.ACCENT_ROSE,
    "pe": t.Color.ACCENT_PEACH, "ok": t.Color.SUCCESS,
    None: t.Color.TEXT_SECONDARY,
}


class SupportReportScreen:
    name = "support"

    def __init__(self, app):
        self.app = app
        self.focus = Z_MAKE          # primary CTA focused per design
        self.include_screenshot = False
        self.report_job = None
        self.report_poll_ms = 0.0
        self.report_phase = ""

        # bundle items: (icon, tint, label, subline, size, optional)
        self.items = [
            ("ph-device-mobile", "cy", "Device facts",
             "model, firmware, screen, memory, storage", "~ 4 KB", False),
            ("ph-bluetooth", "rs", "Bluetooth log",
             "last 30 min · connection history", "62 KB", False),
            ("ph-wifi-high", "cy", "Wi-Fi log",
             "scans, connection events · no passwords", "28 KB", False),
            ("ph-game-controller", "ok", "Input snapshot",
             "controller events, drift values, mapping", "8 KB", False),
            ("ph-warning", "pe", "Recent setup failures",
             "last 5 setup runs", "112 KB", False),
            ("ph-broadcast", None, "System messages",
             "recent system activity", "82 KB", False),
            ("ph-test-tube", None, "Screenshot of current screen",
             "helps support see what you see", None, True),
        ]
        self.dest = "/roms/aahead/reports/2026-05-20-1432.zip"

    # ── input ─────────────────────────────────────────────────────────
    def on_action(self, action):
        if action == "left":
            self.focus = Z_CANCEL
        elif action == "right":
            self.focus = Z_MAKE
        elif action == "x":
            self.include_screenshot = not self.include_screenshot
            self.app.toast("Screenshot added" if self.include_screenshot
                           else "Screenshot off")
        elif action == "a":
            if self.focus == Z_CANCEL:
                self.app.pop()
            else:
                self._make_report()
        elif action == "b":
            self.app.pop()

    def _make_report(self):
        if self.report_job:
            self.app.toast(self.report_phase or "Report is still building")
            return
        self.app.toast("Building report…")
        env = backend.diagnostics_bundle_async()
        job = (((env or {}).get("data") or {}).get("job") or {})
        job_id = job.get("job_id")
        if job_id:
            self.report_job = job_id
            progress = job.get("progress") or {}
            self.report_phase = progress.get("phase") or "Queued"
            self.report_poll_ms = 0.0
            backend.gui_log("support_report.job_started", job_id=job_id)
            return

        # Old backends do not understand --async yet. Keep the screen usable.
        env = backend.diagnostics_bundle()
        if not env:
            backend.gui_log("support_report.backend_unavailable")
            self.app.toast("Report backend unavailable")
            return
        if not env.get("ok"):
            backend.gui_log("support_report.failed", title=env.get("title"), state=env.get("state"))
            self.app.toast(env.get("title") or "Report failed")
            return
        path = ((env.get("data") or {}).get("path"))
        if path:
            self.dest = path
        backend.gui_log("support_report.created", path=self.dest)
        self.app.toast("Support report created")

    def update(self, dt_ms):
        if not self.report_job:
            return
        self.report_poll_ms += dt_ms
        if self.report_poll_ms < 450:
            return
        self.report_poll_ms = 0.0
        env = backend.job_status(self.report_job)
        if not env:
            return
        job = ((env.get("data") or {}).get("job") or {})
        progress = job.get("progress") or {}
        self.report_phase = progress.get("phase") or self.report_phase
        state = job.get("state")
        if state == "completed":
            result = job.get("result") or {}
            if result.get("path"):
                self.dest = result["path"]
            backend.gui_log("support_report.job_completed", job_id=self.report_job, path=self.dest)
            self.report_job = None
            self.report_phase = ""
            self.app.toast("Support report created")
        elif state == "failed":
            backend.gui_log("support_report.job_failed", job_id=self.report_job, title=job.get("title"))
            self.report_job = None
            self.report_phase = ""
            self.app.toast(job.get("title") or "Report failed")

    # ── draw ──────────────────────────────────────────────────────────
    def draw(self, surf):
        w.status_bar(surf, title="Support report", back=True)
        y = self._draw_hero(surf)
        y = self._draw_bundle(surf, y + 6)
        y = self._draw_privacy(surf, y + 5)
        y = self._draw_dest(surf, y + 5)
        self._draw_cta(surf)
        w.footer_hints(surf, [("A", "make report"),
                              ("X", "browse"), ("B", "back")])

    def _draw_hero(self, surf):
        y = 52
        gbox = 44
        box = render.rounded_gradient(
            (gbox, gbox), t.with_alpha(t.Color.ACCENT_ROSE, 0.22)[:3],
            t.with_alpha(t.Color.ACCENT_CYAN, 0.18)[:3], 11, 135)
        pygame.draw.rect(box, t.with_alpha(t.Color.ACCENT_ROSE, 0.40),
                         (0, 0, gbox, gbox), width=1, border_radius=11)
        ic = icons.icon("ph-file-text", 24, t.Color.ACCENT_ROSE)
        box.blit(ic, ((gbox - 24) // 2, (gbox - 24) // 2))
        surf.blit(box, (16, y))

        tx = 16 + gbox + 14
        title = fonts.render(t.Type.TITLE, "Make a report for support",
                             t.Color.TEXT_PRIMARY)
        surf.blit(title, (tx, y))
        sy = y + title.get_height() + 3
        lead = fonts.render(t.Type.BODY_SM,
                            "One zip with device facts and recent logs. ",
                            t.Color.TEXT_SECONDARY)
        surf.blit(lead, (tx, sy))
        strong = fonts.render(t.Type.LABEL_SM, "No saves, no passwords.",
                              t.Color.TEXT_PRIMARY)
        surf.blit(strong, (tx + lead.get_width(), sy))

        # right: big "~ 1.4 MB" + "estimated"
        rx = 640 - 16
        big = fonts.render(t.Type.TITLE, "~ 1.4 MB", t.Color.TEXT_PRIMARY)
        surf.blit(big, (rx - big.get_width(), y))
        est = fonts.render(t.Type.META_SM, "estimated", t.Color.TEXT_MUTED)
        surf.blit(est, (rx - est.get_width(), y + big.get_height() + 2))

        hb = y + gbox
        pygame.draw.line(surf, t.Color.BORDER_SOFT, (16, hb), (624, hb), 1)
        return hb

    def _draw_bundle(self, surf, y):
        pad_x = 14
        row_h = 28
        head_h = 18
        n = len(self.items)
        card_h = head_h + row_h * n + 8
        rect = pygame.Rect(16, y, 608, card_h)
        body = render.rounded_gradient((rect.w, rect.h), t.Color.SURFACE_BASE,
                                       t.Color.BG_MID, 10, 160)
        pygame.draw.rect(body, t.Color.BORDER_SOFT, (0, 0, rect.w, rect.h),
                         width=1, border_radius=10)

        # header: "WHAT'S INSIDE" ........ "7 items"
        h = fonts.render(t.Type.EYEBROW, "What's inside", t.Color.TEXT_MUTED, upper=True)
        body.blit(h, (pad_x, 8))
        cnt = fonts.render(t.Type.META_SM, f"{n} items", t.Color.TEXT_MUTED)
        body.blit(cnt, (rect.w - pad_x - cnt.get_width(), 9))

        ry = head_h + 4
        for idx, (icon_name, tint, label, sub, size, optional) in enumerate(self.items):
            cy = ry + row_h // 2
            dim = optional and not self.include_screenshot
            # icon chip (22px square, faint surface)
            ibox = 22
            chip = pygame.Surface((ibox, ibox), pygame.SRCALPHA)
            pygame.draw.rect(chip, (255, 255, 255, 8), (0, 0, ibox, ibox), border_radius=5)
            pygame.draw.rect(chip, t.Color.BORDER_SOFT, (0, 0, ibox, ibox),
                             width=1, border_radius=5)
            icol = _TINT.get(tint, t.Color.TEXT_SECONDARY)
            gi = icons.icon(icon_name, 12, icol)
            chip.blit(gi, ((ibox - 12) // 2, (ibox - 12) // 2))
            if dim:
                chip.set_alpha(140)
            body.blit(chip, (pad_x, cy - ibox // 2))

            # label + mono subline
            lx = pad_x + ibox + 12
            lab = fonts.render(t.Type.BODY_SM, label, t.Color.TEXT_PRIMARY)
            sb = fonts.render(t.Type.META_SM, sub, t.Color.TEXT_MUTED)
            stack_h = lab.get_height() + 1 + sb.get_height()
            ly = cy - stack_h // 2
            if dim:
                lab = lab.copy(); lab.set_alpha(140)
                sb = sb.copy(); sb.set_alpha(140)
            body.blit(lab, (lx, ly))
            body.blit(sb, (lx, ly + lab.get_height() + 1))

            # right: size label, or toggle for the optional row
            if optional:
                self._toggle(body, rect.w - pad_x - 32, cy - 9, self.include_screenshot)
            elif size:
                sz = fonts.render(t.Type.META_SM, size, t.Color.TEXT_SECONDARY)
                body.blit(sz, (rect.w - pad_x - sz.get_width(), cy - sz.get_height() // 2))

            # dashed separator (except last)
            if idx < n - 1:
                sepy = ry + row_h
                self._dashed(body, pad_x, rect.w - pad_x, sepy)
            ry += row_h

        surf.blit(body, rect.topleft)
        return rect.bottom

    def _toggle(self, surf, x, y, on):
        """Pill toggle (32×18) matching .tg / .tg.on."""
        tw, th = 32, 18
        if on:
            track = render.rounded_gradient(
                (tw, th), t.with_alpha(t.Color.ACCENT_ROSE, 0.60)[:3],
                t.with_alpha(t.Color.ACCENT_CYAN, 0.60)[:3], 999, 135)
            surf.blit(track, (x, y))
            pygame.draw.circle(surf, t.Color.TEXT_PRIMARY, (x + tw - 9, y + th // 2), 6)
        else:
            track = render.rounded_fill((tw, th), t.Color.BORDER_SOFT, 999)
            pygame.draw.rect(track, t.Color.BORDER_BRIGHT, (0, 0, tw, th),
                             width=1, border_radius=999)
            surf.blit(track, (x, y))
            pygame.draw.circle(surf, t.Color.TEXT_SECONDARY, (x + 9, y + th // 2), 6)

    def _dashed(self, surf, x0, x1, y, *, dash=4, gap=3):
        col = t.with_alpha(t.Color.BORDER_SOFT, 0.55)
        x = x0
        while x < x1:
            pygame.draw.line(surf, col, (x, y), (min(x + dash, x1), y), 1)
            x += dash + gap

    def _draw_privacy(self, surf, y):
        rect = pygame.Rect(16, y, 608, 28)
        body = pygame.Surface((rect.w, rect.h), pygame.SRCALPHA)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_CYAN, 0.06),
                         (0, 0, rect.w, rect.h), border_radius=8)
        pygame.draw.rect(body, t.with_alpha(t.Color.ACCENT_CYAN, 0.30),
                         (0, 0, rect.w, rect.h), width=1, border_radius=8)
        pad = 12
        ic = icons.icon("ph-info", 14, t.Color.ACCENT_CYAN)
        body.blit(ic, (pad, (rect.h - ic.get_height()) // 2))
        tx = pad + ic.get_width() + 10
        cy = rect.h // 2
        bold = fonts.render(t.Type.LABEL_SM, "Stripped before zipping: ",
                            t.Color.TEXT_PRIMARY)
        body.blit(bold, (tx, cy - bold.get_height() // 2))
        rest = fonts.render(t.Type.BODY_SM,
                            "Wi-Fi passwords, Bluetooth bonds, your name in usernames.",
                            t.Color.TEXT_SECONDARY)
        body.blit(rest, (tx + bold.get_width(), cy - rest.get_height() // 2))
        surf.blit(body, rect.topleft)
        return rect.bottom

    def _draw_dest(self, surf, y):
        rect = pygame.Rect(16, y, 608, 28)
        body = pygame.Surface((rect.w, rect.h), pygame.SRCALPHA)
        pygame.draw.rect(body, t.with_alpha(t.Color.BG_DEEP, 0.40),
                         (0, 0, rect.w, rect.h), border_radius=8)
        pygame.draw.rect(body, t.Color.BORDER_SOFT, (0, 0, rect.w, rect.h),
                         width=1, border_radius=8)
        pad = 12
        cy = rect.h // 2
        lbl = fonts.render(t.Type.META_SM, "SAVE TO", t.Color.TEXT_MUTED, upper=True)
        body.blit(lbl, (pad, cy - lbl.get_height() // 2))
        # "Open folder" pill measured from the right
        of_label = fonts.render(t.Type.META_SM, "Open folder", t.Color.TEXT_SECONDARY)
        of_ic = icons.icon("ph-file-text", 11, t.Color.TEXT_SECONDARY)
        of_w = 10 + of_ic.get_width() + 6 + of_label.get_width() + 10
        of_h = 26
        of = render.rounded_fill((of_w, of_h), t.Color.BG_MID, 999)
        pygame.draw.rect(of, t.Color.BORDER_SOFT, (0, 0, of_w, of_h),
                         width=1, border_radius=999)
        ox = 10
        of.blit(of_ic, (ox, (of_h - of_ic.get_height()) // 2))
        ox += of_ic.get_width() + 6
        of.blit(of_label, (ox, (of_h - of_label.get_height()) // 2))
        of_x = rect.w - pad - of_w
        body.blit(of, (of_x, (rect.h - of_h) // 2))
        # path (cyan mono), clipped to fit before the pill
        px = pad + lbl.get_width() + 12
        path = fonts.render(t.Type.MONO_TECH, self.dest, t.Color.ACCENT_CYAN)
        maxw = of_x - 10 - px
        if path.get_width() > maxw:
            path = path.subsurface((0, 0, max(maxw, 1), path.get_height()))
        body.blit(path, (px, cy - path.get_height() // 2))
        surf.blit(body, rect.topleft)
        return rect.bottom

    def _draw_cta(self, surf):
        h = 44
        y = 448 - 8 - h
        gap = 10
        # grid-template-columns: 1fr 1.4fr
        total = 608 - gap
        cancel_w = int(total / 2.4)
        make_w = total - cancel_w
        w.button(surf, pygame.Rect(16, y, cancel_w, h), "Cancel",
                 focused=(self.focus == Z_CANCEL))
        label = self.report_phase or "Make report · ~ 3 s"
        w.button(surf, pygame.Rect(16 + cancel_w + gap, y, make_w, h),
                 label, icon_name="ph-download-simple",
                 focused=(self.focus == Z_MAKE))
