// Catalogue Maker product screens.

const statusTone = (status) => {
  const s = String(status || "").toLowerCase();
  if (s.includes("success") || s.includes("approved") || s.includes("active") || s.includes("passed")) return "good";
  if (s.includes("running") || s.includes("testing") || s.includes("queued") || s.includes("waiting")) return "accent";
  if (s.includes("fail") || s.includes("reject") || s.includes("blocked")) return "warn";
  return "neutral";
};

const apiList = (value, keys, fallback) => {
  if (Array.isArray(value)) return value;
  for (const key of keys) {
    if (Array.isArray(value?.[key])) return value[key];
  }
  return fallback;
};

const apiObject = (value, keys, fallback) => {
  if (!value || Array.isArray(value)) return fallback;
  for (const key of keys) {
    if (value[key] && typeof value[key] === "object") return value[key];
  }
  return value.placeholder ? fallback : value;
};

const useApiListData = (endpoint, keys, fallback, deps = []) => {
  const state = window.useApi ? useApi(endpoint, null, deps) : { data: null, loading: false, error: null };
  return { ...state, rows: apiList(state.data, keys, fallback) };
};

const useApiObjectData = (endpoint, params, keys, fallback, deps = []) => {
  const state = window.useApi ? useApi(endpoint, params, deps) : { data: null, loading: false, error: null };
  return { ...state, value: apiObject(state.data, keys, fallback) };
};

const normalizeStatus = (s) => {
  const value = String(s || "").toLowerCase();
  if (value === "succeeded") return "Succeeded";
  if (value === "failed") return "Failed";
  if (value === "running") return "Running";
  if (value === "queued") return "Queued";
  if (value === "awaiting_uploads") return "Awaiting uploads";
  if (value === "cancelled") return "Cancelled";
  return s || "Unknown";
};

const normalizeJobs = (rows, data) => rows.map((j) => ({
  id: j.id,
  script: j.script || j.scriptName || data.scripts.find(s => s.id === j.scriptId || s.scriptId === j.script_id)?.name || j.scriptId || j.script_id || "-",
  org: j.org || j.orgName || j.organization_id || data.currentProject,
  user: j.user || j.userId || j.requested_by_user_id || "-",
  status: normalizeStatus(j.status),
  files: j.files ?? j.fileCount ?? 0,
  artifacts: j.artifacts ?? j.artifactCount ?? 0,
  credits: j.credits ?? j.credits_charged ?? j.creditsCharged ?? j.credits_reserved ?? 0,
  created: j.created || j.createdAt || j.created_at || "-",
  duration: j.duration || "-",
  error: j.error || j.error_message || j.failureReason || "",
  raw: j,
}));

const normalizeScripts = (rows) => rows.map((s) => ({
  id: s.id || s.scriptId,
  scriptId: s.scriptId || s.id,
  name: s.name,
  version: s.version || s.latestVersionId || "-",
  status: s.status ? normalizeStatus(s.status) : "Active",
  creditCost: s.creditCost ?? 0,
  input: s.input || Object.keys(s.inputSchema || {}).join(", ") || "-",
  output: s.output || Object.keys(s.outputSchema || {}).join(", ") || "-",
  owner: s.owner || "-",
  lastRun: s.lastRun || "-",
  runtime: s.runtime || s.runtime_key || "-",
}));

const normalizePackages = (rows) => rows.map((p) => ({
  id: p.id,
  name: p.name || p.scriptName || p.filename || "-",
  version: p.version || p.scriptVersionId || p.script_version_id || "-",
  status: normalizeStatus(p.status),
  tests: p.tests || p.latestReportSummary?.status || "-",
  uploadedBy: p.uploadedBy || p.uploadedByUserId || p.uploaded_by_user_id || "-",
  uploadedAt: p.uploadedAt || p.createdAt || p.created_at || "-",
  detectedRuntime: p.detectedRuntime || p.detected_runtime,
}));

const DashboardScreen = ({ data }) => {
  const jobsState = useApiListData("listAllJobs", ["jobs", "items"], data.jobs, []);
  const scriptsState = useApiListData("listScripts", ["scripts", "items"], data.scripts, []);
  const packagesState = useApiListData("adminListPackages", ["packages", "items"], data.packages, []);
  const jobs = normalizeJobs(jobsState.rows, data);
  const scripts = normalizeScripts(scriptsState.rows);
  const packages = normalizePackages(packagesState.rows);
  const failed = jobs.filter(j => j.status === "Failed").length;
  const running = jobs.filter(j => ["Running", "Queued", "awaiting_uploads", "queued", "running"].includes(j.status)).length;
  return (
    <div className="cm-page">
      <header className="cm-head">
        <div>
          <h1>Catalogue Maker</h1>
          <p>Script operations, usage, packages, and customer support in one workspace.</p>
        </div>
        <div className="cm-actions">
          <Btn kind="secondary" icon={<IconList size={14}/>} onClick={() => window.__nav("jobs")}>View jobs</Btn>
          <Btn kind="primary" icon={<IconUpload size={14}/>} onClick={() => window.__nav("run-script")}>Run script</Btn>
        </div>
      </header>

      <div className="cm-stats">
        <StatCard label="Credits available" value={data.creditLedger.balance} delta={`${data.creditLedger.usedThisMonth} used this month`} deltaTone="accent"/>
        <StatCard label="Jobs today" value={jobs.length} delta={`${running} active`} deltaTone="neutral"/>
        <StatCard label="Success rate" value={data.usageAnalytics.successRate} delta={`${failed} failed`} deltaTone={failed ? "warn" : "good"}/>
        <StatCard label="Active scripts" value={scripts.filter(s => s.status === "Active").length} delta={`${packages.length} packages`} deltaTone="good"/>
      </div>

      <div className="cm-grid">
        <Card title="Recent jobs" subtitle="Latest script runs across customer and admin workflows." action={<Btn kind="ghost" size="sm" iconRight={<IconChevR size={12}/>} onClick={() => window.__nav("jobs")}>All jobs</Btn>} padded={false}>
          <JobsTable jobs={jobs.slice(0, 4)} compact/>
        </Card>
        <Card title="Platform health" subtitle="Live backend plus current operational signals.">
          <HealthPanel/>
        </Card>
      </div>

      <div className="cm-grid">
        <Card title="Package lifecycle" subtitle="Admin package readiness.">
          <SimpleRows rows={packages.map(p => ({ left: `${p.name} ${p.version || ""}`, mid: p.tests || p.detectedRuntime || "-", right: p.status }))}/>
        </Card>
        <Card title="Latest artifacts" subtitle="Outputs ready for download.">
          <SimpleRows rows={data.artifacts.map(a => ({ left: a.name, mid: a.type, right: a.size }))}/>
        </Card>
      </div>
      <CatalogueStyles/>
    </div>
  );
};

const HealthPanel = () => {
  return (
    <div className="cm-health">
      <div className="cm-health-row"><span>Worker API</span><Pill tone="good">Mapped</Pill></div>
      <div className="cm-health-row"><span>Queue</span><Pill tone="good">Configured</Pill></div>
      <div className="cm-health-row"><span>Storage</span><Pill tone="good">R2 artifacts</Pill></div>
      <div className="cm-health-row"><span>Executor</span><Pill tone="accent">Container jobs</Pill></div>
      <div className="cm-muted">Live health endpoint is configured in API_CONFIG. Browser calls require Cloudflare Access and CORS policy alignment.</div>
    </div>
  );
};

const RunScriptScreen = ({ data, setData }) => {
  const scriptsState = useApiListData("listScripts", ["scripts", "items"], data.scripts, []);
  const scripts = normalizeScripts(scriptsState.rows);
  const [scriptId, setScriptId] = React.useState(data.scripts[0]?.id || "");
  const [fileName, setFileName] = React.useState("");
  const [file, setFile] = React.useState(null);
  const [jobStatus, setJobStatus] = React.useState("Ready");
  const selected = scripts.find(s => s.id === scriptId || s.scriptId === scriptId) || scripts[0];
  const createDemoJob = async () => {
    setJobStatus("Creating job through API");
    let job = { id: `job_${Math.floor(Math.random() * 9000 + 1000)}`, script: selected.name, org: data.currentProject, user: data.user.name.split(" ")[0], status: "Queued", files: fileName ? 1 : 0, artifacts: 0, credits: 0, created: "Just now", duration: "-", error: "" };
    try {
      const created = await window.api.call("createJob", null, {
        orgId: window.API_CONFIG.defaults.headers["x-org-id"],
        scriptId: selected.scriptId || selected.id,
        input: { fileName, outputPreference: document.querySelector("#cm-output-pref")?.value || "excel-images" },
      });
      const backendJob = created?.job || created;
      if (backendJob?.id) {
        job = normalizeJobs([backendJob], data)[0];
      }
      if (file && backendJob?.id) {
        setJobStatus("Creating upload slot");
        const uploadResult = await window.api.call("createUploadSlots", { id: backendJob.id }, {
          files: [{ name: file.name, contentType: file.type || "application/octet-stream", sizeBytes: file.size }],
        });
        const slot = (uploadResult?.uploads || [])[0];
        if (slot?.fileId) {
          setJobStatus("Uploading input");
          await window.api.call("uploadJobInput", { id: backendJob.id, uploadId: slot.fileId }, file, {
            headers: { "Content-Type": file.type || "application/octet-stream" },
          });
        }
      }
      if (backendJob?.id) {
        setJobStatus("Starting job");
        await window.api.call("startJob", { id: backendJob.id }, {});
      }
      setJobStatus("Started");
    } catch (e) {
      setJobStatus(`API fallback: ${e.message || "local fixture"}`);
    }
    setData(d => ({ ...d, jobs: [job, ...d.jobs] }));
    window.__toast("Job created");
    window.__nav("job-detail", job.id);
  };
  return (
    <div className="cm-page">
      <ScreenHeader icon={<IconUpload size={20}/>} title="Run Script" subtitle="Select an approved script, upload input files, and start a tracked job."/>
      <div className="cm-form-grid">
        <Card title="Script and input" subtitle="Catalogue Maker will use real backend endpoints when available.">
          <FormField label="Script">
            <select className="cm-select" value={scriptId} onChange={e => setScriptId(e.target.value)}>
              {scripts.map(s => <option key={s.id} value={s.id}>{s.name} - {s.version}</option>)}
            </select>
          </FormField>
          <FormField label="Input file" hint="PDF, Excel, CSV, or image files depending on script contract.">
            <input className="cm-file" type="file" onChange={e => { const f = e.target.files?.[0] || null; setFile(f); setFileName(f?.name || ""); }}/>
          </FormField>
          <FormField label="Output preference">
            <select id="cm-output-pref" className="cm-select" defaultValue="excel-images">
              <option value="excel-images">Excel linked to extracted images</option>
              <option value="json">Structured JSON</option>
              <option value="images">Image ZIP only</option>
            </select>
          </FormField>
          <Btn kind="primary" icon={<IconCheck size={14}/>} disabled={!selected} onClick={createDemoJob}>Create and start job</Btn>
        </Card>
        <Card title="Script contract" subtitle={selected?.status || "Not selected"}>
          {selected && <div className="cm-contract">
            <div><span>Input</span><strong>{selected.input}</strong></div>
            <div><span>Output</span><strong>{selected.output}</strong></div>
            <div><span>Credit cost</span><strong>{selected.creditCost} per run</strong></div>
            <div><span>Last run</span><strong>{selected.lastRun}</strong></div>
          </div>}
          <Banner tone="info" icon={<IconInfo size={14}/>}>Status: {jobStatus}. Upload and start calls are wired for backend integration; local fallback keeps the workflow usable during API hardening.</Banner>
        </Card>
      </div>
      <CatalogueStyles/>
    </div>
  );
};

const JobsScreen = ({ data, admin = false }) => {
  const jobsState = useApiListData(admin ? "listAllJobs" : "listJobs", ["jobs", "items"], data.jobs, [admin]);
  const jobs = normalizeJobs(jobsState.rows, data);
  const [query, setQuery] = React.useState("");
  const [status, setStatus] = React.useState("All");
  const rows = jobs.filter(j =>
    (status === "All" || j.status === status) &&
    (`${j.id} ${j.script} ${j.org} ${j.user}`.toLowerCase().includes(query.toLowerCase()))
  );
  return (
    <div className="cm-page">
      <ScreenHeader icon={<IconList size={20}/>} title={admin ? "All Jobs" : "Jobs"} subtitle="Track queue state, execution result, artifacts, credits, and failure reason." right={<Btn kind="primary" onClick={() => window.__nav("run-script")}>Run script</Btn>}/>
      <div className="cm-toolbar">
        <Input prefix={<IconSearch size={14}/>} value={query} onChange={e => setQuery(e.target.value)} placeholder="Search jobs"/>
        <select className="cm-select cm-filter" value={status} onChange={e => setStatus(e.target.value)}>
          {["All", "Queued", "Running", "Succeeded", "Failed"].map(s => <option key={s}>{s}</option>)}
        </select>
      </div>
      {jobsState.error && <Banner tone="warn" icon={<IconInfo size={14}/>}>Live jobs API unavailable. Showing local fallback rows.</Banner>}
      <Card padded={false}><JobsTable jobs={rows}/></Card>
      <CatalogueStyles/>
    </div>
  );
};

const JobsTable = ({ jobs, compact = false }) => (
  <Table columns={[
    { key: "id", label: "Job", mono: true, render: r => <button className="cm-link" onClick={() => window.__nav("job-detail", r.id)}>{r.id}</button> },
    { key: "script", label: "Script" },
    !compact && { key: "org", label: "Client" },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    { key: "artifacts", label: "Artifacts", align: "right" },
    { key: "credits", label: "Credits", align: "right" },
    !compact && { key: "duration", label: "Duration" },
  ].filter(Boolean)} rows={jobs}/>
);

const JobDetailScreen = ({ data, jobId }) => {
  const fallbackJob = data.jobs.find(j => j.id === jobId) || data.jobs[0];
  const jobState = useApiObjectData("getJob", { id: jobId || fallbackJob.id }, ["job"], fallbackJob, [jobId]);
  const job = normalizeJobs([jobState.value], data)[0];
  const artifactState = useApiListData("listArtifacts", ["artifacts", "items"], data.artifacts.filter(a => a.jobId === job.id), [job.id]);
  const artifacts = artifactState.rows.map(a => ({
    id: a.id,
    jobId: a.jobId || a.job_id || job.id,
    name: a.name || a.filename,
    type: a.type || a.kind || a.contentType || a.content_type,
    size: a.size || (a.sizeBytes || a.byte_size ? `${Math.round((a.sizeBytes || a.byte_size) / 1024)} KB` : "-"),
    created: a.created || a.createdAt || a.created_at || "-",
  }));
  return (
    <div className="cm-page">
      <ScreenHeader icon={<IconFile size={20}/>} title={job.id} subtitle={`${job.script} for ${job.org}`} right={<Btn kind="secondary" onClick={() => window.__nav("jobs")}>Back to jobs</Btn>}/>
      <div className="cm-stats">
        <StatCard label="Status" value={job.status} delta={job.error || "No current error"} deltaTone={statusTone(job.status)}/>
        <StatCard label="Artifacts" value={job.artifacts} delta={`${artifacts.length} listed`} deltaTone="neutral"/>
        <StatCard label="Credits" value={job.credits} delta="Charged/reserved" deltaTone="accent"/>
        <StatCard label="Duration" value={job.duration} delta={job.created} deltaTone="neutral"/>
      </div>
      <div className="cm-grid">
        <Card title="Timeline" subtitle="Execution lifecycle">
          <SimpleRows rows={[
            { left: "Job created", mid: job.created, right: "Done" },
            { left: "Input uploaded", mid: `${job.files} file(s)`, right: job.files ? "Done" : "Waiting" },
            { left: "Execution", mid: job.duration, right: job.status },
            { left: "Artifacts", mid: `${job.artifacts} generated`, right: artifacts.length ? "Ready" : "Pending" },
          ]}/>
        </Card>
        <Card title="Artifacts" subtitle="Download links use the backend artifact API when available.">
          <SimpleRows rows={artifacts.map(a => ({ left: a.name, mid: a.type, right: a.size }))}/>
          {!artifacts.length && <EmptyState icon={<IconDownload size={28}/>} title="No artifacts yet" description="Artifacts appear here after the job finishes."/>}
        </Card>
      </div>
      <CatalogueStyles/>
    </div>
  );
};

const ScriptsScreen = ({ data }) => {
  const state = useApiListData("listScripts", ["scripts", "items"], data.scripts, []);
  return <ListingScreen title="Scripts" subtitle="Approved script contracts available to customers and app managers." icon={<IconCpu size={20}/>} rows={normalizeScripts(state.rows)} columns={[
    { key: "name", label: "Script" },
    { key: "version", label: "Version", mono: true },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    { key: "input", label: "Input" },
    { key: "output", label: "Output" },
    { key: "creditCost", label: "Credits", align: "right" },
  ]}/>;
};

const ArtifactsScreen = ({ data }) => (
  <ListingScreen title="Artifacts" subtitle="Generated outputs from completed and running jobs." icon={<IconDownload size={20}/>} rows={data.artifacts} columns={[
    { key: "name", label: "Artifact" },
    { key: "jobId", label: "Job", mono: true, render: r => <button className="cm-link" onClick={() => window.__nav("job-detail", r.jobId)}>{r.jobId}</button> },
    { key: "type", label: "Type" },
    { key: "size", label: "Size", align: "right" },
    { key: "created", label: "Created" },
  ]}/>
);

const AnalyticsScreen = ({ data, admin = false }) => {
  const analyticsState = useApiListData("packageAnalytics", ["analytics", "items"], data.analyticsByScript, []);
  const rows = analyticsState.rows.map((r, i) => ({
    id: r.id || `analytics_${i}`,
    script: r.script || r.scriptName || r.script_name || r.name || "-",
    runs: r.runs ?? r.jobCount ?? r.job_count ?? 0,
    success: r.success || r.successRate || r.success_rate || "-",
    credits: r.credits ?? r.creditsCharged ?? r.credits_charged ?? 0,
    avgDuration: r.avgDuration || r.avg_duration || "-",
  }));
  return <div className="cm-page">
    <ScreenHeader icon={<IconChart size={20}/>} title={admin ? "Usage Analytics" : "Analytics"} subtitle="Usage by script, credits, reliability, and storage."/>
    <div className="cm-stats">
      <StatCard label="Total runs" value={data.usageAnalytics.totalRuns} delta="All scripts" deltaTone="neutral"/>
      <StatCard label="Success rate" value={data.usageAnalytics.successRate} delta="Last 30 days" deltaTone="good"/>
      <StatCard label="Credits used" value={data.usageAnalytics.creditsUsed} delta="This month" deltaTone="accent"/>
      <StatCard label="Storage" value={`${data.usageAnalytics.storageGb} GB`} delta="R2 artifacts" deltaTone="neutral"/>
    </div>
    <Card title="Script usage" subtitle="Backend package analytics endpoint is mapped; fixture data is used when unavailable." padded={false}>
      <Table columns={[
        { key: "script", label: "Script" },
        { key: "runs", label: "Runs", align: "right" },
        { key: "success", label: "Success", align: "right" },
        { key: "credits", label: "Credits", align: "right" },
        { key: "avgDuration", label: "Avg duration", align: "right" },
      ]} rows={rows}/>
    </Card>
    <CatalogueStyles/>
  </div>;
};

const CreditsScreen = ({ data }) => (
  <CreditsScreenInner data={data}/>
);

const CreditsScreenInner = ({ data }) => {
  const subState = useApiObjectData("orgSubscription", { id: data.org.id }, ["subscription"], data.subscription, [data.org.id]);
  const creditState = useApiObjectData("orgCredits", { id: data.org.id }, ["credits"], data.creditLedger, [data.org.id]);
  const subscription = subState.value;
  const credits = creditState.value;
  const balance = credits.balance ?? credits.monthlyCreditsRemaining ?? data.creditLedger.balance;
  return <div className="cm-page">
    <ScreenHeader icon={<IconCard size={20}/>} title="Credits" subtitle="Subscription and run-credit position for the current workspace." right={<Btn kind="secondary" onClick={async () => {
      try { await window.api.call("changePlan", { id: data.org.id }, { plan: "Growth", reason: "UI plan change request" }); window.__toast("Plan change requested"); }
      catch (e) { window.__toast(e.message || "Plan API failed", "warn"); }
    }}>Request plan change</Btn>}/>
    <div className="cm-stats">
      <StatCard label="Plan" value={subscription.plan || data.subscription.plan} delta={subscription.status || data.subscription.status} deltaTone="good"/>
      <StatCard label="Included runs" value={subscription.includedRuns || data.subscription.includedRuns} delta={`${subscription.usedRuns || data.subscription.usedRuns} used`} deltaTone="accent"/>
      <StatCard label="Credit balance" value={balance} delta={`${credits.reserved || data.creditLedger.reserved} reserved`} deltaTone="neutral"/>
      <StatCard label="Renewal" value={subscription.renewal || subscription.renewsAt || data.subscription.renewal} delta="Subscription date" deltaTone="neutral"/>
    </div>
    <Banner tone="info" icon={<IconInfo size={14}/>}>Credits and subscription reads call real org endpoints. Plan changes and adjustments call current admin endpoints, which are placeholders until billing is hardened.</Banner>
    <CatalogueStyles/>
  </div>;
};

const PackageManagerScreen = ({ data }) => {
  const state = useApiListData("adminListPackages", ["packages", "items"], data.packages, []);
  return <ListingScreen title="Package Manager" subtitle="Upload, validate, build, test, approve, or reject script ZIP packages." icon={<IconUpload size={20}/>} right={<PackageUploadButton/>} rows={normalizePackages(state.rows)} columns={[
    { key: "name", label: "Package" },
    { key: "version", label: "Version", mono: true },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    { key: "tests", label: "Tests" },
    { key: "uploadedBy", label: "Uploaded by" },
    { key: "uploadedAt", label: "Uploaded" },
    { key: "action", label: "", align: "right", render: r => <PackageActions row={r}/> },
  ]}/>;
};

const PackageUploadButton = () => {
  const inputRef = React.useRef();
  const [busy, setBusy] = React.useState(false);
  const upload = async (file) => {
    if (!file) return;
    setBusy(true);
    try {
      await window.api.call("adminCreatePackage", null, file, {
        headers: { "Content-Type": file.type || "application/zip", "x-filename": file.name },
      });
      window.__toast("Package uploaded");
    } catch (e) {
      window.__toast(e.message || "Package upload failed", "warn");
    } finally {
      setBusy(false);
    }
  };
  return <>
    <input ref={inputRef} type="file" accept=".zip,application/zip" style={{display:"none"}} onChange={e => upload(e.target.files?.[0])}/>
    <Btn kind="primary" disabled={busy} onClick={() => inputRef.current?.click()}>{busy ? "Uploading..." : "Upload ZIP"}</Btn>
  </>;
};

const PackageActions = ({ row }) => {
  const run = async (endpoint, body) => {
    try {
      await window.api.call(endpoint, { id: row.id }, body || {});
      window.__toast(`${endpoint.replace("admin", "")} requested`);
    } catch (e) {
      window.__toast(e.message || "Package action failed", "warn");
    }
  };
  return <div style={{display:"inline-flex", gap:6}}>
    <Btn kind="secondary" size="sm" onClick={() => run("adminValidatePackage")}>Validate</Btn>
    <Btn kind="secondary" size="sm" onClick={() => run("adminTestPackage")}>Test</Btn>
    <Btn kind="secondary" size="sm" onClick={() => run("adminApprovePackage")}>Approve</Btn>
  </div>;
};

const ScriptVersionsScreen = ({ data }) => (
  <ListingScreen title="Script Versions" subtitle="Approved and candidate script versions." icon={<IconFile size={20}/>} rows={data.scriptVersions} columns={[
    { key: "script", label: "Script" },
    { key: "version", label: "Version", mono: true },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    { key: "packageId", label: "Package", mono: true },
    { key: "approvedBy", label: "Approved by" },
    { key: "date", label: "Date" },
  ]}/>
);

const ClientsScreen = ({ data }) => {
  const state = useApiListData("listClients", ["orgs", "organizations", "items"], data.clients, []);
  const rows = apiList(state.data, ["orgs", "organizations", "items"], data.clients).map((c, i) => ({
    id: c.id || `client_${i}`,
    name: c.name || c.slug || "-",
    plan: c.plan || c.planKey || c.plan_key || "-",
    status: normalizeStatus(c.status || "Active"),
    runs: c.runs ?? c.jobCount ?? 0,
    credits: c.credits ?? c.creditBalance ?? 0,
    lastSeen: c.lastSeen || c.updated_at || c.created_at || "-",
  }));
  return <ListingScreen title="Clients" subtitle="App manager view of customer workspaces, plans, credits, and usage." icon={<IconBuilding size={20}/>} rows={rows} columns={[
    { key: "name", label: "Client" },
    { key: "plan", label: "Plan" },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    { key: "runs", label: "Runs", align: "right" },
    { key: "credits", label: "Credits", align: "right" },
    { key: "lastSeen", label: "Last seen" },
  ]}/>;
};

const AdminScreen = ({ data }) => (
  <div className="cm-page">
    <ScreenHeader icon={<IconShield size={20}/>} title="Admin" subtitle="Superadmin and app manager controls for clients, packages, support, and analytics."/>
    <div className="cm-admin-grid">
      {[
        ["Clients", "View all customers and support context.", "clients", IconBuilding],
        ["All Jobs", "Monitor jobs across every workspace.", "all-jobs", IconList],
        ["Package Manager", "Review and approve uploaded scripts.", "package-manager", IconUpload],
        ["Usage Analytics", "Track script volume and reliability.", "usage-analytics", IconChart],
        ["Support", "Assist customers and failed runs.", "support", IconQuestion],
        ["AI App Manager", "Manage marketing, sales, and support tasks.", "ai-app-manager", IconCpu],
      ].map(([title, sub, route, IconC]) => (
        <button className="cm-admin-card" key={route} onClick={() => window.__nav(route)}>
          <IconC size={20}/><strong>{title}</strong><span>{sub}</span><IconChevR size={14}/>
        </button>
      ))}
    </div>
    <CatalogueStyles/>
  </div>
);

const SupportScreen = ({ data }) => (
  <SupportScreenInner data={data}/>
);

const SupportScreenInner = ({ data }) => {
  const state = useApiListData("supportQueue", ["tickets", "items"], data.supportQueue, []);
  const rows = state.rows.map((r) => ({
    id: r.id,
    client: r.client || r.clientName || r.orgName || "-",
    topic: r.topic,
    priority: r.priority ? String(r.priority).replace(/^./, c => c.toUpperCase()) : "Medium",
    status: r.status ? String(r.status).replace(/^./, c => c.toUpperCase()) : "Open",
    owner: r.owner || r.assignedTo || "AppManager",
  }));
  return <div className="cm-page">
    <ScreenHeader icon={<IconQuestion size={20}/>} title="Support" subtitle="App manager support queue connected to clients, jobs, and AI summaries."/>
    <Card title="Support actions" subtitle="These actions call the admin support API and then refresh through the ticket list endpoint.">
      <div className="cm-actions">
        <Btn kind="secondary" onClick={async () => {
          try { await window.api.call("supportAccessRequest", null, { orgId: window.API_CONFIG.defaults.headers["x-org-id"], reason: "Support review" }); window.__toast("Access request sent"); }
          catch (e) { window.__toast(e.message || "Support API failed", "warn"); }
        }}>Request access</Btn>
        <Btn kind="secondary" onClick={async () => {
          try { await window.api.call("supportImpersonationRequest", null, { orgId: window.API_CONFIG.defaults.headers["x-org-id"], reason: "Customer support" }); window.__toast("Impersonation request sent"); }
          catch (e) { window.__toast(e.message || "Support API failed", "warn"); }
        }}>Request impersonation</Btn>
      </div>
    </Card>
    <Card padded={false}>
      <Table rows={rows} columns={[
    { key: "client", label: "Client" },
    { key: "topic", label: "Topic" },
    { key: "priority", label: "Priority", render: r => <Pill tone={r.priority === "High" ? "warn" : "accent"}>{r.priority}</Pill> },
    { key: "status", label: "Status" },
    { key: "owner", label: "Owner" },
      ]}/>
    </Card>
    <CatalogueStyles/>
  </div>;
};

const AiAppManagerScreen = ({ data }) => {
  const state = useApiListData("aiManagerTasks", ["tasks", "insights", "items"], data.aiManagerTasks, []);
  const rows = apiList(state.data, ["tasks", "insights", "items"], data.aiManagerTasks);
  return <div className="cm-page">
    <ScreenHeader icon={<IconCpu size={20}/>} title="AI App Manager" subtitle="AI-assisted marketing, sales, and customer-support task queue." right={<div className="cm-actions">
      <Btn kind="secondary" onClick={async () => { try { await window.api.call("aiDraftAction", null, { area: "support" }); window.__toast("Draft requested"); } catch (e) { window.__toast(e.message || "AI API failed", "warn"); } }}>Draft action</Btn>
      <Btn kind="primary" onClick={async () => { try { await window.api.call("aiApproveAction", null, { actionId: "selected" }); window.__toast("Approval requested"); } catch (e) { window.__toast(e.message || "AI API failed", "warn"); } }}>Approve</Btn>
    </div>}/>
    <Card padded={false}><Table rows={rows} columns={[
    { key: "area", label: "Area" },
    { key: "task", label: "Task" },
    { key: "status", label: "Status", render: r => <Pill tone={statusTone(r.status)}>{r.status}</Pill> },
    ]}/></Card>
    <CatalogueStyles/>
  </div>;
};

const ListingScreen = ({ title, subtitle, icon, right, rows, columns }) => (
  <div className="cm-page">
    <ScreenHeader icon={icon} title={title} subtitle={subtitle} right={right}/>
    <Card padded={false}><Table columns={columns} rows={rows}/></Card>
    <CatalogueStyles/>
  </div>
);

const SimpleRows = ({ rows }) => (
  <div className="cm-rows">
    {rows.map((r, i) => (
      <div className="cm-row" key={i}>
        <strong>{r.left}</strong><span>{r.mid}</span><Pill tone={statusTone(r.right)}>{r.right}</Pill>
      </div>
    ))}
  </div>
);

const CatalogueStyles = () => (
  <style>{`
    .cm-page { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
    .cm-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 18px; flex-wrap: wrap; }
    .cm-head h1 { margin: 0; font-size: 26px; font-weight: 650; letter-spacing: 0; }
    .cm-head p { margin: 6px 0 0; color: var(--muted); font-size: 14px; }
    .cm-actions, .cm-toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
    .cm-toolbar .hx-input-wrap { min-width: 280px; }
    .cm-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap); }
    .cm-grid, .cm-form-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(320px, .85fr); gap: var(--gap); min-width: 0; }
    .cm-grid > *, .cm-form-grid > *, .cm-stats > *, .cm-admin-grid > * { min-width: 0; }
    .cm-admin-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); }
    .cm-admin-card { display: grid; grid-template-columns: auto 1fr auto; gap: 8px 12px; align-items: center; text-align: left; padding: 16px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md); color: var(--ink); cursor: pointer; box-shadow: var(--shadow-1); }
    .cm-admin-card:hover { background: var(--hover); }
    .cm-admin-card span { grid-column: 2 / 3; color: var(--muted); font-size: 13px; line-height: 1.4; }
    .cm-health, .cm-contract, .cm-rows { display: flex; flex-direction: column; gap: 10px; }
    .cm-health-row, .cm-row, .cm-contract div { display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line-2); }
    .cm-health-row:last-child, .cm-row:last-child, .cm-contract div:last-child { border-bottom: none; }
    .cm-row strong { font-size: 13.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .cm-row span, .cm-contract span, .cm-muted { color: var(--muted); font-size: 12.5px; }
    .cm-contract strong { font-size: 13.5px; text-align: right; }
    .cm-select, .cm-file { width: 100%; height: var(--row); border: 1px solid var(--line); border-radius: 8px; background: var(--panel); color: var(--ink); font: inherit; padding: 0 10px; }
    .cm-file { padding: 9px 10px; }
    .cm-filter { width: 160px; }
    .cm-link { border: none; background: transparent; color: var(--accent); font: inherit; font-family: var(--mono); cursor: pointer; padding: 0; }
    .cm-link:hover { text-decoration: underline; }
    .hx-dash-stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--pad); box-shadow: var(--shadow-1); }
    .hx-dash-stat-label { color: var(--muted); font-size: 13px; font-weight: 500; }
    .hx-dash-stat-value { font-size: 27px; font-weight: 650; letter-spacing: 0; margin-top: 8px; font-feature-settings: "tnum"; line-height: 1.1; overflow-wrap: anywhere; }
    .hx-dash-stat-foot { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
    .hx-dash-stat-sub { color: var(--muted); font-size: 12px; }
    @media (max-width: 1180px) {
      .cm-stats, .cm-admin-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .cm-grid, .cm-form-grid { grid-template-columns: 1fr; }
    }
    @media (max-width: 680px) {
      .cm-stats, .cm-admin-grid { grid-template-columns: 1fr; }
      .cm-toolbar .hx-input-wrap, .cm-filter { width: 100%; min-width: 0; }
      .cm-head h1 { font-size: 22px; }
    }
  `}</style>
);

Object.assign(window, {
  DashboardScreen, RunScriptScreen, JobsScreen, JobDetailScreen, ScriptsScreen,
  ArtifactsScreen, AnalyticsScreen, AdminScreen, CreditsScreen, PackageManagerScreen,
  ScriptVersionsScreen, ClientsScreen, SupportScreen, AiAppManagerScreen
});
