/**
 * App.tsx – Root Application Component
 *
 * Assembles the entire application:
 * - Wraps everything in ErrorBoundary to catch unhandled render errors
 * - Uses useOnlineStatus for network detection (Req 11.3)
 * - Dual-panel desktop layout via ResizableLayout with 40/60 split (Req 12.1)
 * - Left panel: ChatPanel (fixed)
 * - Right panel: Dynamically switches between ExportRecordList (default) and EditorPanel (when document is opened)
 * - Uses React.lazy for code splitting of non-critical panels (Req 13.2, 13.8)
 *
 * Layout Structure:
 * ┌─────────────────────────────────────────────────────────────┐
 * │                         Toolbar                             │
 * ├──────────────────────┬──────────────────────────────────────┤
 * │  Chat Panel          │  Export Records List (default)       │
 * │  (Left 40%)          │  OR                                  │
 * │                      │  Editor Panel (when document opened) │
 * │                      │  (Right 60%)                         │
 * └──────────────────────┴──────────────────────────────────────┘
 *
 * Requirements: 4.1, 4.6, 11.3, 12.1, 13.2, 13.8
 *
 * @module App
 */

import React, { useCallback, useState, memo, lazy, Suspense, useMemo } from 'react';
import { ConfigProvider, Alert, Button, Drawer, Spin } from 'antd';
import { MessageOutlined } from '@ant-design/icons';
import zhCN from 'antd/locale/zh_CN';

import { ErrorBoundary } from './components/common';
import ResizableLayout from './components/Layout/ResizableLayout';
import { useUIStore } from './stores/uiStore';

// ── Lazy-loaded panel components (Req 13.2, 13.8) ────────────────────────────
// These non-first-screen panels are split into separate chunks by Vite,
// reducing the initial JS bundle size.
const ChatPanel = lazy(() => import('./components/ChatPanel/ChatPanel'));
const EditorPanel = lazy(() => import('./components/EditorPanel/EditorPanel'));
const ExportRecordList = lazy(() =>
  import('./components/ExportRecordList').then((m) => ({ default: m.ExportRecordList }))
);
const SessionList = lazy(() =>
  import('./components/SessionList').then((m) => ({ default: m.SessionList }))
);

import { useOnlineStatus } from './hooks/useOnlineStatus';

// ── Panel loading fallback ────────────────────────────────────────────────────

/**
 * Lightweight fallback rendered by <Suspense> while a lazy panel chunk is
 * being fetched. Keeps the layout stable by filling the full available area.
 */
const PanelFallback: React.FC = memo(() => (
  <div
    style={{
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      height: '100%',
      width: '100%',
      backgroundColor: '#ffffff',
    }}
    aria-busy="true"
    aria-label="加载中"
  >
    <Spin size="default" tip="加载中…">
      <div style={{ minHeight: 50 }} />
    </Spin>
  </div>
));
PanelFallback.displayName = 'PanelFallback';

// ── Styles ────────────────────────────────────────────────────────────────────

const appStyle: React.CSSProperties = {
  display: 'flex',
  flexDirection: 'column',
  height: '100vh',
  width: '100vw',
  overflow: 'hidden',
  backgroundColor: '#f5f5f5',
};

const offlineBannerStyle: React.CSSProperties = {
  flexShrink: 0,
};

const mainContentStyle: React.CSSProperties = {
  flex: 1,
  overflow: 'hidden',
  display: 'flex',
  flexDirection: 'column',
};

// ── Subcomponents ─────────────────────────────────────────────────────────────

/**
 * Offline banner shown at the top when network is unavailable.
 */
const OfflineBanner: React.FC = memo(() => (
  <div style={offlineBannerStyle}>
    <Alert
      banner
      type="warning"
      message="您当前处于离线状态，部分功能可能不可用"
      showIcon
      data-testid="offline-banner"
    />
  </div>
));
OfflineBanner.displayName = 'OfflineBanner';

// ── App Component ─────────────────────────────────────────────────────────────

/**
 * App
 *
 * The top-level React component. Handles layout orchestration.
 *
 * Uses a fixed dual-panel desktop layout with ResizableLayout (40% left / 60% right).
 * The left panel shows ChatPanel (fixed), and the right panel dynamically switches:
 * - Default: ExportRecordList (shows export history)
 * - When document opened: EditorPanel (shows document for preview and editing)
 */
const App: React.FC = () => {
  // ── Network status (Req 11.3) ────────────────────────────────────────────
  const isOnline = useOnlineStatus();

  // ── Editor state ──────────────────────────────────────────────────────────
  const previewDocumentId = useUIStore((state) => state.previewDocumentId);
  const previewDocumentName = useUIStore((state) => state.previewDocumentName);
  const closeDocumentPreview = useUIStore((state) => state.closeDocumentPreview);
  
  // ── Session history drawer ────────────────────────────────────────────────
  const [sessionListOpen, setSessionListOpen] = useState(false);
  
  // ── User ID (in a real app, this would come from auth context) ───────────
  const currentUserId = 'default-user';
  
  /** Stable callback to close the session drawer */
  const handleCloseSessionList = useCallback(() => setSessionListOpen(false), []);
  /** Stable callback to open the session drawer */
  const handleOpenSessionList = useCallback(() => setSessionListOpen(true), []);

  /**
   * Handle close editor button click
   */
  const handleCloseEditor = useCallback(() => {
    closeDocumentPreview();
  }, [closeDocumentPreview]);

  // ── Panels ────────────────────────────────────────────────────────────────
  // Each panel is wrapped in <Suspense> so the lazy chunk loads independently.
  // useMemo ensures the JSX elements are stable references and don't cause
  // Suspense to remount unnecessarily on parent re-renders (Req 13.7).

  const leftPanel = useMemo(() => {
    // Always show chat panel on the left
    return (
      <Suspense fallback={<PanelFallback />}>
        <ChatPanel />
      </Suspense>
    );
  }, []);
  
  const rightPanel = useMemo(() => {
    // If a document is being previewed, show EditorPanel
    // Otherwise show ExportRecordList (default)
    if (previewDocumentId) {
      return (
        <Suspense fallback={<PanelFallback />}>
          <EditorPanel 
            documentId={previewDocumentId}
            initialDocumentName={previewDocumentName}
            onClose={handleCloseEditor}
          />
        </Suspense>
      );
    }
    
    // Default: show export records list
    return (
      <Suspense fallback={<PanelFallback />}>
        <ExportRecordList userId={currentUserId} />
      </Suspense>
    );
  }, [previewDocumentId, previewDocumentName, handleCloseEditor, currentUserId]);

  // ── Session history drawer ────────────────────────────────────────────────
  const sessionListDrawer = sessionListOpen ? (
    <Drawer
      title="会话历史"
      placement="left"
      width={360}
      open
      onClose={handleCloseSessionList}
      styles={{ body: { padding: 0, display: 'flex', flexDirection: 'column' } }}
      data-testid="session-list-drawer"
    >
      <Suspense fallback={<PanelFallback />}>
        <SessionList onSessionLoad={handleCloseSessionList} />
      </Suspense>
    </Drawer>
  ) : null;

  // ── Session history toggle button ─────────────────────────────────────────
  const sessionListButton = (
    <Button
      type="text"
      icon={<MessageOutlined />}
      onClick={handleOpenSessionList}
      title="会话历史"
      aria-label="打开会话历史"
      data-testid="open-session-list-button"
    />
  );

  // ── Desktop dual-panel layout (Req 12.1) ──────────────────────────────────
  return (
    <ConfigProvider locale={zhCN}>
      <ErrorBoundary>
        <div style={appStyle} data-testid="app">
          {/* Offline banner (Req 11.3) */}
          {!isOnline && <OfflineBanner />}

          {/* Session history drawer */}
          {sessionListDrawer}

          {/* Main two-panel layout */}
          <div style={mainContentStyle}>
            {/* Toolbar row with session history toggle */}
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                padding: '2px 8px',
                borderBottom: '1px solid #f0f0f0',
                backgroundColor: '#ffffff',
                flexShrink: 0,
                height: 40,
                gap: 8,
              }}
              data-testid="app-toolbar"
            >
              {sessionListButton}
            </div>

            {/* Resizable dual-panel layout (Req 4.1–4.5, 12.1) */}
            <div style={{ flex: 1, overflow: 'hidden' }}>
              <ResizableLayout
                leftPanel={leftPanel}
                rightPanel={rightPanel}
                defaultLeftWidth={40}
                minWidth={300}
              />
            </div>
          </div>
        </div>
      </ErrorBoundary>
    </ConfigProvider>
  );
};

export default App;
