"use client";

import { useState } from "react";
import { post } from "@/lib/api";
import { Badge, Notice } from "@/components/ui";

type ResetResult = {
  ok: boolean;
  total?: number;
  cleared?: { claims: number; messages: number; events: number; runs: number; attributeResults: number; imageResults: number };
  ergonodeReset?: { reset: number; errors: string[] } | null;
  detail?: string;
  error?: string;
};
type SyncResult = { ok: boolean; detail?: string; error?: string; imported?: number; added?: number; updated?: number; removed?: number };

export default function ActionsPanel() {
  const [resetErgonode, setResetErgonode] = useState(false);
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState<ResetResult | null>(null);
  const [costBusy, setCostBusy] = useState(false);
  const [costResult, setCostResult] = useState<{ ok: boolean; cleared?: number; detail?: string; error?: string } | null>(null);
  const [attrBusy, setAttrBusy] = useState(false);
  const [attrResult, setAttrResult] = useState<SyncResult | null>(null);
  const [catBusy, setCatBusy] = useState(false);
  const [catResult, setCatResult] = useState<SyncResult | null>(null);
  const [stuckBusy, setStuckBusy] = useState(false);
  const [stuckResult, setStuckResult] = useState<{ ok: boolean; released?: number; detail?: string; error?: string } | null>(null);

  async function releaseStuckClaims() {
    if (!window.confirm(
      "Release stuck (orphaned) claims?\n\n" +
      "Products left in claimed/processing because a Worker stopped mid-run are set back to Idle and re-queued for the next poll. " +
      "The Worker and Poller are stopped first. Completed history, cost and the audit log are kept.\n\n" +
      "Restart the Worker + Poller afterwards to re-process them."
    )) return;
    setStuckBusy(true);
    setStuckResult(null);
    try {
      setStuckResult(await post("admin/reset-stuck-claims"));
    } catch (e) {
      setStuckResult({ ok: false, error: (e as Error).message });
    } finally {
      setStuckBusy(false);
    }
  }

  async function syncAttributes() {
    if (!window.confirm("Sync the attribute catalogue with Ergonode?\n\nErgonode is the source of truth: new attributes are added, known ones keep their config (in-research + verbalized rule are preserved), and attributes no longer in Ergonode are removed. Safe to re-run.")) return;
    setAttrBusy(true);
    setAttrResult(null);
    try {
      setAttrResult(await post("ergonode/attributes/import"));
    } catch (e) {
      setAttrResult({ ok: false, error: (e as Error).message });
    } finally {
      setAttrBusy(false);
    }
  }

  async function syncCategories() {
    if (!window.confirm("Pull categories from Ergonode and OVERWRITE the local Category Tree?\n\nPer-Category Rules for categories that no longer exist are removed, and trusted-source category hints are kept valid. This cannot be undone.")) return;
    setCatBusy(true);
    setCatResult(null);
    try {
      setCatResult(await post("ergonode/categories/import"));
    } catch (e) {
      setCatResult({ ok: false, error: (e as Error).message });
    } finally {
      setCatBusy(false);
    }
  }

  async function resetCost() {
    if (!window.confirm("Reset cost tracking?\n\nThis clears the daily cost ledger so the average cost per product (and the daily/spend figures on the dashboard) restart from zero. Product data and the audit log are untouched.")) return;
    setCostBusy(true);
    setCostResult(null);
    try {
      setCostResult(await post("admin/reset-cost"));
    } catch (e) {
      setCostResult({ ok: false, error: (e as Error).message });
    } finally {
      setCostBusy(false);
    }
  }

  async function reset() {
    const msg =
      "Reset the products queue and the product log?\n\n" +
      "This permanently clears ALL product claims, queued messages, processing-log events and run history " +
      "(attribute & image results). The Worker and Poller are stopped first. Cost tracking and the audit log are kept." +
      (resetErgonode ? "\n\nIt will ALSO set every non-New Ergonode product back to New (writes to Ergonode)." : "") +
      "\n\nThis cannot be undone.";
    if (!window.confirm(msg)) return;
    setBusy(true);
    setResult(null);
    try {
      setResult(await post<ResetResult>("admin/reset-processing", { resetErgonodeStatuses: resetErgonode }));
    } catch (e) {
      setResult({ ok: false, error: (e as Error).message });
    } finally {
      setBusy(false);
    }
  }

  return (
    <section className="space-y-6" aria-labelledby="actions-h">
      <div>
        <h2 id="actions-h" className="text-xl font-semibold text-slate-900">Maintenance actions</h2>
        <p className="mt-1 text-sm text-slate-600">One-off operations. These are destructive — read each description before running.</p>
      </div>

      <section className="card" aria-labelledby="sync-h">
        <h3 id="sync-h" className="font-semibold text-slate-900">Ergonode data sync</h3>
        <p className="mt-1 text-sm text-slate-600">Pull reference data from Ergonode (the source of truth). Safe to re-run.</p>

        <div className="mt-4 space-y-4">
          <div>
            <h4 className="text-sm font-semibold text-slate-800">Attributes</h4>
            <p className="mt-1 text-sm text-slate-600">
              Import / sync the attribute catalogue. New attributes are added; known ones keep their config (in-research
              setting &amp; verbalized rule are preserved, label &amp; type refreshed); attributes no longer in Ergonode are removed.
              Edit them under <strong>Enrichment Rules → Manipulation Rules → Attribute manipulation</strong>.
            </p>
            <div className="mt-3 flex flex-wrap items-center gap-3">
              <button type="button" className="btn-secondary" onClick={syncAttributes} disabled={attrBusy}>
                {attrBusy ? "Syncing…" : "Import / sync attributes"}
              </button>
              {attrResult && (
                <span className="text-sm" role="status">
                  {attrResult.ok ? <Badge kind="ok">+{attrResult.added} new · {attrResult.updated} updated{attrResult.removed ? ` · ${attrResult.removed} removed` : ""}</Badge> : <Badge kind="danger">failed</Badge>}{" "}
                  <span className="text-slate-600">{attrResult.detail || attrResult.error}</span>
                </span>
              )}
            </div>
          </div>

          <div className="border-t border-slate-100 pt-4">
            <h4 className="text-sm font-semibold text-slate-800">Category tree</h4>
            <p className="mt-1 text-sm text-slate-600">
              Pull the category tree and <strong>overwrite</strong> the local one used by Per-Category Rules. Rules for
              removed categories are dropped; trusted-source category hints are kept valid.
            </p>
            <div className="mt-3 flex flex-wrap items-center gap-3">
              <button type="button" className="btn-secondary" onClick={syncCategories} disabled={catBusy}>
                {catBusy ? "Pulling…" : "Pull categories & overwrite"}
              </button>
              {catResult && (
                <span className="text-sm" role="status">
                  {catResult.ok ? <Badge kind="ok">imported {catResult.imported}</Badge> : <Badge kind="danger">failed</Badge>}{" "}
                  <span className="text-slate-600">{catResult.detail || catResult.error}</span>
                </span>
              )}
            </div>
          </div>
        </div>
      </section>

      <section className="card" aria-labelledby="stuck-h">
        <h3 id="stuck-h" className="font-semibold text-slate-900">Stuck / orphaned claims</h3>
        <p className="mt-1 text-sm text-slate-600">
          If a <strong>Worker</strong> stops mid-run, the products it had claimed get stuck showing as
          <strong> processing</strong> in Monitoring and won&rsquo;t advance. This releases them back to <strong>Idle</strong> and
          re-queues them for the next poll — <strong>without</strong> deleting any completed history, cost or audit data.
          The Worker and Poller are stopped first; restart them to re-process the released products.
        </p>
        <div className="mt-4 flex flex-wrap items-center gap-3">
          <button type="button" className="btn-secondary" onClick={releaseStuckClaims} disabled={stuckBusy}>
            {stuckBusy ? "Releasing…" : "Release stuck claims"}
          </button>
          {stuckResult && (
            <span className="text-sm" role="status">
              {stuckResult.ok ? <Badge kind="ok">released {stuckResult.released ?? 0}</Badge> : <Badge kind="danger">failed</Badge>}{" "}
              <span className="text-slate-600">{stuckResult.detail || stuckResult.error}</span>
            </span>
          )}
        </div>
      </section>

      <section className="card border-red-200 bg-red-50/40" aria-labelledby="reset-h">
        <h3 id="reset-h" className="font-semibold text-danger">Danger zone</h3>

        <div className="mt-4 border-t border-red-100 pt-4">
          <h4 className="text-sm font-semibold text-slate-800">Reset products queue &amp; product log</h4>
          <p className="mt-1 text-sm text-slate-600">
            Permanently clears all <strong>product claims</strong>, <strong>queued messages</strong>, processing-log
            <strong> events</strong> and <strong>run history</strong> (attribute &amp; image results) — a clean slate for
            re-processing. The <strong>Worker</strong> and <strong>Poller</strong> are stopped first so nothing is
            processed mid-reset. <strong>Cost tracking and the audit log are preserved.</strong>
          </p>

          <label className="mt-3 flex items-start gap-2 text-sm text-slate-700">
            <input type="checkbox" className="mt-0.5" checked={resetErgonode} onChange={(e) => setResetErgonode(e.target.checked)} />
            <span>
              Also set every non-New Ergonode product back to <strong>New</strong> so it can be re-picked
              <span className="text-slate-500"> (writes to Ergonode; otherwise products mid-workflow stay In&nbsp;Progress/Review there)</span>.
            </span>
          </label>

          <div className="mt-4 flex flex-wrap items-center gap-3">
            <button type="button" className="btn-danger" onClick={reset} disabled={busy}>
              {busy ? "Resetting…" : "Reset queue & log"}
            </button>
            {result && (
              <span className="text-sm" role="status">
                {result.ok ? <Badge kind="ok">done</Badge> : <Badge kind="danger">failed</Badge>}{" "}
                <span className="text-slate-600">{result.detail || result.error}</span>
              </span>
            )}
          </div>

          {result?.ergonodeReset && result.ergonodeReset.errors.length > 0 && (
            <Notice kind="error">
              {result.ergonodeReset.errors.length} Ergonode status write(s) failed:
              <ul className="mt-1 list-disc pl-5 text-xs">{result.ergonodeReset.errors.slice(0, 5).map((e, i) => <li key={i}>{e}</li>)}</ul>
            </Notice>
          )}
        </div>

        <div className="mt-4 border-t border-red-100 pt-4">
          <h4 className="text-sm font-semibold text-slate-800">Reset cost &amp; average</h4>
          <p className="mt-1 text-sm text-slate-600">
            Clears the daily <strong>cost ledger</strong> so the <strong>average cost per product</strong> (and the
            daily/spend figures on the dashboard) start fresh from zero. Product data and the audit log are untouched.
          </p>
          <div className="mt-4 flex flex-wrap items-center gap-3">
            <button type="button" className="btn-danger" onClick={resetCost} disabled={costBusy}>
              {costBusy ? "Resetting…" : "Reset cost tracking"}
            </button>
            {costResult && (
              <span className="text-sm" role="status">
                {costResult.ok ? <Badge kind="ok">done</Badge> : <Badge kind="danger">failed</Badge>}{" "}
                <span className="text-slate-600">{costResult.detail || costResult.error}</span>
              </span>
            )}
          </div>
        </div>
      </section>
    </section>
  );
}
