'use client';

import type React from 'react';
import { useState, useCallback, useRef } from 'react';
import { nanoid } from 'nanoid';
import type { ModeType } from '@/shared/types/common';

export interface TabItem<T> {
  id: string;
  title: string;
  content: T | 'list';
  originalContent?: T;
  closeable?: boolean;
  mode?: ModeType;
  hasUnsavedChanges?: boolean;
}

export interface TabConfig<T> {
  type: string;
  listTitle: string;
  newItemTitle: string;
  initialData: T;
  getItemCode: (item: T) => string;
}

export function useTabsManager<T extends { id: string }>(config: TabConfig<T>) {
  const [tabs, setTabs] = useState<TabItem<T>[]>([
    { id: 'list', title: config.listTitle, content: 'list', closeable: false }
  ]);
  const [activeTab, setActiveTab] = useState<string>('list');
  const [showConfirmDialog, setShowConfirmDialog] = useState(false);
  const pendingAction = useRef<'close' | null>(null);
  const tabToCloseRef = useRef<string | null>(null);

  const findViewTab = useCallback(
    (itemId: string) => {
      return tabs.find((tab) => tab.id === `${itemId}view` && tab.mode === 'view');
    },
    [tabs]
  );

  const checkUnsavedChanges = useCallback((tab: TabItem<T>) => {
    if (tab.content === 'list' || tab.mode === 'view') return false;

    if (!tab.originalContent) return false;

    return JSON.stringify(tab.originalContent) !== JSON.stringify(tab.content);
  }, []);

  const updateTabContent = useCallback((tabId: string, newContent: T) => {
    setTabs((prevTabs) => {
      return prevTabs.map((tab) => {
        if (tab.id === tabId) {
          const updatedTab = { ...tab, content: newContent };
          const hasChanges = tab.originalContent
            ? JSON.stringify(tab.originalContent) !== JSON.stringify(newContent)
            : false;

          updatedTab.hasUnsavedChanges = hasChanges;
          return updatedTab;
        }
        return tab;
      });
    });
  }, []);

  const setTabHasUnsavedChanges = useCallback((tabId: string, hasChanges: boolean) => {
    setTabs((prevTabs) => {
      const tab = prevTabs.find((t) => t.id === tabId);
      if (tab && tab.hasUnsavedChanges === hasChanges) {
        return prevTabs;
      }
      return prevTabs.map((tab) =>
        tab.id === tabId ? { ...tab, hasUnsavedChanges: hasChanges } : tab
      );
    });
  }, []);

  const handleTabClose = useCallback(
    (event: React.MouseEvent, tabId: string) => {
      event.stopPropagation();

      const tabToClose = tabs.find((tab) => tab.id === tabId);
      if (tabToClose?.hasUnsavedChanges) {
        tabToCloseRef.current = tabId;
        pendingAction.current = 'close';
        setShowConfirmDialog(true);
        return;
      }

      setTabs((prevTabs) => prevTabs.filter((tab) => tab.id !== tabId));
      if (activeTab === tabId) {
        setActiveTab('list');
      }
    },
    [activeTab, tabs]
  );

  const handleTabChange = useCallback((event: React.SyntheticEvent, newValue: string) => {
    setActiveTab(newValue);
  }, []);

  const handleConfirmDialogAction = useCallback(() => {
    setShowConfirmDialog(false);
    if (pendingAction.current === 'close') {
      const tabIdToClose = tabToCloseRef.current || activeTab;
      setTabs((prevTabs) => prevTabs.filter((tab) => tab.id !== tabIdToClose));

      if (activeTab === tabIdToClose) {
        setActiveTab('list');
      }
    }

    pendingAction.current = null;
    tabToCloseRef.current = null;
  }, [activeTab]);

  const handleTabAdd = useCallback(() => {
    const initialContent = { ...config.initialData } as T;
    const newTab: TabItem<T> = {
      id: nanoid(),
      title: config.newItemTitle,
      content: initialContent,
      originalContent: initialContent,
      closeable: true,
      mode: 'add',
      hasUnsavedChanges: false,
    };
    setTabs((prevTabs) => [...prevTabs, newTab]);
    setActiveTab(newTab.id);
  }, [config]);

  const handleCopy = useCallback(
    (item: T) => {
      const initialContent = { ...item } as T;
      const newTab: TabItem<T> = {
        id: `${item.id}copy`,
        title: `Copie de ${config.getItemCode(item)}`,
        content: initialContent,
        originalContent: initialContent,
        closeable: true,
        mode: 'copy',
        hasUnsavedChanges: false,
      };
      setTabs((prevTabs) => [...prevTabs, newTab]);
      setActiveTab(newTab.id);
    },
    [config]
  );

  const handleEdit = useCallback(
    (item: T) => {
      const initialContent = { ...item };
      const viewTab = findViewTab(item.id);
      if (viewTab) {
        setTabs((prevTabs) =>
          prevTabs.map((tab) =>
            tab.id === viewTab.id
              ? {
                  ...tab,
                  title: config.getItemCode(item),
                  mode: 'edit' as const,
                  content: initialContent,
                  originalContent: initialContent,
                  hasUnsavedChanges: false,
                }
              : tab
          )
        );
        setActiveTab(viewTab.id);
      } else {
        const existingTab = tabs.find((tab) => tab.id === `${item.id}edit`);
        if (existingTab) {
          setActiveTab(existingTab.id);
        } else {
          const newTab: TabItem<T> = {
            id: `${item.id}edit`,
            title: config.getItemCode(item),
            content: initialContent,
            originalContent: initialContent,
            closeable: true,
            mode: 'edit',
            hasUnsavedChanges: false,
          };
          setTabs((prevTabs) => [...prevTabs, newTab]);
          setActiveTab(newTab.id);
        }
      }
    },
    [tabs, config, findViewTab]
  );

  const handleView = useCallback(
    (item: T) => {
      const initialContent = { ...item };
      const existingTab = tabs.find((tab) => tab.id === item.id + 'view');
      if (existingTab) {
        setActiveTab(existingTab.id);
      } else {
        const newTab: TabItem<T> = {
          id: item.id + 'view',
          title: config.getItemCode(item),
          content: initialContent,
          originalContent: initialContent,
          closeable: true,
          mode: 'view',
          hasUnsavedChanges: false,
        };
        setTabs((prevTabs) => [...prevTabs, newTab]);
        setActiveTab(newTab.id);
      }
    },
    [tabs, config]
  );

  const handleCancel = useCallback(
    (tabId: string, forceClose : boolean = false) => {
      const tabToClose = tabs.find((tab) => tab.id === tabId);
      if (!forceClose && tabToClose?.hasUnsavedChanges) {
        tabToCloseRef.current = tabId;
        pendingAction.current = 'close';
        setShowConfirmDialog(true);
        return;
      }
      setTabs((prevTabs) => prevTabs.filter((tab) => tab.id !== tabId));
      setActiveTab('list');
    },
    [tabs]
  );

  const updateListTabTitle = useCallback((newTitle: string) => {
    setTabs((prevTabs) =>
      prevTabs.map((tab) => (tab.id === 'list' ? { ...tab, title: newTitle } : tab))
    );
  }, []);


  return {
    tabs,
    activeTab,
    handleTabClose,
    handleTabChange,
    handleTabAdd,
    handleEdit,
    handleView,
    handleCancel,
    handleCopy,
    updateListTabTitle,
    setTabHasUnsavedChanges,
    showConfirmDialog,
    setShowConfirmDialog,
    handleConfirmDialogAction,
    updateTabContent,
    checkUnsavedChanges,
  };
}
