<script lang="ts">
  import {
    ErrorBoundary,
    FormerResolveSpecAPI,
    GridlerFull,
    NativeSelectCtrl,
    SwitchCtrl,
    TextInputCtrl,
    type GridlerColumn,
    type GridlerContextMenuItem,
  } from "@warkypublic/svelix";
  import FormerShell from "../shared/FormerShell.svelte";
  import { adminGridTheme } from "../../gridTheme";
  import { GlobalStateStore } from "../../shellState";
  import type { Learning } from "../../types";
  import ContentEditorField from "../shared/ContentEditorField.svelte";

  type LearningForm = {
    id?: string;
    summary: string;
    details: string;
    category: string;
    area: string;
    status: string;
    priority: string;
    confidence: string;
    action_required: boolean;
    source_type?: string;
    source_ref?: string;
    tags?: string;
  };

  const LEARNING_PRIMARY_KEY = 'id';

  let selectedLearning = $state<Learning | null>(null);
  let gridTotal = $state<number | null>(null);
  let formOpened = $state(false);
  let formRequest = $state<'insert' | 'update' | 'delete'>('insert');
  let formValues = $state<LearningForm>({ summary: '', details: '', category: '', area: '', status: 'active', priority: 'medium', confidence: 'medium', action_required: false });
  let editorOpened = $state(false);
  let editorValues = $state<{ id?: string; details: string }>({ details: '' });
  let contextRow = $state<Record<string, unknown> | null>(null);
  let refreshKey = $state(0);
  const authToken = GlobalStateStore.getState().session.authToken ?? '';
  const learningOnAPICall = $derived(FormerResolveSpecAPI({
    authToken,
    url: '/api/rs/public/learnings'
  }));

  const menuItems: GridlerContextMenuItem[] = [
    { id: 'add', label: 'Add' },
    { id: 'edit', label: 'Edit' },
    { id: 'edit_content', label: 'Edit Content' },
    { id: 'delete', label: 'Delete' },
  ];

  function onRowContextMenu(_row: number, rowData: Record<string, unknown> | undefined) {
    contextRow = rowData ?? null;
  }

  function toLearningForm(learning: Learning): LearningForm {
    return {
      id: learning.id,
      summary: learning.summary,
      details: learning.details,
      category: learning.category,
      area: learning.area,
      status: learning.status,
      priority: learning.priority,
      confidence: learning.confidence,
      action_required: learning.action_required,
      source_type: learning.source_type,
      source_ref: learning.source_ref,
      tags: learning.tags
    };
  }

  function normalizeLearningRecordForFormer(data: Record<string, unknown>): LearningForm {
    return {
      id: data.id != null ? String(data.id) : undefined,
      summary: typeof data.summary === 'string' ? data.summary : '',
      details: typeof data.details === 'string' ? data.details : '',
      category: typeof data.category === 'string' ? data.category : '',
      area: typeof data.area === 'string' ? data.area : '',
      status: typeof data.status === 'string' ? data.status : 'active',
      priority: typeof data.priority === 'string' ? data.priority : 'medium',
      confidence: typeof data.confidence === 'string' ? data.confidence : 'medium',
      action_required: Boolean(data.action_required),
      source_type: typeof data.source_type === 'string' && data.source_type ? data.source_type : undefined,
      source_ref: typeof data.source_ref === 'string' && data.source_ref ? data.source_ref : undefined,
      tags: typeof data.tags === 'string' ? data.tags : undefined
    };
  }

  async function loadLearningFromRow(rowData: Record<string, unknown>): Promise<Learning> {
    const id = String(rowData[LEARNING_PRIMARY_KEY] ?? '');
    return await learningOnAPICall('read', 'update', undefined, id) as Learning;
  }

  async function onMenuItemSelect(item: GridlerContextMenuItem) {
    if (item.id === 'add') {
      formValues = { summary: '', details: '', category: '', area: '', status: 'active', priority: 'medium', confidence: 'medium', action_required: false };
      formRequest = 'insert';
      formOpened = true;
      return;
    }
    if (!contextRow) return;
    if (item.id === 'edit_content') {
      const learning = normalizeLearning(contextRow);
      selectedLearning = learning;
      editorValues = { id: learning.id, details: learning.details };
      editorOpened = true;
      return;
    }
    const learning = normalizeLearning(contextRow);
    formValues = toLearningForm(learning);
    formRequest = item.id === 'delete' ? 'delete' : 'update';
    formOpened = true;
  }

  function normalizeLearningForm(data: LearningForm): Record<string, unknown> {
    return {
      summary: data.summary.trim(),
      details: data.details,
      category: data.category.trim(),
      area: data.area.trim(),
      status: data.status,
      priority: data.priority,
      confidence: data.confidence,
      action_required: data.action_required,
      source_type: data.source_type?.trim() || undefined,
      source_ref: data.source_ref?.trim() || undefined,
      tags: data.tags?.trim() || undefined,
    };
  }

  async function handleLearningSaved() {
    formOpened = false;
    if (contextRow?.id) {
      selectedLearning = await loadLearningFromRow(contextRow);
    }
    refreshKey++;
  }

  async function handleLearningEditorSaved() {
    editorOpened = false;
    if (editorValues.id) {
      selectedLearning = await learningOnAPICall('read', 'update', undefined, editorValues.id) as Learning;
      editorValues = { id: selectedLearning.id, details: selectedLearning.details };
    }
    refreshKey++;
  }

  const learningsDataSourceOptions = {
    url: "/api/rs",
    authToken: GlobalStateStore.getState().session.authToken,
    schema: "public",
    entity: "learnings",
    uniqueID: LEARNING_PRIMARY_KEY,
    hotfields: [LEARNING_PRIMARY_KEY],
    sort: [{ column: "created_at", direction: "desc" }],
  } as unknown as {
    url: string;
    authToken?: string;
    schema: string;
    entity: string;
    uniqueID: string;
    hotfields: string[];
  };

  const columns: GridlerColumn[] = [
    { id: "summary", title: "Summary", dataKey: "summary", width: 420 },
    { id: "category", title: "Category", dataKey: "category", width: 140 },
    { id: "area", title: "Area", dataKey: "area", width: 140 },
    { id: "status", title: "Status", dataKey: "status", width: 130 },
    { id: "priority", title: "Priority", dataKey: "priority", width: 120 },
    {
      id: "action_required",
      title: "Action",
      dataKey: "action_required",
      width: 100,
    },
    {
      id: "created_at",
      title: "Created",
      dataKey: "created_at",
      width: 210,
      format: "datetime",
    },
  ];

  function normalizeLearning(rowData: Record<string, unknown>): Learning {
    return {
      id: String(rowData.id ?? ""),
      summary: typeof rowData.summary === "string" ? rowData.summary : "",
      details: typeof rowData.details === "string" ? rowData.details : "",
      category: typeof rowData.category === "string" ? rowData.category : "",
      area: typeof rowData.area === "string" ? rowData.area : "",
      status: typeof rowData.status === "string" ? rowData.status : "",
      priority: typeof rowData.priority === "string" ? rowData.priority : "",
      confidence:
        typeof rowData.confidence === "string" ? rowData.confidence : "",
      action_required: Boolean(rowData.action_required),
      source_type:
        typeof rowData.source_type === "string" ? rowData.source_type : undefined,
      source_ref:
        typeof rowData.source_ref === "string" ? rowData.source_ref : undefined,
      tags: typeof rowData.tags === "string" ? rowData.tags : undefined,
      project_id:
        typeof rowData.project_id === "string" ? rowData.project_id : undefined,
      related_thought_id:
        typeof rowData.related_thought_id === "string"
          ? rowData.related_thought_id
          : undefined,
      related_skill_id:
        typeof rowData.related_skill_id === "string"
          ? rowData.related_skill_id
          : undefined,
      reviewed_at:
        typeof rowData.reviewed_at === "string" ? rowData.reviewed_at : undefined,
      reviewed_by:
        typeof rowData.reviewed_by === "string" ? rowData.reviewed_by : undefined,
      created_at: String(rowData.created_at ?? ""),
      updated_at: String(rowData.updated_at ?? ""),
    };
  }

  function onRowClick(
    _row: number,
    rowData: Record<string, unknown> | undefined,
  ) {
    if (!rowData) {
      selectedLearning = null;
      return;
    }
    selectedLearning = normalizeLearning(rowData);
  }

  function onRowDblClick(_row: number, rowData: Record<string, unknown> | undefined) {
    if (!rowData) return;
    contextRow = rowData;
    void onMenuItemSelect({ id: 'edit', label: 'Edit' });
  }

  function onGridEvent(
    type: string,
    _item?: unknown,
    _column?: unknown,
    _coords?: unknown,
    detail?: Record<string, unknown>,
  ) {
    if (type !== "page_loaded" && type !== "load") return;
    const total = detail?.total;
    if (typeof total === "number") gridTotal = total;
  }

  function formatDate(value?: string): string {
    if (!value) return "—";
    return new Date(value).toLocaleString();
  }
</script>

<div class="space-y-4 w-full">
  <div class="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
    <div>
      <h2 class="text-2xl font-semibold text-white">Learnings</h2>
      <p class="mt-1 text-sm text-slate-400">
        {#if gridTotal === null}
          Server-backed grid
        {:else}
          {gridTotal} result{gridTotal !== 1 ? "s" : ""}
        {/if}
      </p>
    </div>
    <div class="flex items-center gap-3">
      <button
        class="rounded-xl border border-white/10 bg-white/5 px-4 py-2 text-sm text-slate-200 transition hover:bg-white/10"
        onclick={() => { formValues = { summary: '', details: '', category: '', area: '', status: 'active', priority: 'medium', confidence: 'medium', action_required: false }; formRequest = 'insert'; formOpened = true; }}>New Learning</button
      >
    </div>
  </div>

  <div class="flex flex-col gap-4">
    <div class="rounded-2xl border border-white/10 bg-slate-950/30 p-3">
      {#key refreshKey}
        <ErrorBoundary namespace="LearningsGridlerFull">
          <GridlerFull
            {columns}
            theme={adminGridTheme}
            rowMarkers="number"
            height={560}
            width="100%"
            pageSize={40}
            dataSource="resolvespec"
            dataSourceOptions={learningsDataSourceOptions}
            serverSideSearch={true}
            searchColumns={["summary", "details", "category", "area", "status"]}
            {menuItems}
            {onGridEvent}
            {onRowClick}
            {onRowDblClick}
            {onRowContextMenu}
            {onMenuItemSelect}
          />
        </ErrorBoundary>
      {/key}
    </div>

    <aside class="rounded-2xl border border-white/10 bg-slate-900/70 p-4">
      <div class="flex items-start justify-between gap-3">
        <h3 class="text-sm font-semibold text-white">Learning Inspector</h3>
        {#if selectedLearning}
          <button
            class="text-xs text-cyan-300 hover:text-cyan-200"
            onclick={() => {
              const learning = selectedLearning;
              if (!learning) return;
              editorValues = { id: learning.id, details: learning.details };
              editorOpened = true;
            }}>Edit Content</button>
        {/if}
      </div>

      {#if !selectedLearning}
        <p class="mt-3 text-sm text-slate-500">
          Select a learning row to inspect details and metadata.
        </p>
      {:else}
        <div class="mt-3 space-y-3 text-sm text-slate-300">
          <p class="text-slate-200">{selectedLearning.summary}</p>
          <div class="rounded-xl border border-white/10 bg-white/5 p-3 space-y-1">
            <p>
              <strong class="text-slate-100">Category:</strong>
              {selectedLearning.category || "—"}
            </p>
            <p>
              <strong class="text-slate-100">Area:</strong>
              {selectedLearning.area || "—"}
            </p>
            <p>
              <strong class="text-slate-100">Status:</strong>
              {selectedLearning.status || "—"}
            </p>
            <p>
              <strong class="text-slate-100">Priority:</strong>
              {selectedLearning.priority || "—"}
            </p>
            <p>
              <strong class="text-slate-100">Confidence:</strong>
              {selectedLearning.confidence || "—"}
            </p>
            <p>
              <strong class="text-slate-100">Action Required:</strong>
              {selectedLearning.action_required ? "yes" : "no"}
            </p>
            <p>
              <strong class="text-slate-100">Created:</strong>
              {formatDate(selectedLearning.created_at)}
            </p>
            <p>
              <strong class="text-slate-100">Updated:</strong>
              {formatDate(selectedLearning.updated_at)}
            </p>
            <p>
              <strong class="text-slate-100">Reviewed:</strong>
              {formatDate(selectedLearning.reviewed_at)}
            </p>
            <p>
              <strong class="text-slate-100">Reviewed By:</strong>
              {selectedLearning.reviewed_by || "—"}
            </p>
          </div>

          <div class="rounded-xl border border-white/10 bg-white/5 p-3">
            <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Details</p>
            <p class="mt-2 whitespace-pre-wrap text-slate-300">
              {selectedLearning.details || "No details provided."}
            </p>
          </div>

          <div class="rounded-xl border border-white/10 bg-white/5 p-3">
            <p class="text-xs uppercase tracking-[0.18em] text-slate-500">Source</p>
            <p class="mt-2 text-slate-300">
              {selectedLearning.source_type || "—"}
              {#if selectedLearning.source_ref}
                · {selectedLearning.source_ref}
              {/if}
            </p>
            <p class="mt-1 text-slate-400">Tags: {selectedLearning.tags || "—"}</p>
          </div>
        </div>
      {/if}
    </aside>
  </div>
</div>

<ErrorBoundary namespace="LearningsEditorFormer">
  <FormerShell
    bind:opened={editorOpened}
    bind:values={editorValues}
    request="update"
    title="Edit Learning Details"
    uniqueKeyField={LEARNING_PRIMARY_KEY}
    width="min(96vw, 90rem)"
    onAPICall={learningOnAPICall}
    beforeSave={(data) => ({ details: data.details })}
    afterSave={handleLearningEditorSaved}
    onClose={() => { editorOpened = false; }}
  >
    {#snippet children(state)}
      <ContentEditorField
        filename="learning.md"
        value={state.values?.details ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, details: v })}
      />
    {/snippet}
  </FormerShell>
</ErrorBoundary>

<ErrorBoundary namespace="LearningsFormer">
<FormerShell
  bind:opened={formOpened}
  bind:values={formValues}
  bind:request={formRequest}
  title={formRequest === 'insert' ? 'New Learning' : formRequest === 'update' ? 'Edit Learning' : 'Delete Learning'}
  uniqueKeyField={LEARNING_PRIMARY_KEY}
  onAPICall={learningOnAPICall}
  afterGet={async (data) => normalizeLearningRecordForFormer(data as Record<string, unknown>)}
  beforeSave={normalizeLearningForm}
  afterSave={handleLearningSaved}
  onClose={() => { formOpened = false; }}
>
  {#snippet children(state)}
    <div class="space-y-4 p-4">
      <TextInputCtrl
        label="Summary"
        name="summary"
        required
        disabled={state.request === 'delete'}
        value={state.values?.summary ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, summary: v })}
      />
      <ContentEditorField
        filename="learning.md"
        value={state.values?.details ?? ''}
        disabled={state.request === 'delete'}
        onchange={(v) => state.setState('values', { ...state.values, details: v })}
      />
      <TextInputCtrl
        label="Category"
        name="category"
        disabled={state.request === 'delete'}
        value={state.values?.category ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, category: v })}
      />
      <TextInputCtrl
        label="Area"
        name="area"
        disabled={state.request === 'delete'}
        value={state.values?.area ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, area: v })}
      />
      <NativeSelectCtrl
        label="Status"
        name="status"
        disabled={state.request === 'delete'}
        value={state.values?.status ?? 'active'}
        options={['active', 'completed', 'pending', 'archived']}
        onchange={(v) => state.setState('values', { ...state.values, status: v })}
      />
      <NativeSelectCtrl
        label="Priority"
        name="priority"
        disabled={state.request === 'delete'}
        value={state.values?.priority ?? 'medium'}
        options={['low', 'medium', 'high', 'critical']}
        onchange={(v) => state.setState('values', { ...state.values, priority: v })}
      />
      <NativeSelectCtrl
        label="Confidence"
        name="confidence"
        disabled={state.request === 'delete'}
        value={state.values?.confidence ?? 'medium'}
        options={['low', 'medium', 'high']}
        onchange={(v) => state.setState('values', { ...state.values, confidence: v })}
      />
      <SwitchCtrl
        label="Action Required"
        name="action_required"
        disabled={state.request === 'delete'}
        checked={state.values?.action_required ?? false}
        onchange={(v) => state.setState('values', { ...state.values, action_required: v })}
      />
      <TextInputCtrl
        label="Source Type"
        name="source_type"
        disabled={state.request === 'delete'}
        value={state.values?.source_type ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, source_type: v || undefined })}
      />
      <TextInputCtrl
        label="Source Ref"
        name="source_ref"
        disabled={state.request === 'delete'}
        value={state.values?.source_ref ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, source_ref: v || undefined })}
      />
      <TextInputCtrl
        label="Tags"
        name="tags"
        placeholder="comma-separated"
        disabled={state.request === 'delete'}
        value={state.values?.tags ?? ''}
        onchange={(v) => state.setState('values', { ...state.values, tags: v })}
      />
    </div>
  {/snippet}
</FormerShell>
</ErrorBoundary>
