'use client';

import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { usePrivacy } from './use-privacy.js';
import { useShareData } from './use-share-data.js';

const ProjectAlbumContext = createContext(null);

function itemKey(item) {
  return `${item.source_type}-${item.id}`;
}

function mergeItem(items, nextItem) {
  if (!nextItem?.id || !nextItem?.source_type) return items;
  const key = itemKey(nextItem);
  let found = false;
  const merged = items.map((item) => {
    if (itemKey(item) !== key) return item;
    found = true;
    return { ...item, ...nextItem };
  });
  return found ? merged : [nextItem, ...merged];
}

export function ProjectAlbumProvider({
  children,
  initialItems = [],
  initialFolders = [],
  projectId,
  projectSlug,
  rootFolderId = null,
  currentFolderId = null,
  liveDeltasEnabled = false,
}) {
  const privacy = usePrivacy({ projectId });
  const shareData = useShareData();
  const [items, setItems] = useState(initialItems);
  const [folders, setFolders] = useState(initialFolders);
  const [setupModalOpen, setSetupModalOpen] = useState(false);
  const [unlockModalOpen, setUnlockModalOpen] = useState(false);

  useEffect(() => {
    setItems(initialItems);
  }, [initialItems]);

  useEffect(() => {
    setFolders(initialFolders);
  }, [initialFolders]);

  const refreshLibrary = useCallback(async () => {
    if (!projectSlug) return;
    const res = await fetch(`/api/projects/${encodeURIComponent(projectSlug)}/library`, {
      cache: 'no-store',
    });
    if (!res.ok) throw new Error(`library refresh failed (${res.status})`);
    const data = await res.json();
    setItems(Array.isArray(data.libraryItems) ? data.libraryItems : []);
    setFolders(Array.isArray(data.folders) ? data.folders : []);
  }, [projectSlug]);

  useEffect(() => {
    if (!liveDeltasEnabled || typeof window === 'undefined') return undefined;
    const events = new EventSource('/api/events/stream');
    let refreshTimer = null;
    let safetyTimer = null;

    const scheduleRefresh = () => {
      if (refreshTimer) window.clearTimeout(refreshTimer);
      refreshTimer = window.setTimeout(() => {
        refreshTimer = null;
        refreshLibrary().catch((err) => {
          // eslint-disable-next-line no-console
          console.warn('[project-album] live library refresh failed', err);
        });
      }, 250);
    };

    const watched = [
      'state.disk.changed',
      'state.artifacts.changed',
      'state.acl.changed',
      'state.share_links.changed',
    ];
    for (const type of watched) events.addEventListener(type, scheduleRefresh);
    const onVisible = () => {
      if (document.visibilityState === 'visible') scheduleRefresh();
    };
    document.addEventListener('visibilitychange', onVisible);
    safetyTimer = window.setInterval(scheduleRefresh, 60000);

    return () => {
      for (const type of watched) events.removeEventListener(type, scheduleRefresh);
      document.removeEventListener('visibilitychange', onVisible);
      if (refreshTimer) window.clearTimeout(refreshTimer);
      if (safetyTimer) window.clearInterval(safetyTimer);
      events.close();
    };
  }, [liveDeltasEnabled, refreshLibrary]);

  const applyItemPatch = useCallback((patch) => {
    setItems((current) => mergeItem(current, patch));
  }, []);

  const removeItem = useCallback((itemOrKey) => {
    const key = typeof itemOrKey === 'string' ? itemOrKey : itemKey(itemOrKey);
    setItems((current) => current.filter((item) => itemKey(item) !== key));
  }, []);

  const value = useMemo(() => ({
    items,
    folders,
    setItems,
    setFolders,
    applyItemPatch,
    removeItem,
    refreshLibrary,
    liveDeltasEnabled,
    projectId,
    projectSlug,
    rootFolderId,
    currentFolderId,
    privacy,
    shareData,
    setupModalOpen,
    unlockModalOpen,
    openSetupModal: () => setSetupModalOpen(true),
    closeSetupModal: () => setSetupModalOpen(false),
    openUnlockModal: () => setUnlockModalOpen(true),
    closeUnlockModal: () => setUnlockModalOpen(false),
  }), [items, folders, applyItemPatch, removeItem, refreshLibrary, liveDeltasEnabled, projectId, projectSlug, rootFolderId, currentFolderId, privacy, shareData, setupModalOpen, unlockModalOpen]);

  return (
    <ProjectAlbumContext.Provider value={value}>
      {children}
    </ProjectAlbumContext.Provider>
  );
}

export function useProjectAlbum() {
  const value = useContext(ProjectAlbumContext);
  if (!value) {
    throw new Error('useProjectAlbum must be used inside ProjectAlbumProvider');
  }
  return value;
}
