/**
 * App
 * Coordinates the main frontend workspace, including dashboard navigation,
 * atlas and model pickers, and the editor shell that binds the core hooks and views.
 */
import React, { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useEditor } from './hooks/useEditor';
import EditorViewport from './components/layout/EditorViewport';
import EditorSidebar from './components/layout/EditorSidebar';
import HistoryDashboard from './components/layout/HistoryDashboard';
import AtlasManagement from './components/layout/AtlasManagement';
import AppNavbar from './components/layout/AppNavbar';
import { Book, Check, X, FileCode2, Plus, User } from 'lucide-react';
import { useAnnotations } from './hooks/useAnnotations';
import { client } from './api/generated/client.gen';
import { getAtlases } from './api/generated/index';
import { Button } from './components/ui/button';
import { useLanguage } from './context/LanguageContext';
import { useMessageDialog } from './hooks/useMessageDialog';
import { API_BASE_URL, buildApiUrl } from './utils/api';
import { extractDroppedModelFiles } from './utils/modelUploadValidation';

client.setConfig({ baseURL: API_BASE_URL });

const GLOBAL_ANNOTATOR_STORAGE_KEY = 'globalAnnotatorName';
const DEFAULT_EDITOR_SIDEBAR_MIN_WIDTH = 860;
const DEFAULT_EDITOR_SIDEBAR_MAX_WIDTH = 1400;

export default function App() {
  const { t, lang, setLang } = useLanguage();
  const { alert: showAlert, confirm } = useMessageDialog();
  const [globalAnnotatorName, setGlobalAnnotatorName] = useState(() => localStorage.getItem(GLOBAL_ANNOTATOR_STORAGE_KEY) || '');
  const [pendingAnnotatorName, setPendingAnnotatorName] = useState(() => localStorage.getItem(GLOBAL_ANNOTATOR_STORAGE_KEY) || '');
  const [showAnnotatorDialog, setShowAnnotatorDialog] = useState(true);
  const { state, refs, actions } = useEditor({ defaultAnnotatorName: globalAnnotatorName });
  const { annotations: rawAnnotations, isLoading: isHistoryLoading } = useAnnotations();

  const [atlases, setAtlases] = useState([]);
  const [showAtlasPicker, setShowAtlasPicker] = useState(false);
  const [showModelPicker, setShowModelPicker] = useState(false);
  const [tempSelectedAtlasId, setTempSelectedAtlasId] = useState(null);
  const [filterAtlasId, setFilterAtlasId] = useState('all');
  const [view, setView] = useState('dashboard');
  const [sidebarWidth, setSidebarWidth] = useState(() =>
    Math.min(Math.max(window.innerWidth * 0.45, DEFAULT_EDITOR_SIDEBAR_MIN_WIDTH), DEFAULT_EDITOR_SIDEBAR_MAX_WIDTH)
  );
  const [isResizing, setIsResizing] = useState(false);
  const [modelToAnnotate, setModelToAnnotate] = useState(null);
  const [isEditorUploadDragActive, setIsEditorUploadDragActive] = useState(false);
  const [isModelPickerDropActive, setIsModelPickerDropActive] = useState(false);

  const fileInputRef = useRef(null);

  const handleAnnotatorDialogSave = useCallback(() => {
    const cleanName = pendingAnnotatorName.trim();
    if (!cleanName) {
      return;
    }

    setGlobalAnnotatorName(cleanName);
    localStorage.setItem(GLOBAL_ANNOTATOR_STORAGE_KEY, cleanName);
    setPendingAnnotatorName(cleanName);
    setShowAnnotatorDialog(false);
  }, [pendingAnnotatorName]);

  const openAnnotatorDialog = useCallback(() => {
    setPendingAnnotatorName(globalAnnotatorName);
    setShowAnnotatorDialog(true);
  }, [globalAnnotatorName]);

  const { data: modelsData } = useQuery({
    queryKey: ['models'],
    queryFn: async () => {
      const r = await fetch(buildApiUrl('/api/models'));
      if (!r.ok) throw new Error('Failed to load models');
      return r.json();
    },
  });

  const refreshAtlases = useCallback(async () => {
    try {
      const { data, error } = await getAtlases();
      if (error) throw error;

      const atlasData = data || [];
      setAtlases(atlasData);

      if (!tempSelectedAtlasId) {
        const def = atlasData.find(a => a.je_vychozi);
        if (def) setTempSelectedAtlasId(def.id);
      }
    } catch (e) {
      console.error('Failed to load atlases:', e);
    }
  }, [tempSelectedAtlasId]);

  useEffect(() => {
    refreshAtlases();
  }, [refreshAtlases]);

  const filteredAnnotations = useMemo(() => {
    const list = rawAnnotations?.data?.annotations ||
      rawAnnotations?.annotations ||
      rawAnnotations?.data ||
      (Array.isArray(rawAnnotations) ? rawAnnotations : []);

    if (filterAtlasId === 'all') return list;

    return list.filter(ann => String(ann.atlasId) === String(filterAtlasId));
  }, [rawAnnotations, filterAtlasId]);

  const startResizing = useCallback(() => setIsResizing(true), []);
  const stopResizing = useCallback(() => setIsResizing(false), []);
  const resize = useCallback((e) => {
    if (isResizing) {
      let newWidth = window.innerWidth - e.clientX;
      if (newWidth < DEFAULT_EDITOR_SIDEBAR_MIN_WIDTH) newWidth = DEFAULT_EDITOR_SIDEBAR_MIN_WIDTH;
      if (newWidth > DEFAULT_EDITOR_SIDEBAR_MAX_WIDTH) newWidth = DEFAULT_EDITOR_SIDEBAR_MAX_WIDTH;
      setSidebarWidth(newWidth);
    }
  }, [isResizing]);

  useEffect(() => {
    window.addEventListener("mousemove", resize);
    window.addEventListener("mouseup", stopResizing);
    return () => {
      window.removeEventListener("mousemove", resize);
      window.removeEventListener("mouseup", stopResizing);
    };
  }, [resize, stopResizing]);

  const handleViewChange = async (newView) => {
    if (view === 'editor' && state.isDirty) {
      const shouldDiscard = await confirm({
        title: t('dialogConfirmTitle'),
        message: t('unsavedChanges'),
        tone: 'warning',
        confirmLabel: t('dialogDiscardAction'),
      });
      if (!shouldDiscard) {
        return;
      } else {
        await actions.handleResetForm(true);
      }
    }
    setView(newView);
  };

  const handleStartNewEditing = async () => {
    if (view === 'editor' && state.isDirty) {
      const shouldDiscard = await confirm({
        title: t('dialogConfirmTitle'),
        message: t('confirmDiscard'),
        tone: 'warning',
        confirmLabel: t('dialogDiscardAction'),
      });
      if (!shouldDiscard) return;
    }

    setShowAtlasPicker(true);
  };

  const handleAtlasConfirmed = async () => {
    if (!tempSelectedAtlasId) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('selectAtlas'),
        tone: 'warning',
      });
      return;
    }
    setShowAtlasPicker(false);
    
    if (modelToAnnotate) {
      if (actions.handleResetForm) await actions.handleResetForm(true);
      if (actions.setAtlasId) actions.setAtlasId(tempSelectedAtlasId);
      actions.loadModelFromModel(modelToAnnotate);
      setModelToAnnotate(null);
      setView('editor');
    } else {
      setShowModelPicker(true);
    }
  };

  const handleModelConfirmed = (selectedModel) => {
    setShowModelPicker(false);
    if (actions.handleResetForm) actions.handleResetForm(true);
    if (actions.setAtlasId) actions.setAtlasId(tempSelectedAtlasId);
    
    if (selectedModel) {
      actions.loadModelFromModel(selectedModel);
    } else {
      setTimeout(() => fileInputRef.current?.click(), 150);
    }
    setView('editor');
  };

  const handleContinueAnnotation = async (item) => {
    if (typeof item === 'string') {
      await actions.loadModelFromHistory(item);
      setView('editor');
    } else if (item && item.id) {
      console.warn('handleContinueAnnotation called with model, use handleAddAnnotationToModel instead');
    }
  };

  const handleAddAnnotationToModel = (model) => {
    setModelToAnnotate(model);
    setShowAtlasPicker(true);
  };

  const handleUploadDragState = useCallback((event, setter, active) => {
    event.preventDefault();
    event.stopPropagation();
    setter(active);
  }, []);

  const handleDroppedModelFolder = useCallback(async (event, setter) => {
    event.preventDefault();
    event.stopPropagation();
    setter(false);
    const files = await extractDroppedModelFiles(event);
    await actions.handleSelectedFiles(files);
    setView('editor');
    setShowModelPicker(false);
  }, [actions, setView]);

  return (
    <div className={`h-screen w-screen flex flex-col bg-slate-50 overflow-hidden text-slate-900 font-sans ${isResizing ? 'cursor-col-resize select-none' : ''}`}>
      <input type="file" ref={fileInputRef} onChange={actions.handleFileUpload} accept=".obj,.mtl,.jpg,.png,.jpeg" multiple directory="" webkitdirectory="" className="hidden" />
      <AppNavbar
        view={view}
        setView={handleViewChange}
        annotatorName={globalAnnotatorName}
        onEditAnnotator={openAnnotatorDialog}
      />
      <main className="flex-1 overflow-hidden relative">
        {view === 'dashboard' && (
          <div className="h-full flex flex-col">
            <div className="flex-1 overflow-y-auto">
              <HistoryDashboard
                customData={filteredAnnotations}
                currentAnnotatorName={globalAnnotatorName}
                selectedAtlasId={filterAtlasId}
                onSelectModel={handleContinueAnnotation}
                onAddNew={handleStartNewEditing}
                onAddAnnotation={handleAddAnnotationToModel}
                isLoading={isHistoryLoading}
                atlases={atlases}
                filterAtlasId={filterAtlasId}
                setFilterAtlasId={setFilterAtlasId}
              />
            </div>
          </div>
        )}
        {view === 'atlases' && (
          <div className="h-full overflow-y-auto">
            <AtlasManagement atlases={atlases} onRefresh={refreshAtlases} />
          </div>
        )}
        {view === 'editor' && (
          <div className="flex h-full w-full overflow-hidden bg-white">
            <div className="flex-1 h-full relative overflow-hidden bg-slate-950" style={{ pointerEvents: isResizing ? 'none' : 'auto' }}>
              <EditorViewport state={state} actions={actions} refs={refs} />
              {!state.modelUrl && (
                <div
                  onDragEnter={(event) => handleUploadDragState(event, setIsEditorUploadDragActive, true)}
                  onDragOver={(event) => handleUploadDragState(event, setIsEditorUploadDragActive, true)}
                  onDragLeave={(event) => handleUploadDragState(event, setIsEditorUploadDragActive, false)}
                  onDrop={(event) => handleDroppedModelFolder(event, setIsEditorUploadDragActive)}
                  className={`absolute inset-0 z-30 backdrop-blur-xl flex flex-col items-center justify-center text-white p-4 transition-all ${isEditorUploadDragActive ? 'bg-slate-800/90 ring-4 ring-blue-400/40' : 'bg-slate-900/80'}`}
                >
                  <p className="text-2xl font-light mb-4">{t('editorReady')}</p>
                  <Button onClick={handleStartNewEditing} className="bg-white text-slate-900 font-bold px-10 py-6 rounded-2xl shadow-2xl transition-all">
                    {t('uploadObj')}
                  </Button>
                  <p className="mt-4 text-center text-xs font-bold uppercase tracking-[0.16em] text-slate-300 max-w-md">
                    {isEditorUploadDragActive ? t('dropModelFolderHere') : t('uploadHint')}
                  </p>
                </div>
              )}
            </div>
            <EditorSidebar state={state} actions={actions} width={sidebarWidth} onResizeStart={startResizing} />
          </div>
        )}
      </main>

      {showAtlasPicker && (
        <div className="fixed inset-0 z-[100] flex items-center justify-center bg-slate-900/60 backdrop-blur-md p-4">
          <div className="bg-white rounded-[40px] shadow-2xl w-full max-w-xl overflow-hidden flex flex-col animate-in zoom-in duration-300">
            <div className="p-8 border-b flex justify-between items-center bg-slate-50">
              <div className="flex items-center gap-4">
                <div className="w-12 h-12 bg-blue-600 text-white rounded-2xl flex items-center justify-center shadow-lg"><Book size={28} /></div>
                <h3 className="text-2xl font-black text-slate-800 tracking-tight">{t('selectAtlas')}</h3>
              </div>
              <button onClick={() => setShowAtlasPicker(false)} className="p-2 hover:bg-slate-200 rounded-full transition-colors"><X size={24} /></button>
            </div>
            <div className="p-8 max-h-[50vh] overflow-y-auto space-y-3">
              {atlases.map((atlas) => (
                <div
                  key={atlas.id}
                  onClick={() => setTempSelectedAtlasId(atlas.id)}
                  className={`p-5 rounded-3xl border-2 cursor-pointer transition-all flex items-center justify-between group ${tempSelectedAtlasId === atlas.id ? 'border-blue-600 bg-blue-50/50 shadow-inner' : 'border-slate-100 hover:border-blue-200'
                    }`}
                >
                  <h4 className={`font-bold text-lg ${tempSelectedAtlasId === atlas.id ? 'text-blue-700' : 'text-slate-700'}`}>
                    {lang === 'cs' ? atlas.nazev_cs : atlas.nazev_en}
                  </h4>
                  <div className={`w-8 h-8 rounded-full border-2 flex items-center justify-center transition-all ${tempSelectedAtlasId === atlas.id ? 'bg-blue-600 border-blue-600 text-white' : 'border-slate-200 text-transparent'}`}>
                    <Check size={18} strokeWidth={3} />
                  </div>
                </div>
              ))}
            </div>
            <div className="p-8 bg-slate-50 border-t flex gap-4">
              <Button onClick={() => setShowAtlasPicker(false)} variant="outline" className="flex-1 py-8 font-bold">{t('cancel')}</Button>
              <Button onClick={handleAtlasConfirmed} className="flex-[2] bg-blue-600 hover:bg-blue-700 text-white font-black text-lg py-8 shadow-xl transition-all">
                {t('proceedToUpload')}
              </Button>
            </div>
          </div>
        </div>
      )}

      {showModelPicker && (
        <div className="fixed inset-0 z-[100] flex items-center justify-center bg-slate-900/60 backdrop-blur-md p-4">
          <div className="bg-white rounded-[40px] shadow-2xl w-full max-w-2xl overflow-hidden flex flex-col animate-in zoom-in duration-300">
            <div className="p-8 border-b flex justify-between items-center bg-slate-50">
              <div className="flex items-center gap-4">
                <div className="w-12 h-12 bg-purple-600 text-white rounded-2xl flex items-center justify-center shadow-lg"><FileCode2 size={28} /></div>
                <h3 className="text-2xl font-black text-slate-800 tracking-tight">{t('selectModel')}</h3>
              </div>
              <button onClick={() => setShowModelPicker(false)} className="p-2 hover:bg-slate-200 rounded-full transition-colors"><X size={24} /></button>
            </div>
            <div className="p-8 max-h-[60vh] overflow-y-auto">
              <div className="grid grid-cols-1 gap-4">
                {modelsData?.map((model) => (
                  <div
                    key={model.id}
                    onClick={() => handleModelConfirmed(model)}
                    className="p-6 rounded-3xl border-2 border-slate-100 hover:border-purple-400 cursor-pointer transition-all flex items-center justify-between group bg-white hover:bg-purple-50/50"
                  >
                    <div className="flex items-center gap-4">
                      <div className="w-12 h-12 bg-purple-100 rounded-2xl flex items-center justify-center">
                        <FileCode2 size={24} className="text-purple-600" />
                      </div>
                      <div>
                        <h4 className="font-bold text-lg text-slate-800">{model.external_id}</h4>
                        <p className="text-sm text-slate-500">{new Date(model.created_at).toLocaleDateString()}</p>
                        <div className="flex items-center gap-2 mt-1">
                          {model.model_path && <span className="text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full">OBJ</span>}
                          {model.mtl_path && <span className="text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full">MTL</span>}
                          {model.texture_path && <span className="text-xs bg-green-100 text-green-700 px-2 py-1 rounded-full">TEX</span>}
                          {model.has_annotations && <span className="text-xs bg-blue-100 text-blue-700 px-2 py-1 rounded-full">{t('hasAnnotations')}</span>}
                        </div>
                      </div>
                    </div>
                    <div className="w-8 h-8 rounded-full border-2 border-slate-200 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all">
                      <Check size={18} strokeWidth={3} className="text-purple-600" />
                    </div>
                  </div>
                ))}

                <div
                  onClick={() => handleModelConfirmed(null)}
                  onDragEnter={(event) => handleUploadDragState(event, setIsModelPickerDropActive, true)}
                  onDragOver={(event) => handleUploadDragState(event, setIsModelPickerDropActive, true)}
                  onDragLeave={(event) => handleUploadDragState(event, setIsModelPickerDropActive, false)}
                  onDrop={(event) => handleDroppedModelFolder(event, setIsModelPickerDropActive)}
                  className={`p-6 rounded-3xl border-2 border-dashed cursor-pointer transition-all flex flex-col items-center justify-center min-h-[120px] group ${isModelPickerDropActive ? 'border-blue-500 bg-blue-50/80 ring-4 ring-blue-200/60' : 'border-slate-300 bg-slate-50/50 hover:border-blue-400 hover:bg-blue-50/50'}`}
                >
                  <div className="w-16 h-16 bg-slate-100 group-hover:bg-blue-100 rounded-3xl flex items-center justify-center mb-4 transition-colors">
                    <Plus size={32} className="text-slate-400 group-hover:text-blue-600" />
                  </div>
                  <span className="font-black text-slate-700 group-hover:text-blue-700 uppercase text-sm tracking-wider">{t('uploadNewModel')}</span>
                  <span className="mt-2 text-center text-[11px] font-bold uppercase tracking-[0.14em] text-slate-500">
                    {isModelPickerDropActive ? t('dropModelFolderHere') : t('uploadHint')}
                  </span>
                </div>
              </div>
            </div>
            <div className="p-8 bg-slate-50 border-t flex gap-4">
              <Button onClick={() => setShowModelPicker(false)} variant="outline" className="flex-1 py-6 font-bold">{t('cancel')}</Button>
            </div>
          </div>
        </div>
      )}

      {showAnnotatorDialog && (
        <div className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/70 backdrop-blur-md p-4">
          <div className="w-full max-w-lg overflow-hidden rounded-[36px] bg-white shadow-2xl animate-in zoom-in duration-300">
            <div className="border-b bg-slate-50 p-8 flex items-center justify-between">
              <div className="flex items-center gap-4">
                <div className="flex h-14 w-14 items-center justify-center rounded-3xl bg-blue-600 text-white shadow-lg">
                  <User size={28} />
                </div>
                <div>
                  <h3 className="text-2xl font-black tracking-tight text-slate-900">{t('globalSignatureTitle')}</h3>
                  <p className="mt-1 text-sm text-slate-500">{t('globalSignatureDescription')}</p>
                </div>
              </div>
              <div className="flex bg-slate-100 p-1 rounded-lg border border-slate-200">
                <button
                  onClick={() => setLang('cs')}
                  className={`px-3 py-1 rounded-md text-[10px] font-black transition-all ${lang === 'cs' ? 'bg-white text-blue-600 shadow-sm' : 'text-slate-400 hover:text-slate-600'
                    }`}
                >
                  CZ
                </button>
                <button
                  onClick={() => setLang('en')}
                  className={`px-3 py-1 rounded-md text-[10px] font-black transition-all ${lang === 'en' ? 'bg-white text-blue-600 shadow-sm' : 'text-slate-400 hover:text-slate-600'
                    }`}
                >
                  EN
                </button>
              </div>
            </div>
            <div className="p-8">
              <label className="mb-3 block text-[11px] font-black uppercase tracking-[0.18em] text-slate-500">
                {t('signature')}
              </label>
              <input
                type="text"
                value={pendingAnnotatorName}
                onChange={(e) => setPendingAnnotatorName(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' && pendingAnnotatorName.trim()) {
                    handleAnnotatorDialogSave();
                  }
                }}
                placeholder={t('globalSignaturePlaceholder')}
                autoFocus
                className="h-14 w-full rounded-2xl border-2 border-slate-200 px-4 text-base font-medium outline-none transition-all focus:border-blue-500"
              />
            </div>
            <div className="flex gap-4 border-t bg-slate-50 p-8">
              <Button
                onClick={handleAnnotatorDialogSave}
                disabled={!pendingAnnotatorName.trim()}
                className="flex-1 bg-blue-600 py-7 text-base font-black text-white shadow-xl transition-all hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-slate-300"
              >
                {t('globalSignatureAction')}
              </Button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}