// ============================================================
// HomeContent — 首页三列正文布局 + HomeProvider（Context + Provider + Hook）
// 可拖拽调整三栏宽度，所有数据请求在登录后发送
// ============================================================

import React, { useState, useCallback, useRef, useEffect, useMemo } from 'react';
import { theme as antTheme, Empty } from 'antd';

import { useAppContext } from '@/app/providers/AppProvider';
import type { ModelsListResponseBody } from '@/modules/home/controllers/model-api';
import type { TaskInfoItemResponseBody } from '@/modules/home/controllers/task-api';
import { LeftPanel } from './left/LeftPanel';
import { CenterPanel } from './center/CenterPanel';
import { RightPanel } from './right/RightPanel';

import { Typography } from 'antd';

import { HomeContext } from '../stores/HomeContext';

const { Text } = Typography;

// ---------- 常量 ----------

/** 左列最小/默认宽度 */
const LEFT_MIN = 400;
const LEFT_DEFAULT = 750;
/** 右列最小/默认宽度 */
const RIGHT_MIN = 300;
const RIGHT_DEFAULT = 480;
/** 中列最小宽度 */
const CENTER_MIN = 300;
/** 拖拽分隔条宽度 */
const DIVIDER_WIDTH = 6;
/** 布局固定消耗：左右 padding(12*2) + 两个分隔条(6*2) */
const LAYOUT_OVERHEAD = 36; // 24 + 12

// ---------- 组件 ----------

export function HomeContent() {
   const { token } = antTheme.useToken();
   const { isLoggedIn } = useAppContext();

   // ======== HomeContext 状态 ========

   const [selectedModel, setSelectedModel] = useState<ModelsListResponseBody | null>(null);
   const [selectedTask, setSelectedTask] = useState<TaskInfoItemResponseBody | null>(null);
   const [taskPage, setTaskPage] = useState(1);
   const [taskPageSize, setTaskPageSize] = useState(10);
   const [isLeftCollapsed, setIsLeftCollapsed] = useState(false);

   const toggleLeftCollapsed = useCallback(() => {
      setIsLeftCollapsed((v) => !v);
   }, []);

   const handleSetSelectedModel = useCallback(
       (model: ModelsListResponseBody | null) => {
          setSelectedModel(model);
          setSelectedTask(null);
       },
       [],
   );

   const handleSetSelectedTask = useCallback(
       (task: TaskInfoItemResponseBody | null) => {
          setSelectedTask(task);
       },
       [],
   );

   const contextValue = useMemo(() => ({
      selectedModel,
      setSelectedModel: handleSetSelectedModel,
      taskPage,
      taskPageSize,
      setTaskPage,
      setTaskPageSize,
      selectedTask,
      setSelectedTask: handleSetSelectedTask,
      isLeftCollapsed,
      toggleLeftCollapsed,
   }), [
      selectedModel,
      handleSetSelectedModel,
      taskPage,
      taskPageSize,
      selectedTask,
      handleSetSelectedTask,
      isLeftCollapsed,
      toggleLeftCollapsed,
   ]);

   // ======== 拖拽调整列宽 ========

   const [leftWidth, setLeftWidth] = useState(LEFT_DEFAULT);
   const [rightWidth, setRightWidth] = useState(RIGHT_DEFAULT);
   const containerRef = useRef<HTMLDivElement>(null);

   // 拖拽状态
   const [dragging, setDragging] = useState<'left' | 'right' | null>(null);
   // 分隔条 hover 状态
   const [hoveredDivider, setHoveredDivider] = useState<'left' | 'right' | null>(null);
   const dragState = useRef<{
      startX: number;
      startWidth: number;
   }>({ startX: 0, startWidth: 0 });

   // 用 ref 追踪最新列宽，避免拖拽 mousemove 闭包中读到过期值
   const leftWidthRef = useRef(leftWidth);
   const rightWidthRef = useRef(rightWidth);
   const draggingRef = useRef(dragging);
   // 上一次重算时的容器宽度（用于三栏等比缩放时反推中列宽度）
   const prevWidthRef = useRef(0);
   // 标记拖拽期间被跳过的重算，拖拽结束后补算
   const needsRecalcRef = useRef(false);

   useEffect(() => {
      leftWidthRef.current = leftWidth;
      rightWidthRef.current = rightWidth;
      draggingRef.current = dragging;
   }, [leftWidth, rightWidth, dragging]);

   const handleDividerMouseDown = (side: 'left' | 'right') => (e: React.MouseEvent) => {
      e.preventDefault();
      // eslint-disable-next-line react-hooks/refs
      dragState.current = { startX: e.clientX, startWidth: side === 'left' ? leftWidth : rightWidth };
      setDragging(side);
   };

   useEffect(() => {
      const handleMouseMove = (e: MouseEvent) => {
         if (!dragging) return;

         const containerEl = containerRef.current;
         if (!containerEl) return;
         const containerWidth = containerEl.clientWidth;
         const ds = dragState.current;
         const delta = e.clientX - ds.startX;

         if (dragging === 'left') {
            // 左列最大宽度 = 容器宽 - 固定消耗 - 中列最小宽 - 右列当前宽
            // 确保中列至少保留 CENTER_MIN、右列不被挤出视口
            const maxLeft = containerWidth - LAYOUT_OVERHEAD - CENTER_MIN - rightWidthRef.current;
            const newWidth = Math.max(LEFT_MIN, Math.min(maxLeft, ds.startWidth + delta));
            setLeftWidth(newWidth);
         } else {
            // 右列最大宽度同理：不能把中列挤到 CENTER_MIN 以下
            const maxRight = containerWidth - LAYOUT_OVERHEAD - CENTER_MIN - leftWidthRef.current;
            const newWidth = Math.max(RIGHT_MIN, Math.min(maxRight, ds.startWidth - delta));
            setRightWidth(newWidth);
         }
      };

      const handleMouseUp = () => {
         draggingRef.current = null; // 即时清除 —— 优先级高于 React 状态，避免 ResizeObserver 被永久阻塞
         setDragging(null);
      };

      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);

      return () => {
         document.removeEventListener('mousemove', handleMouseMove);
         document.removeEventListener('mouseup', handleMouseUp);
      };
   }, [dragging]);

   // ======== 视口缩放时按比例自动调整面板宽度 ========

   /**
    * 三栏等比缩放核心（ResizeObserver + window.resize 共用）。
    *
    * 旧算法只保持 left:right 比例，中列被动吸收剩余空间——窗口从半屏拉到全屏时
    * 新增宽度全部给了左右栏，中列反而被挤到 CENTER_MIN。
    *
    * 新算法通过 prevWidthRef 反推中列上次实际宽度，三栏按各自占比分配空间变化。
    */
   const recalcLayout = useCallback(() => {
      if (draggingRef.current) {
         needsRecalcRef.current = true;
         return;
      }

      requestAnimationFrame(() => {
         if (draggingRef.current) {
            needsRecalcRef.current = true;
            return;
         }

         const el = containerRef.current;
         if (!el) return;
         const containerWidth = el.clientWidth;
         const available = containerWidth - LAYOUT_OVERHEAD; // 三栏可用总宽

         const currentLeft = leftWidthRef.current;
         const currentRight = rightWidthRef.current;

         // ---- 反推中列上次实际宽度（基于上一次记录的容器宽度） ----
         const prevWidth = prevWidthRef.current || containerWidth; // 首次调用用当前值
         const currentCenter = Math.max(
            CENTER_MIN,
            prevWidth - LAYOUT_OVERHEAD - currentLeft - currentRight,
         );
         const total = currentLeft + currentCenter + currentRight;
         if (total <= 0) return;

         // ---- 三栏按比例分配可用空间 ----
         let newLeft = Math.round(available * (currentLeft / total));
         let newCenter = Math.round(available * (currentCenter / total));
         let newRight = available - newLeft - newCenter;

         // ---- 最小值约束（左/右优先保底，中列弹性收缩） ----
         if (newLeft < LEFT_MIN) {
            newLeft = LEFT_MIN;
            // 差额从右侧扣（先扣中列，再扣右列）
            const deficit = available - newLeft - newCenter - newRight;
            newCenter = Math.max(CENTER_MIN, newCenter + deficit);
         }
         if (newRight < RIGHT_MIN) {
            newRight = RIGHT_MIN;
            const deficit = available - newLeft - newCenter - newRight;
            newCenter = Math.max(CENTER_MIN, newCenter + deficit);
         }

         // 更新 ref（在 setState 之前，确保并发回调读到最新值）
         leftWidthRef.current = newLeft;
         rightWidthRef.current = newRight;
         prevWidthRef.current = containerWidth;

         if (newLeft !== currentLeft) setLeftWidth(newLeft);
         if (newRight !== currentRight) setRightWidth(newRight);
      });
   }, []);

   // 主触发器：ResizeObserver（响应容器尺寸变化）
   useEffect(() => {
      const el = containerRef.current;
      if (!el) return;

      const observer = new ResizeObserver(() => recalcLayout());
      observer.observe(el);
      return () => observer.disconnect();
   }, [recalcLayout]);

   // 兜底触发器：window.resize（捕获 ResizeObserver 可能遗漏的快照/最大化/分屏事件）
   useEffect(() => {
      const handleResize = () => recalcLayout();
      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
   }, [recalcLayout]);

   // 拖拽结束后，若 ResizeObserver 曾因拖拽跳过重算，立即补算
   useEffect(() => {
      if (dragging !== null) return;
      if (!needsRecalcRef.current) return;

      needsRecalcRef.current = false;
      // 使用 requestAnimationFrame 确保 React 已完成 commit 再读取 DOM
      requestAnimationFrame(() => recalcLayout());
   }, [dragging, recalcLayout]);

   // ======== 分隔条样式工厂 ========

   const dividerStyle = (side: 'left' | 'right'): React.CSSProperties => {
      const isActive = dragging === side;
      const isHovered = hoveredDivider === side;
      return {
         width: DIVIDER_WIDTH,
         flexShrink: 0,
         cursor: 'col-resize',
         background: isActive
             ? token.colorPrimary
             : isHovered
                 ? `${token.colorPrimary}60`
                 : token.colorBorderSecondary,
         position: 'relative' as const,
         zIndex: 10,
         display: 'flex',
         alignItems: 'center',
         justifyContent: 'center',
         transition: 'background 0.15s linear',
      };
   };

   // ======== 未登录提示 ========

   if (!isLoggedIn) {
      return (
          <HomeContext.Provider value={contextValue}>
             <div
                 style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    flex: 1,
                    background: token.colorBgLayout,
                 }}
             >
                <Empty
                    description={
                       <Text type="secondary">
                          请先登录后再使用首页功能
                       </Text>
                    }
                    image={Empty.PRESENTED_IMAGE_SIMPLE}
                />
             </div>
          </HomeContext.Provider>
      );
   }

   // ======== 三列布局（可拖拽） ========

   return (
       <HomeContext.Provider value={contextValue}>
          <div
              ref={containerRef}
              style={{
                 display: 'flex',
                 padding: 12,
                 gap: 0,
                 flex: 1,
                 overflow: 'hidden',
                 background: token.colorBgLayout,
                 cursor: !!dragging ? 'col-resize' : undefined,
                 userSelect: !!dragging ? 'none' : undefined,
              }}
          >
             {/* 左列 */}
             {!isLeftCollapsed && (
                 <>
                    <div style={{ width: leftWidth, overflow: 'hidden', flexShrink: 0 }}>
                       <LeftPanel />
                    </div>

                    {/* 左分隔条 */}
                    <div
                        onMouseDown={handleDividerMouseDown('left')}
                        style={dividerStyle('left')}
                        onMouseEnter={() => setHoveredDivider('left')}
                        onMouseLeave={() => setHoveredDivider(null)}
                    >
                       {/* 拖拽手柄竖线 */}
                       <div style={{
                          width: 2,
                          height: 32,
                          borderRadius: 1,
                          background: dragging === 'left'
                              ? '#fff'
                              : hoveredDivider === 'left'
                                  ? token.colorPrimary
                                  : token.colorBorder,
                          transition: 'background 0.15s linear',
                       }} />
                    </div>
                 </>
             )}

             {/* 中列 */}
             <div style={{ flex: 1, overflow: 'hidden', minWidth: CENTER_MIN }}>
                <CenterPanel />
             </div>

             {/* 右分隔条 */}
             <div
                 onMouseDown={handleDividerMouseDown('right')}
                 style={dividerStyle('right')}
                 onMouseEnter={() => setHoveredDivider('right')}
                 onMouseLeave={() => setHoveredDivider(null)}
             >
                {/* 拖拽手柄竖线 */}
                <div style={{
                   width: 2,
                   height: 32,
                   borderRadius: 1,
                   background: dragging === 'right'
                       ? '#fff'
                       : hoveredDivider === 'right'
                           ? token.colorPrimary
                           : token.colorBorder,
                   transition: 'background 0.15s linear',
                }} />
             </div>

             {/* 右列 */}
             <div style={{ width: rightWidth, overflow: 'hidden', flexShrink: 0 }}>
                <RightPanel />
             </div>
          </div>
       </HomeContext.Provider>
   );
}
