<script setup lang="ts">
import { computed, onMounted, ref, watch } from "vue";
import { storeToRefs } from "pinia";
import { Plus, Trash2, Hash } from "lucide-vue-next";
import { useTopicsStore } from "@/stores/topics";
import { useNodeStore } from "@/stores/node";
import { base64ToUtf8, isPrintableUtf8, utf8ToBase64 } from "@/lib/utils";

const topicsStore = useTopicsStore();
const node = useNodeStore();
const { topics, defaultAction, sources, forwards, error } = storeToRefs(topicsStore);
const { phase } = storeToRefs(node);

const isReady = computed(() => phase.value === "ready");
const newTopic = ref("");
const selected = ref<string | null>(null);
const newSource = ref("");
const newForward = ref("");

onMounted(async () => {
  if (isReady.value) await topicsStore.refresh();
});

watch(
  () => topics.value,
  (list) => {
    if (selected.value && !list.includes(selected.value)) selected.value = null;
    if (!selected.value && list.length) selected.value = list[0];
  },
  { immediate: true },
);

watch(selected, async (t) => {
  if (!t) return;
  await Promise.all([topicsStore.refreshSources(t), topicsStore.refreshForward(t)]);
});

function topicLabel(t: string): string {
  return isPrintableUtf8(t) ? base64ToUtf8(t) : `b64:${t.slice(0, 18)}…`;
}

async function addTopic() {
  const v = newTopic.value.trim();
  if (!v) return;
  try {
    await topicsStore.addTopic(utf8ToBase64(v));
    newTopic.value = "";
  } catch (e) {
    alert(`Could not add topic: ${e}`);
  }
}

async function removeTopic(t: string) {
  if (!confirm(`Remove topic "${topicLabel(t)}"?`)) return;
  try {
    await topicsStore.removeTopic(t);
  } catch (e) {
    alert(`Could not remove: ${e}`);
  }
}

async function addSource() {
  if (!selected.value || !newSource.value.trim()) return;
  try {
    await topicsStore.addSource(selected.value, newSource.value.trim());
    newSource.value = "";
  } catch (e) {
    alert(`Could not add source: ${e}`);
  }
}

async function removeSource(subnet: string) {
  if (!selected.value) return;
  try {
    await topicsStore.removeSource(selected.value, subnet);
  } catch (e) {
    alert(`Could not remove source: ${e}`);
  }
}

async function setForward() {
  if (!selected.value || !newForward.value.trim()) return;
  try {
    await topicsStore.setForward(selected.value, newForward.value.trim());
    newForward.value = "";
  } catch (e) {
    alert(`Could not set forward: ${e}`);
  }
}

async function clearForward() {
  if (!selected.value) return;
  if (!confirm("Remove forward socket?")) return;
  await topicsStore.removeForward(selected.value);
}

async function toggleDefault() {
  await topicsStore.setDefault(!defaultAction.value.accept);
}
</script>

<template>
  <div v-if="!isReady" class="text-sm text-muted-foreground">Daemon offline.</div>
  <div v-else class="grid gap-4 lg:grid-cols-[260px_1fr]">
    <section class="space-y-3">
      <div class="rounded-lg border border-border bg-card p-3">
        <div class="text-xs uppercase tracking-wide text-muted-foreground">
          Default action
        </div>
        <button
          class="mt-2 w-full rounded-md border border-border px-3 py-2 text-sm hover:bg-secondary"
          @click="toggleDefault"
        >
          {{ defaultAction.accept ? "Accept by default" : "Reject by default" }}
        </button>
        <p class="mt-2 text-[11px] text-muted-foreground">
          Controls how the daemon treats topics that aren't in the whitelist
          below.
        </p>
      </div>

      <div class="rounded-lg border border-border bg-card">
        <header class="flex items-center justify-between border-b border-border px-3 py-2">
          <span class="text-sm font-medium">Whitelisted topics</span>
          <span class="text-xs text-muted-foreground">{{ topics.length }}</span>
        </header>
        <ul class="max-h-[40vh] divide-y divide-border overflow-y-auto">
          <li v-if="!topics.length" class="px-3 py-4 text-center text-xs text-muted-foreground">
            No topics yet.
          </li>
          <li
            v-for="t in topics"
            :key="t"
            class="flex cursor-pointer items-center justify-between gap-2 px-3 py-2 text-sm hover:bg-muted/30"
            :class="selected === t ? 'bg-secondary text-secondary-foreground' : ''"
            @click="selected = t"
          >
            <Hash class="h-3 w-3 shrink-0 text-muted-foreground" />
            <span class="min-w-0 flex-1 truncate font-mono text-xs">
              {{ topicLabel(t) }}
            </span>
            <button
              class="shrink-0 rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
              @click.stop="removeTopic(t)"
            >
              <Trash2 class="h-3 w-3" />
            </button>
          </li>
        </ul>
        <footer class="flex gap-2 border-t border-border p-3">
          <input
            v-model="newTopic"
            type="text"
            placeholder="topic name"
            class="flex-1 rounded-md border border-input bg-background px-2 py-1 text-xs focus:outline-none focus:ring-1 focus:ring-ring"
            @keyup.enter="addTopic"
          />
          <button
            class="inline-flex items-center gap-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90"
            @click="addTopic"
          >
            <Plus class="h-3 w-3" /> Add
          </button>
        </footer>
      </div>
      <p v-if="error" class="text-xs text-destructive">{{ error }}</p>
    </section>

    <section v-if="selected" class="space-y-4">
      <div class="rounded-lg border border-border bg-card p-4">
        <div class="text-xs uppercase tracking-wide text-muted-foreground">
          Selected topic
        </div>
        <div class="mt-1 break-all font-mono text-sm">
          {{ topicLabel(selected) }}
        </div>
        <div class="mt-1 break-all text-[11px] text-muted-foreground">
          base64: {{ selected }}
        </div>
      </div>

      <div class="rounded-lg border border-border bg-card">
        <header class="border-b border-border px-4 py-2 text-sm font-medium">
          Allowed source subnets
        </header>
        <ul class="divide-y divide-border">
          <li
            v-if="!(sources[selected]?.length)"
            class="px-4 py-3 text-center text-xs text-muted-foreground"
          >
            No sources — all subnets allowed for this topic.
          </li>
          <li
            v-for="s in sources[selected] ?? []"
            :key="s"
            class="flex items-center justify-between px-4 py-2 text-sm hover:bg-muted/30"
          >
            <span class="font-mono text-xs">{{ s }}</span>
            <button
              class="rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
              @click="removeSource(s)"
            >
              <Trash2 class="h-3 w-3" />
            </button>
          </li>
        </ul>
        <footer class="flex gap-2 border-t border-border p-3">
          <input
            v-model="newSource"
            type="text"
            placeholder="503:5478:df06:d79a::/64"
            class="flex-1 rounded-md border border-input bg-background px-2 py-1 font-mono text-xs focus:outline-none focus:ring-1 focus:ring-ring"
            @keyup.enter="addSource"
          />
          <button
            class="inline-flex items-center gap-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90"
            @click="addSource"
          >
            <Plus class="h-3 w-3" /> Allow
          </button>
        </footer>
      </div>

      <div class="rounded-lg border border-border bg-card">
        <header class="border-b border-border px-4 py-2 text-sm font-medium">
          Forward socket
        </header>
        <div class="px-4 py-3 text-sm">
          <span v-if="forwards[selected]" class="font-mono text-xs">
            {{ forwards[selected] }}
          </span>
          <span v-else class="text-muted-foreground">No forward configured.</span>
        </div>
        <footer class="flex gap-2 border-t border-border p-3">
          <input
            v-model="newForward"
            type="text"
            placeholder="/var/run/myapp.sock"
            class="flex-1 rounded-md border border-input bg-background px-2 py-1 font-mono text-xs focus:outline-none focus:ring-1 focus:ring-ring"
            @keyup.enter="setForward"
          />
          <button
            class="rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground hover:opacity-90"
            @click="setForward"
          >
            Set
          </button>
          <button
            v-if="forwards[selected]"
            class="rounded-md border border-border px-2 py-1 text-xs hover:bg-destructive/10 hover:text-destructive"
            @click="clearForward"
          >
            Clear
          </button>
        </footer>
      </div>
    </section>
    <section v-else class="text-sm text-muted-foreground">
      Pick a topic on the left to manage its sources and forward.
    </section>
  </div>
</template>
