"use client";

import { ReactNode, useCallback, useEffect, useState } from "react";
import { get, post } from "@/lib/api";
import { Notice, Spinner } from "@/components/ui";
import { timeAgo } from "@/lib/format";
import { useRoles } from "@/components/RolesProvider";
import { canAccess } from "@/lib/roles";

type Rulebook = { markdown: string; generatedAt: string; language: string; model: string };

/** Inline formatting: **bold** (everything else is plain text — safe, no HTML injection). */
function inline(s: string): ReactNode {
  return s.split(/(\*\*[^*]+\*\*)/g).map((part, i) =>
    /^\*\*[^*]+\*\*$/.test(part) ? (
      <strong key={i} className="font-semibold text-slate-900">{part.slice(2, -2)}</strong>
    ) : (
      <span key={i}>{part}</span>
    ),
  );
}

/** Minimal, safe Markdown renderer (#/##/### headings, - bullets, **bold**, paragraphs). */
function Markdown({ text }: { text: string }) {
  const blocks: ReactNode[] = [];
  let list: string[] = [];
  let para: string[] = [];
  const flushList = () => {
    if (list.length) {
      const items = list;
      blocks.push(<ul key={`u${blocks.length}`} className="my-2 ml-5 list-disc space-y-1">{items.map((li, i) => <li key={i}>{inline(li)}</li>)}</ul>);
      list = [];
    }
  };
  const flushPara = () => {
    if (para.length) {
      const text = para.join(" ");
      blocks.push(<p key={`p${blocks.length}`} className="my-2 leading-relaxed">{inline(text)}</p>);
      para = [];
    }
  };
  for (const raw of text.split(/\r?\n/)) {
    const line = raw.trimEnd();
    if (/^###\s+/.test(line)) { flushList(); flushPara(); blocks.push(<h4 key={`h${blocks.length}`} className="mt-4 font-semibold text-slate-800">{inline(line.replace(/^###\s+/, ""))}</h4>); }
    else if (/^##\s+/.test(line)) { flushList(); flushPara(); blocks.push(<h3 key={`h${blocks.length}`} className="mt-6 border-b border-slate-200 pb-1 text-lg font-semibold text-slate-900">{inline(line.replace(/^##\s+/, ""))}</h3>); }
    else if (/^#\s+/.test(line)) { flushList(); flushPara(); blocks.push(<h2 key={`h${blocks.length}`} className="mt-4 text-xl font-semibold text-slate-900">{inline(line.replace(/^#\s+/, ""))}</h2>); }
    else if (/^[-*]\s+/.test(line)) { flushPara(); list.push(line.replace(/^[-*]\s+/, "")); }
    else if (line.trim() === "") { flushList(); flushPara(); }
    else { para.push(line); }
  }
  flushList();
  flushPara();
  return <div className="text-sm text-slate-700">{blocks}</div>;
}

export default function RulebookPanel() {
  const roles = useRoles();
  const canRegenerate = canAccess("/enrichment", roles); // rule-editors only (not read-only roles)
  const [data, setData] = useState<Rulebook | null | undefined>(undefined); // undefined = loading
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      const r = await get<{ rulebook: Rulebook | null }>("rulebook");
      setData(r.rulebook ?? null);
    } catch (e) {
      setError((e as Error).message);
      setData(null);
    }
  }, []);
  useEffect(() => {
    load();
  }, [load]);

  async function regenerate() {
    setBusy(true);
    setError(null);
    try {
      const r = await post<{ ok: boolean; rulebook?: Rulebook; error?: string }>("rulebook/regenerate");
      if (r.ok && r.rulebook) setData(r.rulebook);
      else setError(r.error || "Could not generate the rulebook.");
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setBusy(false);
    }
  }

  if (data === undefined) return <Spinner label="Loading rulebook…" />;

  return (
    <>
      {canRegenerate && (
        <div className="mb-4 flex items-center justify-end">
          <button type="button" className="btn-secondary shrink-0" onClick={regenerate} disabled={busy}>
            {busy ? "Generating…" : "Regenerate now"}
          </button>
        </div>
      )}

      {error && <div className="mb-4"><Notice kind="error">{error}</Notice></div>}

      {data === null ? (
        <Notice kind="info">
          No rulebook yet — it is generated automatically the next time a rule changes{canRegenerate ? <>, or click <strong>Regenerate now</strong></> : ""}.
        </Notice>
      ) : (
        <article className="card">
          <p className="mb-3 border-b border-slate-100 pb-2 text-xs text-slate-500">
            Generated {timeAgo(data.generatedAt)} · {data.language} · model: {data.model}
          </p>
          <Markdown text={data.markdown} />
        </article>
      )}
    </>
  );
}
