<script lang="ts">
  import {
    createPolicy,
    deletePolicy,
    listFolders,
    listPolicies,
    updatePolicy,
  } from "$lib/api/endpoints";
  import type {
    CaptureToggles,
    Folder,
    PolicyRecord,
    PolicyScopeType,
  } from "$lib/api/types";
  import CaptureToggleList from "$lib/components/policy/CaptureToggleList.svelte";
  import Icon from "$lib/components/ui/Icon.svelte";
  import Spinner from "$lib/components/ui/Spinner.svelte";
  import { accounts } from "$lib/stores/accounts.svelte";
  import { chats } from "$lib/stores/chats.svelte";
  import { toasts } from "$lib/stores/toasts.svelte";

  let policies = $state<PolicyRecord[]>([]);
  let folders = $state<Folder[]>([]);
  let loading = $state(true);
  let pickFolder = $state(false);
  let pickChat = $state(false);
  let chatFilter = $state("");

  const DEFAULT_SCOPES: { label: string; scope: PolicyScopeType }[] = [
    { scope: "default_dm", label: "Личные чаты" },
    { scope: "default_group", label: "Группы" },
    { scope: "default_channel", label: "Каналы" },
  ];

  const ALL_FALSE: CaptureToggles = {
    messages: false,
    media: false,
    self_destruct_media: false,
    stt: false,
    reactions: false,
    track_edits_deletes: false,
    profile_history: false,
    stories: false,
    presence: false,
    backfill: false,
  };

  function pickToggles(t: CaptureToggles): CaptureToggles {
    return {
      messages: t.messages,
      media: t.media,
      self_destruct_media: t.self_destruct_media,
      stt: t.stt,
      reactions: t.reactions,
      track_edits_deletes: t.track_edits_deletes,
      profile_history: t.profile_history,
      stories: t.stories,
      presence: t.presence,
      backfill: t.backfill,
    };
  }

  const defaults = $derived(
    DEFAULT_SCOPES.map((d) => ({
      label: d.label,
      record: policies.find((p) => p.scope_type === d.scope),
    })).filter((d): d is { label: string; record: PolicyRecord } =>
      Boolean(d.record)
    )
  );
  const folderPolicies = $derived(
    policies.filter((p) => p.scope_type === "folder")
  );
  const chatPolicies = $derived(
    policies.filter((p) => p.scope_type === "chat")
  );
  const availableFolders = $derived(
    folders.filter(
      (f) => !folderPolicies.some((p) => p.scope_id === f.folder_id)
    )
  );
  const availableChats = $derived(
    chats.list
      .filter((c) => !chatPolicies.some((p) => p.scope_id === c.chat_id))
      .filter((c) =>
        (c.title ?? "").toLowerCase().includes(chatFilter.trim().toLowerCase())
      )
      .slice(0, 40)
  );

  function folderTitle(id: number | null): string {
    return folders.find((f) => f.folder_id === id)?.title ?? `Папка ${id}`;
  }

  function chatTitle(id: number | null): string {
    return chats.byId(id ?? 0)?.title ?? `Чат ${id}`;
  }

  async function reload() {
    [policies, folders] = await Promise.all([listPolicies(), listFolders()]);
  }

  async function toggle(
    record: PolicyRecord,
    key: keyof CaptureToggles,
    value: boolean
  ) {
    const next = { ...pickToggles(record), [key]: value };
    policies = policies.map((p) =>
      p.id === record.id ? { ...p, [key]: value } : p
    );
    try {
      const saved = await updatePolicy(record.id, next);
      policies = policies.map((p) => (p.id === record.id ? saved : p));
    } catch {
      toasts.error("Не удалось сохранить политику");
      await reload();
    }
  }

  async function addOverride(scope: "folder" | "chat", scopeId: number) {
    try {
      const record = await createPolicy({
        ...ALL_FALSE,
        scope_type: scope,
        scope_id: scopeId,
      });
      policies = [...policies, record];
      pickFolder = false;
      pickChat = false;
      chatFilter = "";
    } catch {
      toasts.error("Не удалось создать оверрайд");
    }
  }

  async function removeOverride(record: PolicyRecord) {
    policies = policies.filter((p) => p.id !== record.id);
    try {
      await deletePolicy(record.id);
    } catch {
      toasts.error("Не удалось удалить оверрайд");
      await reload();
    }
  }

  async function load(_account: number | null) {
    loading = true;
    chats.load();
    try {
      await reload();
    } catch {
      toasts.error("Не удалось загрузить политики");
    } finally {
      loading = false;
    }
  }

  $effect(() => {
    load(accounts.selectedId);
  });
</script>

{#snippet card(record: PolicyRecord, title: string, onremove?: () => void)}
  <div class="card">
    <div class="card-head">
      <span class="card-title">{title}</span>
      {#if record.account_id === null}
        <span class="shared">для всех аккаунтов</span>
      {/if}
      {#if onremove && record.account_id !== null}
        <button
          type="button"
          class="remove"
          aria-label="Удалить оверрайд"
          onclick={onremove}
        >
          <Icon name="close" size="1.125rem" />
        </button>
      {/if}
    </div>
    <CaptureToggleList
      toggles={record}
      onchange={(key, value) => toggle(record, key, value)}
    />
  </div>
{/snippet}

{#if loading}
  <div class="state"><Spinner /></div>
{:else}
  <div class="editor">
    <section>
      <div class="section-title">По умолчанию</div>
      {#each defaults as item (item.record.id)}
        {@render card(item.record, item.label)}
      {/each}
    </section>

    <section>
      <div class="section-title">Оверрайды папок</div>
      {#each folderPolicies as record (record.id)}
        {@render card(record, folderTitle(record.scope_id), () =>
          removeOverride(record)
        )}
      {/each}
      {#if availableFolders.length > 0}
        <button
          type="button"
          class="add"
          onclick={() => {
            pickFolder = !pickFolder;
          }}
        >
          <Icon name="add" size="1.25rem" />
          <span>Добавить папку</span>
        </button>
        {#if pickFolder}
          <div class="picker">
            {#each availableFolders as folder (folder.folder_id)}
              <button
                type="button"
                class="pick-row"
                onclick={() => addOverride("folder", folder.folder_id)}
              >
                {folder.title}
              </button>
            {/each}
          </div>
        {/if}
      {/if}
    </section>

    <section>
      <div class="section-title">Оверрайды чатов</div>
      {#each chatPolicies as record (record.id)}
        {@render card(record, chatTitle(record.scope_id), () =>
          removeOverride(record)
        )}
      {/each}
      <button
        type="button"
        class="add"
        onclick={() => {
          pickChat = !pickChat;
        }}
      >
        <Icon name="add" size="1.25rem" />
        <span>Добавить чат</span>
      </button>
      {#if pickChat}
        <div class="picker">
          <input
            class="filter"
            type="text"
            placeholder="Поиск чата"
            bind:value={chatFilter}
          >
          {#each availableChats as chat (chat.chat_id)}
            <button
              type="button"
              class="pick-row"
              onclick={() => addOverride("chat", chat.chat_id)}
            >
              {chat.title ?? `Чат ${chat.chat_id}`}
            </button>
          {/each}
        </div>
      {/if}
    </section>
  </div>
{/if}

<style lang="scss">
  .state {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
  }

  .editor {
    padding-bottom: 1rem;
  }

  section {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-borders);
  }

  .section-title {
    padding: 0.5rem 1rem;
    font-size: 0.8125rem;
    font-weight: var(--font-weight-medium);
    color: var(--color-primary);
  }

  .card {
    padding: 0.25rem 0 0.5rem;
  }

  .card-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 1rem;
  }

  .card-title {
    flex: 1;
    font-size: 0.9375rem;
    font-weight: var(--font-weight-medium);
  }

  .shared {
    font-size: 0.75rem;
    color: var(--color-text-secondary);
  }

  .remove {
    cursor: pointer;
    display: flex;
    padding: 0.25rem;
    border: 0;
    border-radius: 50%;
    color: var(--color-text-secondary);
    background-color: transparent;

    &:hover {
      background-color: var(--color-chat-hover);
    }
  }

  .add {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 1rem;

    width: 100%;
    padding: 0.625rem 1rem;
    border: 0;

    font-size: 0.9375rem;
    color: var(--color-primary);
    background-color: transparent;

    &:hover {
      background-color: var(--color-chat-hover);
    }
  }

  .picker {
    display: flex;
    flex-direction: column;
    padding: 0 0.5rem 0.5rem;
  }

  .filter {
    margin: 0.25rem 0.5rem 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--color-borders);
    border-radius: var(--border-radius-default);

    font-size: 0.9375rem;
    color: var(--color-text);
    background-color: var(--color-background);

    &:focus {
      border-color: var(--color-primary);
      outline: none;
    }
  }

  .pick-row {
    cursor: pointer;
    overflow: hidden;

    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 0;
    border-radius: 0.5rem;

    font-size: 0.9375rem;
    text-align: start;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--color-text);
    background-color: transparent;

    &:hover {
      background-color: var(--color-chat-hover);
    }
  }
</style>
