<script lang="ts">
  import { onMount } from "svelte";
  import { bridgeState } from "./lib/bridge.svelte";
  import * as rpc from "./lib/rpc";
  import { cfg, channels, agents, users, recents, status } from "./lib/stores.svelte";
  import SubscriptionsPanel from "./lib/SubscriptionsPanel.svelte";
  import DestinationsPanel from "./lib/DestinationsPanel.svelte";
  import ClassifierPanel from "./lib/ClassifierPanel.svelte";
  import RecentsPanel from "./lib/RecentsPanel.svelte";

  let mounted = $state(false);

  onMount(async () => {
    await new Promise<void>((resolve) => {
      const check = () => {
        if (bridgeState.ready) resolve();
        else setTimeout(check, 50);
      };
      check();
    });
    try {
      await rpc.connectRpc(bridgeState.gatewayUrl, bridgeState.authToken);
      const got = await rpc.pluginsConfigGet("complaint-listener");
      cfg.subscriptions = (got.config.subscriptions as any[]) ?? [];
      cfg.destinations = (got.config.destinations as any[]) ?? [];
      cfg.classifier = (got.config.classifier as any) ?? {};
      channels.list = got.channels ?? [];
      agents.list = got.agents ?? [];
    } catch (err) {
      console.error("[complaint-listener] RPC init failed:", err);
      status.saveError = `RPC error: ${err instanceof Error ? err.message : String(err)}`;
    }
    try {
      recents.list = (await rpc.pluginsComplaintsRecent(20)) ?? [];
    } catch (err) {
      console.error("failed to load recents", err);
    }
    try {
      const { users: list } = await rpc.pluginsUsersList();
      users.list = list ?? [];
    } catch (err) {
      // Hub-served RPC — fails outside hub context, which is fine.
      console.warn("[complaint-listener] users.list unavailable:", err);
    }
    mounted = true;
  });

  async function refreshRecents() {
    try {
      recents.list = (await rpc.pluginsComplaintsRecent(20)) ?? [];
    } catch (err) {
      console.error("failed to refresh recents", err);
    }
  }

  async function save() {
    status.saving = true;
    status.saveError = null;
    try {
      const res = await rpc.pluginsConfigSet("complaint-listener", { ...cfg });
      if (!res.ok) status.saveError = (res.errors ?? []).join("; ") || "save failed";
    } catch (err) {
      status.saveError = String(err);
    } finally {
      status.saving = false;
    }
  }
</script>

{#if !mounted}
  <main class="p-8">
    <div class="flex items-center gap-3 text-sm text-[var(--color-fg-muted)]">
      <span
        class="inline-block h-4 w-4 animate-spin rounded-full border-2 border-[var(--color-border)] border-t-[var(--color-primary)]"
        aria-hidden="true"
      ></span>
      <span>Loading…</span>
    </div>
  </main>
{:else}
  <main class="mx-auto max-w-5xl space-y-8 p-6 sm:p-8">
    <header class="space-y-1">
      <h1 class="text-xl font-semibold tracking-tight text-[var(--color-fg)]">
        Complaint Listener
      </h1>
      <p class="text-sm text-[var(--color-fg-muted)]">
        Watches subscribed channels and fans out alerts to configured destinations.
      </p>
    </header>

    <SubscriptionsPanel
      subs={cfg.subscriptions}
      channels={channels.list}
      agents={agents.list}
      onAdd={(s) => (cfg.subscriptions = [...cfg.subscriptions, s])}
      onRemove={(i) => (cfg.subscriptions = cfg.subscriptions.filter((_, idx) => idx !== i))}
      onUpdate={(i, s) =>
        (cfg.subscriptions = cfg.subscriptions.map((existing, idx) => (idx === i ? s : existing)))}
    />

    <DestinationsPanel
      dests={cfg.destinations}
      channels={channels.list}
      users={users.list}
      onAdd={(d) => (cfg.destinations = [...cfg.destinations, d])}
      onRemove={(i) => (cfg.destinations = cfg.destinations.filter((_, idx) => idx !== i))}
      onUpdate={(i, d) =>
        (cfg.destinations = cfg.destinations.map((existing, idx) => (idx === i ? d : existing)))}
    />

    <ClassifierPanel classifier={cfg.classifier} onChange={(c) => (cfg.classifier = c)} />

    <div
      class="sticky bottom-4 flex items-center gap-3 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)]/95 px-4 py-3 shadow-lg backdrop-blur"
    >
      <button
        class="inline-flex h-10 items-center justify-center rounded-md bg-[var(--color-primary)] px-5 text-sm font-medium text-[var(--color-primary-fg)] shadow-sm transition-all duration-150 hover:brightness-110 active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-bg)]"
        disabled={status.saving}
        onclick={save}
      >
        {#if status.saving}
          <span
            class="mr-2 inline-block h-3.5 w-3.5 animate-spin rounded-full border-2 border-white/40 border-t-white"
            aria-hidden="true"
          ></span>
        {/if}
        {status.saving ? "Saving…" : "Save changes"}
      </button>
      {#if status.saveError}
        <span role="alert" class="text-sm text-[var(--color-danger)]">{status.saveError}</span>
      {/if}
    </div>

    <RecentsPanel recents={recents.list} onRefresh={refreshRecents} />
  </main>
{/if}
