import React, { useState, useEffect } from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
import { Chat } from './components/Chat/Chat';
import { Constructor } from './components/Constructor/Constructor';
import { Archive } from './components/Archive/Archive';
import { AdminPanel } from './components/AdminPanel/AdminPanel';
import { RightSidebar } from './components/RightSidebar/RightSidebar';
import { AuthForm } from './components/Auth/AuthForm';
import { ShareModal } from './components/Archive/ShareModal';
import { Settings } from './components/Settings/Settings';
import { useAuth } from './contexts/AuthContext';
import { useTheme } from './contexts/ThemeContext';
import { api } from './api/client';
import { Moon, Sun, LogOut } from 'lucide-react';

export interface Estimate {
  id: string;
  number: string;
  direction: { code: string; name: string; shortName: string };
  objectName: string;
  customer: string;
  executor: string;
  items: EstimateItem[];
  totals: EstimateTotal[];
  totalFieldWorks?: number;
  totalOfficeWorks?: number;
  totalLaboratory?: number;
  subtotal?: number;
  regionalCoef?: number;
  regionalCoefDocRef?: string;
  inflationIndex?: number;
  inflationDocRef?: string;
  companyCoef?: number;
  companyCoefDocRef?: string;
  executorCoef?: number;
  executorCoefDocRef?: string;
  totalWithoutVat?: number;
  vatRate?: number;
  vatAmount?: number;
  totalWithVat?: number;
  withVat?: boolean;
  status: string;
}

export interface EstimateItem {
  id: string;
  orderNumber: number;
  sectionType: string;
  workName: string;
  justification?: string;
  basePrice: number;
  quantity: number;
  unit?: string;
  coef1?: number;
  coef1Desc?: string;
  coef2?: number;
  coef2Desc?: string;
  coef3?: number;
  coef3Desc?: string;
  totalPrice: number;
}

export interface EstimateTotal {
  id: string;
  orderNumber: number;
  label: string;
  description?: string;
  resultValue: number;
}

export interface ExtractedData {
  direction?: string;
  customer?: string;
  objectName?: string;
  executor?: string;
  works?: Array<{
    name: string;
    volume: number;
    unit: string;
    priceItemId?: string;
    justification?: string;
  }>;
}

export interface EstimateWithShared extends Estimate {
  sharedWithMe?: boolean;
}

function App() {
  const { user, loading, logout } = useAuth();
  const { theme, toggleTheme } = useTheme();
  const [showArchive, setShowArchive] = useState(false);
  const [manualMode, setManualMode] = useState(false);
  const [currentEstimate, setCurrentEstimate] = useState<EstimateWithShared | null>(null);
  const [extractedData, setExtractedData] = useState<ExtractedData | null>(null);
  const [chatSessionId, setChatSessionId] = useState<string | null>(null);
  const [showShareModal, setShowShareModal] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [settings, setSettings] = useState<any>(null);
  const [sidebarExpanded, setSidebarExpanded] = useState(false);
  const [externalMessageTrigger, setExternalMessageTrigger] = useState(0);

  useEffect(() => {
    if (showSettings) {
      api.getSettings().then(setSettings).catch(() => setSettings(null));
    }
  }, [showSettings]);

  useEffect(() => {
    if (!user || currentEstimate) return;
    let cancelled = false;
    const loadOrCreateEstimate = async () => {
      try {
        const list = await api.getEstimates();
        const lastId = typeof localStorage !== 'undefined' ? localStorage.getItem('smeta-last-estimate-id') : null;
        if (list?.length) {
          const toOpen = list.find((e: { id: string }) => e.id === lastId) ?? list[0];
          const full = await api.getEstimate(toOpen.id);
          if (!cancelled) setCurrentEstimate(full);
        } else {
          const directions = await api.getSurveyDirections();
          const firstDir = directions?.[0];
          const estimate = await api.createEstimate({
            directionCode: firstDir?.code ?? 'geodesy',
            objectName: 'Новая смета',
            customer: '—',
          });
          if (!cancelled) setCurrentEstimate(estimate);
        }
      } catch (err) {
        console.error('Failed to load initial estimate:', err);
      }
    };
    loadOrCreateEstimate();
    return () => { cancelled = true; };
  }, [user, currentEstimate]);

  useEffect(() => {
    setExtractedData(null);
  }, [currentEstimate?.id]);

  useEffect(() => {
    if (currentEstimate?.id && typeof localStorage !== 'undefined') {
      localStorage.setItem('smeta-last-estimate-id', currentEstimate.id);
    }
  }, [currentEstimate?.id]);

  if (loading) {
    return (
      <div className="h-screen flex items-center justify-center bg-slate-100 dark:bg-slate-900">
        <div className="w-8 h-8 border-2 border-primary-600 border-t-transparent rounded-full animate-spin" />
      </div>
    );
  }
  if (!user) {
    return <AuthForm />;
  }

  /** Заполняет текущую смету (справа) данными из загруженного в чат файла. Обновляет только смету, чат не трогает. */
  const fillCurrentEstimateFromData = async (estimateId: string, data: ExtractedData) => {
    try {
      const updates: { objectName?: string; customer?: string; executor?: string } = {};
      if (data.objectName?.trim()) updates.objectName = data.objectName.trim();
      if (data.customer?.trim()) updates.customer = data.customer.trim();
      if (data.executor?.trim()) updates.executor = data.executor.trim();
      if (Object.keys(updates).length > 0) {
        await api.updateEstimate(estimateId, updates);
      }
      if (data.works?.length) {
        for (const work of data.works) {
          await api.addEstimateItem(estimateId, {
            sectionType: 'field',
            workName: work.name,
            justification: work.justification,
            basePrice: 0,
            quantity: work.volume,
            unit: work.unit,
          });
        }
      }
      if (Object.keys(updates).length > 0 || (data.works?.length ?? 0) > 0) {
        try {
          await api.recalculateEstimate(estimateId);
        } catch (_) {
          // Пересчёт мог упасть (например vatRate null) — всё равно подтягиваем сохранённые данные
        }
        const fullEstimate = await api.getEstimate(estimateId);
        setCurrentEstimate(fullEstimate);
      }
    } catch (err) {
      console.error('Failed to fill estimate from file:', err);
    }
  };

  const handleExtractedData = (data: ExtractedData) => {
    setExtractedData(prev => {
      const next: ExtractedData = prev ? { ...prev } : {};
      if (data.direction != null && data.direction !== '') next.direction = data.direction;
      if (data.customer != null && data.customer !== '') next.customer = data.customer;
      if (data.objectName != null && data.objectName !== '') next.objectName = data.objectName;
      if (data.executor != null && data.executor !== '') next.executor = data.executor;
      if (data.works != null && data.works.length > 0) next.works = data.works;
      return next;
    });
  };

  const handleCreateEstimate = async () => {
    if (!extractedData?.direction || !extractedData?.customer || !extractedData?.objectName) return;
    try {
      const estimate = await api.createEstimate({
        directionCode: extractedData.direction,
        customer: extractedData.customer,
        objectName: extractedData.objectName,
        executor: extractedData.executor,
      });
      if (extractedData.works?.length) {
        for (const work of extractedData.works) {
          await api.addEstimateItem(estimate.id, {
            sectionType: 'field',
            workName: work.name,
            justification: work.justification,
            basePrice: 0,
            quantity: work.volume,
            unit: work.unit,
          });
        }
        await api.recalculateEstimate(estimate.id);
      }
      const fullEstimate = await api.getEstimate(estimate.id);
      setCurrentEstimate(fullEstimate);
      if (chatSessionId) {
        await api.updateChatSession(chatSessionId, { estimateId: fullEstimate.id });
      }
    } catch (error) {
      console.error('Failed to create estimate:', error);
    }
  };

  const handleEstimateUpdate = async (estimateId: string) => {
    try {
      const estimate = await api.getEstimate(estimateId);
      setCurrentEstimate(estimate);
    } catch (error) {
      console.error('Failed to update estimate:', error);
    }
  };

  const handleCreateManualEstimate = async (data: {
    directionCode: string;
    objectName: string;
    customer: string;
    executor?: string;
  }) => {
    try {
      const estimate = await api.createEstimate(data);
      const fullEstimate = await api.getEstimate(estimate.id);
      setCurrentEstimate(fullEstimate);
    } catch (error) {
      console.error('Failed to create estimate:', error);
    }
  };

  return (
    <Routes>
      <Route path="/geo" element={<AdminPanel />} />
      <Route path="/*" element={
        <div className="flex flex-col h-screen bg-slate-100 dark:bg-slate-900">
          <header className="flex items-center justify-between gap-4 px-4 py-2 bg-white dark:bg-slate-800 border-b border-slate-200 dark:border-slate-700 shrink-0">
            <div className="flex items-center gap-2 min-w-0">
              <span className="font-semibold text-slate-800 dark:text-slate-200 truncate">Портал смет</span>
            </div>
            <div className="flex items-center gap-2 shrink-0">
              <button
                type="button"
                onClick={() => toggleTheme()}
                className="min-w-[40px] min-h-[40px] flex items-center justify-center p-2 text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg transition-colors cursor-pointer select-none"
                title={theme === 'dark' ? 'Светлая тема' : 'Тёмная тема'}
                aria-label={theme === 'dark' ? 'Включить светлую тему' : 'Включить тёмную тему'}
              >
                {theme === 'dark' ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
              </button>
              <div className="h-6 w-px bg-slate-200 dark:bg-slate-600" />
              <div className="flex items-center gap-2">
                <span
                  className="text-sm text-slate-600 dark:text-slate-300 truncate max-w-[180px]"
                  title={user.email}
                >
                  {user.name || user.email}
                </span>
                <button
                  type="button"
                  onClick={() => logout()}
                  className="min-w-[40px] min-h-[40px] flex items-center justify-center p-2 text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-slate-800 rounded-lg transition-colors cursor-pointer"
                  title="Выйти"
                >
                  <LogOut className="w-5 h-5" />
                </button>
              </div>
            </div>
          </header>

          <div className="flex-1 flex overflow-hidden">
            <RightSidebar
              expanded={sidebarExpanded}
              onToggle={() => setSidebarExpanded(v => !v)}
              currentEstimate={currentEstimate}
              onOpenEstimate={estimate => {
                setCurrentEstimate(estimate);
                setShowArchive(false);
              }}
              onShowArchive={() => setShowArchive(true)}
              onShowShare={() => setShowShareModal(true)}
              onShowSettings={() => setShowSettings(true)}
            />
            <main className="flex-1 flex overflow-hidden min-w-0 bg-slate-50 dark:bg-slate-800">
              {showArchive ? (
                <div className="flex-1 flex flex-col overflow-hidden">
                  <Archive
                    onOpenEstimate={estimate => {
                      setCurrentEstimate(estimate);
                      setShowArchive(false);
                    }}
                    onClose={() => setShowArchive(false)}
                  />
                </div>
              ) : manualMode ? (
                <div className="flex-1 flex flex-col overflow-hidden">
                  <Constructor
                    estimate={currentEstimate}
                    extractedData={extractedData}
                    onEstimateUpdate={handleEstimateUpdate}
                    manualMode={true}
                    onSetManualMode={setManualMode}
                    onCreateManualEstimate={handleCreateManualEstimate}
                    onAskAboutSelection={async (question, contextText) => {
                      if (!chatSessionId) return;
                      try {
                        await api.sendMessage(chatSessionId, `[Вопрос по выделенному]\n\nКонтекст: ${contextText}\n\nВопрос: ${question}`, 'discuss');
                        setExternalMessageTrigger(t => t + 1);
                      } catch (e) {
                        console.error('Failed to ask about selection:', e);
                      }
                    }}
                  />
                </div>
              ) : (
                <>
                  <div className="w-[400px] border-r border-slate-200 dark:border-slate-700 flex flex-col bg-slate-50 dark:bg-slate-800/50 shrink-0">
                    <Chat
                      currentEstimate={currentEstimate}
                      onExtractedData={handleExtractedData}
                      onCreateEstimate={handleCreateEstimate}
                      onFillEstimate={fillCurrentEstimateFromData}
                      onSessionReady={setChatSessionId}
                      extractedData={extractedData}
                      externalMessageTrigger={externalMessageTrigger}
                    />
                  </div>

                  <div className="flex-1 flex flex-col overflow-hidden">
                    <Constructor
                      estimate={currentEstimate}
                      extractedData={extractedData}
                      onEstimateUpdate={handleEstimateUpdate}
                      manualMode={false}
                      onSetManualMode={setManualMode}
                      onCreateManualEstimate={handleCreateManualEstimate}
                      onAskAboutSelection={async (question, contextText) => {
                        if (!chatSessionId) return;
                        try {
                          await api.sendMessage(chatSessionId, `[Вопрос по выделенному]\n\nКонтекст: ${contextText}\n\nВопрос: ${question}`, 'discuss');
                          setExternalMessageTrigger(t => t + 1);
                        } catch (e) {
                          console.error('Failed to ask about selection:', e);
                        }
                      }}
                    />
                  </div>
                </>
              )}
            </main>
          </div>

          {showShareModal && currentEstimate && !currentEstimate.sharedWithMe && (
            <ShareModal
              estimate={currentEstimate}
              onClose={() => setShowShareModal(false)}
              onShared={() => {}}
            />
          )}

          {showSettings && (
            <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={() => setShowSettings(false)}>
              <div className="bg-white dark:bg-slate-800 rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-hidden" onClick={e => e.stopPropagation()}>
                <Settings
                  settings={settings}
                  onClose={() => setShowSettings(false)}
                  onSave={() => { api.getSettings().then(setSettings); }}
                />
              </div>
            </div>
          )}
        </div>
      } />
    </Routes>
  );
}

export default App;
