<script lang="ts">
  import { goto } from "$app/navigation";
  import { unlockVaultWorkspace } from "$lib/backend/auth";
  import AppModal from "$lib/components/AppModal.svelte";
  import { entriesStore, getDefaultEntry, hydrateEntries, loadEntryByStoreId } from "$lib/stores/entries";
  import { hydrateFragments } from "$lib/stores/fragments";
  import { hydrateLists } from "$lib/stores/lists";
  import { isVaultReady, setVaultSession } from "$lib/stores/session";
  import { hydrateTodos } from "$lib/stores/todos";
  import Navbar from "$lib/components/Navbar.svelte";
  import SidePanel from "$lib/components/SidePanel.svelte";
  import EditorPanel from "$lib/components/EditorPanel.svelte";
  import { onMount } from "svelte";
  import { get } from "svelte/store";

  type OpenDocument = {
    id: string;
    label: string;
    initialContent: string;
  };

  const initialEntry = getDefaultEntry(get(entriesStore));

  let selectedSection = "entries";
  let panelOpen = true;
  let activeDocumentId = initialEntry?.id ?? "entries/daily-notes";
  let activeDocumentLabel = initialEntry?.label ?? "Daily Notes";
  let openDocuments: Record<string, string> = initialEntry
    ? { [initialEntry.id]: initialEntry.initialContent }
    : { "entries/daily-notes": "# Daily Notes\n\nStart writing today's entry..." };
  let modalOpen = false;
  let modalTitle = "";
  let modalMessage = "";
  let modalConfirmText = "OK";
  let modalCancelText = "Cancel";
  let modalShowCancel = false;
  let modalTone: "default" | "danger" = "default";
  let modalAction: "logout-confirm" | "logout-info" | "unlock-vault" | null = null;
  let modalInputEnabled = false;
  let modalInputType = "text";
  let modalInputPlaceholder = "";
  let modalInputAriaLabel = "Modal input";
  let modalInputValue = "";
  let unlockResolver: ((password: string | null) => void) | null = null;
  let fragmentBootstrapInFlight = false;

  function showModal(options: {
    action: "logout-confirm" | "logout-info" | "unlock-vault";
    title: string;
    message: string;
    confirmText?: string;
    cancelText?: string;
    showCancel?: boolean;
    tone?: "default" | "danger";
    inputEnabled?: boolean;
    inputType?: string;
    inputPlaceholder?: string;
    inputAriaLabel?: string;
    inputValue?: string;
  }) {
    modalAction = options.action;
    modalTitle = options.title;
    modalMessage = options.message;
    modalConfirmText = options.confirmText ?? "OK";
    modalCancelText = options.cancelText ?? "Cancel";
    modalShowCancel = options.showCancel ?? false;
    modalTone = options.tone ?? "default";
    modalInputEnabled = options.inputEnabled ?? false;
    modalInputType = options.inputType ?? "text";
    modalInputPlaceholder = options.inputPlaceholder ?? "";
    modalInputAriaLabel = options.inputAriaLabel ?? "Modal input";
    modalInputValue = options.inputValue ?? "";
    modalOpen = true;
  }

  function closeModal() {
    modalOpen = false;
    modalAction = null;
    modalInputEnabled = false;
    modalInputType = "text";
    modalInputPlaceholder = "";
    modalInputAriaLabel = "Modal input";
    modalInputValue = "";
  }

  function handleModalConfirm() {
    if (modalAction === "logout-confirm") {
      showModal({
        action: "logout-info",
        title: "Logout Requested",
        message: "You have been logged out.",
        confirmText: "Close"
      });
      return;
    }

    if (modalAction === "unlock-vault") {
      const value = modalInputValue.trim();
      if (!value) return;
      const resolve = unlockResolver;
      unlockResolver = null;
      closeModal();
      resolve?.(value);
      return;
    }

    closeModal();
  }

  function handleModalCancel() {
    if (modalAction === "unlock-vault") {
      const resolve = unlockResolver;
      unlockResolver = null;
      closeModal();
      resolve?.(null);
      return;
    }

    closeModal();
  }

  function requestVaultPassword(): Promise<string | null> {
    return new Promise((resolve) => {
      unlockResolver = resolve;
      showModal({
        action: "unlock-vault",
        title: "Unlock Vault",
        message: "Enter your vault password to load journal data.",
        confirmText: "Unlock",
        cancelText: "Cancel",
        showCancel: true,
        inputEnabled: true,
        inputType: "password",
        inputPlaceholder: "Vault password",
        inputAriaLabel: "Vault password",
        inputValue: ""
      });
    });
  }

  function isLockedError(error: unknown): boolean {
    const message = error instanceof Error ? error.message : String(error);
    const normalized = message.toLowerCase();
    return normalized.includes("database is locked") || normalized.includes("incorrect vault password");
  }

  async function bootstrapFragmentsWithUnlock(maxAttempts = 3) {
    if (fragmentBootstrapInFlight) return;

    if (isVaultReady()) {
      try {
        await hydrateEntries();
        const firstEntry = getDefaultEntry(get(entriesStore));
        if (firstEntry && activeDocumentId === "entries/daily-notes") {
          await handleOpenDocument(firstEntry);
        }
        await hydrateFragments();
        await hydrateLists().catch(() => {});
        await hydrateTodos().catch(() => {});
      } catch (error) {
        console.error("Hydration failed:", error);
      }
      return;
    }

    fragmentBootstrapInFlight = true;
    try {
      let attempts = 0;
      while (attempts < maxAttempts) {
        try {
          const password = await requestVaultPassword();
          if (!password) return;

          await unlockVaultWorkspace(password);
          setVaultSession(password);

          await hydrateEntries();
          const firstEntry = getDefaultEntry(get(entriesStore));
          if (firstEntry && activeDocumentId === "entries/daily-notes") {
            await handleOpenDocument(firstEntry);
          }

          await hydrateFragments();
          await hydrateLists().catch(() => {});
          await hydrateTodos().catch(() => {});
          return;
        } catch (error) {
          if (!isLockedError(error)) return;
          attempts += 1;
        }
      }

    } finally {
      fragmentBootstrapInFlight = false;
    }
  }

  function handleSelect(id: string) {
    if (id === "account" || id === "settings") {
      goto(`/${id}`);
      return;
    }

    if (id === "logout") {
      showModal({
        action: "logout-confirm",
        title: "Confirm Logout",
        message: "Are you sure you want to log out?",
        confirmText: "Log Out",
        cancelText: "Cancel",
        showCancel: true,
        tone: "danger"
      });
      return;
    }

    if (selectedSection === id) {
      panelOpen = !panelOpen;
      return;
    }

    selectedSection = id;
    panelOpen = true;
    activeDocumentId = "";
    activeDocumentLabel = "";
  }

  async function handleOpenDocument(doc: OpenDocument) {
    let resolvedDoc = doc;
    if (selectedSection === "entries" && doc.id.startsWith("entries/file/") && !doc.initialContent) {
      try {
        const loaded = await loadEntryByStoreId(doc.id);
        if (loaded) {
          resolvedDoc = loaded;
        }
      } catch {
        // entry content will use initialContent fallback
      }
    }

    if (!(resolvedDoc.id in openDocuments)) {
      openDocuments = { ...openDocuments, [resolvedDoc.id]: resolvedDoc.initialContent };
    }
    activeDocumentId = resolvedDoc.id;
    activeDocumentLabel = resolvedDoc.label;
  }

  function handleDocumentContentChange(content: string) {
    openDocuments = { ...openDocuments, [activeDocumentId]: content };
  }

  function handleDeleteDocument(id: string) {
    const { [id]: _, ...remaining } = openDocuments;
    openDocuments = remaining;
  }

  onMount(() => {
    bootstrapFragmentsWithUnlock();
  });
</script>

<div class="app-shell" class:panel-closed={!panelOpen}>
  <Navbar activeSection={selectedSection} onSelect={handleSelect} />
  {#if panelOpen}
    <SidePanel
      activeSection={selectedSection}
      {activeDocumentId}
      onOpenDocument={handleOpenDocument}
    />
  {/if}
  <EditorPanel
    activeSection={selectedSection}
    openDocumentId={activeDocumentId}
    openDocumentName={activeDocumentLabel}
    openDocumentContent={openDocuments[activeDocumentId] ?? ""}
    onDocumentContentChange={handleDocumentContentChange}
    onOpenDocument={handleOpenDocument}
    onDeleteDocument={handleDeleteDocument}
  />
</div>

<AppModal
  open={modalOpen}
  title={modalTitle}
  message={modalMessage}
  confirmText={modalConfirmText}
  cancelText={modalCancelText}
  showCancel={modalShowCancel}
  tone={modalTone}
  inputEnabled={modalInputEnabled}
  inputType={modalInputType}
  inputPlaceholder={modalInputPlaceholder}
  inputAriaLabel={modalInputAriaLabel}
  bind:inputValue={modalInputValue}
  onConfirm={handleModalConfirm}
  onCancel={handleModalCancel}
/>


