/**
 * 侧边栏面板组件
 * 插件的主操作界面，固定在浏览器右上角
 * 包含：职位信息卡片、自动填写按钮、简历管理、填写进度等功能区域
 */

import { useState, useEffect, useRef, useCallback } from "react"
import { getCookieValue } from "~utils/cookie"
import { getCustomizeResume } from "~api/aiApi"
import { handleAutoFillCommon } from "~handlers/handleAutoFillCommon"
import { handleAutoFillBeisen } from "~handlers/handleAutoFillBeisen"
import { scanPageFields, extractNonResumeFields, printFieldStats } from "~lib/fillStats"
import type { TitleStat } from "~lib/fillStats"
import type { MatchedFormField, ResumeData, JobInfo } from "~lib/types"
import logoImg from "data-base64:~/../assets/logo-offerpai.png"
import "./SidebarPanel.scss"

/** 侧边栏面板的 Props */
interface SidebarPanelProps {
  /** 当前标签页的来源链接 */
  sourceUrl: string
  /** 岗位信息（由 sidebar 层查询后传入） */
  jobInfo: JobInfo | null
  /** 关闭面板的回调函数 */
  onClose: () => void
}

export function SidebarPanel({ sourceUrl, jobInfo, onClose }: SidebarPanelProps) {
  /** 是否已登录（有 Token） */
  const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null)
  /** 是否正在执行自动填写 */
  const [filling, setFilling] = useState(false)
  /** 页面语言类型：中文 / 英文 */
  const [pageLang, setPageLang] = useState<"zh" | "en">("zh")
  /** 是否为职位申请表单页面 */
  const [isFormPage, setIsFormPage] = useState(false)
  /** 匹配到的表单字段列表 */
  const [formFields, setFormFields] = useState<MatchedFormField[]>([])
  /** 当前使用的简历数据 */
  const [resumeData, setResumeData] = useState<ResumeData | null>(null)
  /** 自动填写流程是否已完成（控制模拟提交按钮可用） */
  const [fillCompleted, setFillCompleted] = useState(false)
  /** 页面字段扫描统计结果（用于面板底部展示已填/待填字段列表） */
  const [fieldStats, setFieldStats] = useState<TitleStat[]>([])
  /** 顶部状态文字 */
  const [headerStatus, setHeaderStatus] = useState<string>("")

  /** 是否启用字段更新时自动滚动到该字段，模拟跟踪（常量开关，方便调试关闭） */
  const ENABLE_AUTO_SCROLL_TO_UPDATED = true

  /** 循环扫描定时器引用 */
  const scanIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
  /** 上一次扫描结果快照（用于对比哪些字段刚刚更新） */
  const prevFieldSnapshotRef = useRef<Map<Element, string>>(new Map())
  /** 字段列表容器 ref（用于滚动） */
  const fieldListRef = useRef<HTMLDivElement | null>(null)
  /** 最新一次更新的字段 inputElement（用于定位滚动目标） */
  const [lastUpdatedFieldEl, setLastUpdatedFieldEl] = useState<Element | null>(null)
  /** 是否显示"助手已记住的表单"弹窗 */
  const [showCacheModal, setShowCacheModal] = useState(false)
  /** 弹窗中编辑的表单数据（从 localStorage 读取后在弹窗内编辑） */
  const [cacheModalData, setCacheModalData] = useState<any[] | null>(null)

  /** 面板是否收起（收起时只显示 logo 圆圈） */
  const [collapsed, setCollapsed] = useState(false)
  /** 拖拽位置偏移量（相对于初始位置） */
  const [dragOffset, setDragOffset] = useState<{ x: number; y: number }>({ x: 0, y: 0 })
  /** 是否已经被拖动过（用于判断是否显示拖拽提示气泡） */
  const [hasDragged, setHasDragged] = useState(false)
  /** 拖拽提示：收起状态已提示过 */
  const collapsedTooltipShownRef = useRef(false)
  /** 拖拽提示：展开状态已提示过 */
  const expandedTooltipShownRef = useRef(false)
  /** 是否正在显示拖拽提示气泡 */
  const [showDragTooltip, setShowDragTooltip] = useState(false)
  /** 拖拽提示气泡定时器 */
  const dragTooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  /** 面板容器 ref（用于拖拽） */
  const containerRef = useRef<HTMLDivElement | null>(null)
  /** 拖拽状态 ref */
  const dragStateRef = useRef<{ isDragging: boolean; startX: number; startY: number; startOffsetX: number; startOffsetY: number; longPressTimer: ReturnType<typeof setTimeout> | null; isLongPress: boolean }>({
    isDragging: false, startX: 0, startY: 0, startOffsetX: 0, startOffsetY: 0, longPressTimer: null, isLongPress: false
  })

  /** 停止当前循环扫描 */
  const stopScanLoop = () => {
    if (scanIntervalRef.current) {
      clearInterval(scanIntervalRef.current)
      scanIntervalRef.current = null
    }
  }

  /** 对比前后快照，找出刚刚变为已填写的字段 */
  const findUpdatedField = (newStats: TitleStat[]): Element | null => {
    const prevMap = prevFieldSnapshotRef.current
    let updatedEl: Element | null = null
    const newMap = new Map<Element, string>()

    for (const ts of newStats) {
      for (const f of ts.fields) {
        if (!f.inputElement) continue
        const newColor = f.color
        newMap.set(f.inputElement, newColor)
        const prevColor = prevMap.get(f.inputElement)
        // 从非绿变成绿/greenTwo → 刚刚被填写（取最后一个变化的）
        if (prevColor && prevColor !== "green" && prevColor !== "greenTwo" && (newColor === "green" || newColor === "greenTwo")) {
          updatedEl = f.inputElement
        }
      }
    }

    prevFieldSnapshotRef.current = newMap
    return updatedEl
  }

  /** 开启循环扫描（每秒执行一次） */
  const startScanLoop = (params: { siteMode?: "beisen"; sectionResults?: any[]; expandedResults?: any[] }) => {
    stopScanLoop()
    const hasFullData = !!(params.sectionResults && params.expandedResults)
    // 立即执行一次
    const stats = scanPageFields(params)
    setFieldStats(stats)
    findUpdatedField(stats) // 初始化快照，不滚动
    if (hasFullData) handleSaveUserInput()
    // 每秒循环
    scanIntervalRef.current = setInterval(() => {
      const s = scanPageFields(params)
      setFieldStats(s)
      if (ENABLE_AUTO_SCROLL_TO_UPDATED) {
        const updatedEl = findUpdatedField(s)
        if (updatedEl) setLastUpdatedFieldEl(updatedEl)
      }
      if (hasFullData) handleSaveUserInput()
    }, 1000)
  }

  /** 组件卸载时清理定时器 */
  useEffect(() => {
    return () => { stopScanLoop() }
  }, [])

  /** 页面加载时检测是否有足够的输入框，显示"准备就绪" */
  useEffect(() => {
    const checkInputs = () => {
      // 注意：需要查询宿主页面的 DOM，而不是 Shadow DOM 内部
      const hostDoc = document.getRootNode() === document ? document : (document.getRootNode() as ShadowRoot).ownerDocument
      const inputs = hostDoc.querySelectorAll("input:not([type='hidden']):not([type='submit']):not([type='button']):not([type='file']), textarea")
      if (inputs.length > 2) {
        setHeaderStatus("准备就绪，请点击开始填写")
        return true
      }
      return false
    }
    // 立即检测一次
    if (checkInputs()) return
    // 页面可能还在加载，延迟重试几次
    const timer1 = setTimeout(checkInputs, 500)
    const timer2 = setTimeout(checkInputs, 1500)
    const timer3 = setTimeout(checkInputs, 3000)
    return () => {
      clearTimeout(timer1)
      clearTimeout(timer2)
      clearTimeout(timer3)
    }
  }, [])

  /** 字段更新时自动滚动字段列表到对应项 */
  useEffect(() => {
    if (!ENABLE_AUTO_SCROLL_TO_UPDATED || !lastUpdatedFieldEl || !fieldListRef.current) return
    // 计算该字段在渲染中的全局索引（按渲染顺序：按大标题 → 按段 → 按字段）
    let globalIdx = 0
    let targetIdx = -1
    for (const ts of fieldStats) {
      if (ts.fields.length === 0) continue
      if (ts.isExpType && ts.segmentCount > 1) {
        for (let sIdx = 0; sIdx < ts.segmentCount; sIdx++) {
          const segFields = ts.fields.filter((f) => f.segmentIndex === sIdx)
          for (const f of segFields) {
            if (f.inputElement === lastUpdatedFieldEl) { targetIdx = globalIdx }
            globalIdx++
          }
        }
      } else {
        for (const f of ts.fields) {
          if (f.inputElement === lastUpdatedFieldEl) { targetIdx = globalIdx }
          globalIdx++
        }
      }
      if (targetIdx >= 0) break
    }
    if (targetIdx >= 0) {
      const targetItem = fieldListRef.current.querySelector(`[data-field-idx="${targetIdx}"]`)
      if (targetItem) {
        // 滚动到居中位置再往上偏移30px，让下一个字段更接近视口中心（模拟实时跟踪效果）
        const container = fieldListRef.current
        const itemRect = targetItem.getBoundingClientRect()
        const containerRect = container.getBoundingClientRect()
        const offsetTop = itemRect.top - containerRect.top + container.scrollTop
        const targetScroll = offsetTop - container.clientHeight / 2 + itemRect.height / 2 + 50
        container.scrollTo({ top: Math.max(0, targetScroll), behavior: "smooth" })
      }
    }
    setLastUpdatedFieldEl(null)
  }, [lastUpdatedFieldEl])

  /** 页面加载时检查 Token，有岗位信息则查询定制简历 */
  useEffect(() => {
    getCookieValue("Token").then((token) => {
      console.log("[OfferPie] SidebarPanel 获取到的 Token:", token)
      setIsLoggedIn(!!token)

      // 有 Token 且有岗位 ID 时，查询定制简历
      if (token && jobInfo?.id) {
        getCustomizeResume(jobInfo.id).then((resumeRes: any) => {
          console.log("[OfferPie] 定制简历数据:", resumeRes)
          // 接口返回的 resume 字段映射为 main
          const mappedData: ResumeData = {
            main: resumeRes.resume || {},
            education: resumeRes.education || [],
            work: resumeRes.work || [],
            internship: resumeRes.internship || [],
            project: resumeRes.project || [],
            competition: resumeRes.competition || [],
          }
          setResumeData(mappedData)
        }).catch((err) => {
          console.warn("[OfferPie] 查询定制简历失败:", err)
        })
      }
    })
  }, [jobInfo?.id])

  /**
   * 自动填写按钮点击处理
   * 内部根据当前页面域名判断走哪个处理模式：
   *   - handleAutoFillBeisen：北森模式（域名包含 zhiye.com，如 avicsz.zhiye.com）
   *   - handleAutoFillCommon：通用模式（其他所有网站）
   *   - 后续特殊网站会在此处加条件分支（如根据 domain 或 jobInfo 来源判断）
   */
  /** 显示全页面填写遮罩层（黑色半透明 + 提示文字 + 闪烁圆点动画） */
  function showFillingOverlay() {
    // 防止重复创建
    if (document.getElementById("offerpie-filling-overlay")) return

    const overlay = document.createElement("div")
    overlay.id = "offerpie-filling-overlay"
    Object.assign(overlay.style, {
      position: "fixed",
      top: "0",
      left: "0",
      width: "100vw",
      height: "100vh",
      backgroundColor: "rgba(0, 0, 0, 0.05)",
      zIndex: "2147483646",
      display: "flex",
      alignItems: "center",
      justifyContent: "center",
      pointerEvents: "auto",
    })

    // 提示文字容器
    const content = document.createElement("div")
    Object.assign(content.style, {
      display: "flex",
      alignItems: "center",
      gap: "4px",
      userSelect: "none",
    })

    // 文字
    const text = document.createElement("span")
    text.textContent = "填写中..."
    Object.assign(text.style, {
      color: "rgba(255,255,255, 1)",
      background:"rgba(107, 114, 128, 0.5)",
      height:"40px",
      "line-height":"40px",
      width:"370px",
      "text-align":"center",
      "border-radius":"4px",
      fontSize: "18px",
      fontWeight: "500",
      letterSpacing: "1px",
    })
    content.appendChild(text)

    // 5个按顺序消失闪烁的圆点
    for (let i = 0; i < 5; i++) {
      const dot = document.createElement("span")
      Object.assign(dot.style, {
        display: "inline-block",
        width: "6px",
        height: "6px",
        borderRadius: "50%",
        backgroundColor: "rgba(82, 202, 209, 0.3)",
        marginLeft: i === 0 ? "6px" : "3px",
        animation: `offerpie-dot-blink 1.5s ${i * 0.3}s infinite`,
      })
      content.appendChild(dot)
    }

    overlay.appendChild(content)

    // 注入关键帧动画样式（按顺序消失闪烁）
    if (!document.getElementById("offerpie-dot-style")) {
      const style = document.createElement("style")
      style.id = "offerpie-dot-style"
      style.textContent = `
        @keyframes offerpie-dot-blink {
          0%, 20% { opacity: 1; }
          40%, 100% { opacity: 0; }
        }
      `
      document.head.appendChild(style)
    }

    document.body.appendChild(overlay)
  }

  /** 移除全页面填写遮罩层（先显示完成提示，2秒后再移除） */
  function hideFillingOverlay() {
    const overlay = document.getElementById("offerpie-filling-overlay")
    if (!overlay) return
    // 找到提示文字元素，更新为完成状态
    const text = overlay.querySelector("span") as HTMLElement | null
    if (text) {
      text.textContent = "填写完成，请检查"
      text.style.background = "rgba(118, 213, 132, 0.5)"
    }
    // 隐藏闪烁圆点
    const dots = overlay.querySelectorAll("span:not(:first-child)")
    dots.forEach((dot) => {
      ;(dot as HTMLElement).style.display = "none"
    })
    // 2秒后移除遮罩层
    setTimeout(() => {
      overlay.remove()
    }, 2000)
  }

  /**
   * 自动填写入口
   * 根据当前页面域名分发到不同的处理器：
   * - 北森系统（zhiye.com）→ handleAutoFillBeisen：适配北森 Phoenix UI 组件库的特殊 DOM 结构
   * - 其他招聘网站 → handleAutoFillCommon：通用模式，基于 DOM 差异对比适配各种 UI 框架
   *
   * 两个处理器内部流程一致：
   * 1. extractDomStructure 提取页面 DOM 树结构
   * 2. detectPageLanguage 检测中/英文
   * 3. isJobApplicationForm 判断是否为求职表单页（非表单页直接跳过）
   * 4. 获取简历数据（接口优先，无接口时 fallback 到 mock 数据）
   * 5. locateExperienceSections 定位5大经历区块（教育/工作/实习/项目/竞赛）
   * 6. expandExperienceSections 对比简历段数，点击添加按钮补足经历段
   * 7. 逐段匹配字段 + 填充（走 fillMatchedField 统一入口）
   * 8. matchMainFields 匹配非经历区域字段（姓名/手机/邮箱等）并填充
   * 9. 收集剩余未匹配的空白字段（unmatchedFields），后续交给 AI 生成答案
   *
   * 填写完成后更新组件状态，供后续"保存用户修改"和"AI补填"使用
   */
  const handleAutoFill = async () => {
    setFilling(true)
    setHeaderStatus("正在填写表单，请勿跳转页面")
    // 停止之前的循环扫描（如果有）
    stopScanLoop()
    // 操作中打开遮罩
    showFillingOverlay()
    try {
      // 检测当前页面域名，判断走哪个处理模式
      const currentHost = window.location.hostname
      const isBeisen = currentHost.includes("zhiye.com") // 北森招聘平台域名特征
      const scanSiteMode = isBeisen ? "beisen" as const : undefined

      // 第一次开启循环扫描（不传 sectionResults，阶段A之前就开始展示）
      startScanLoop({ siteMode: scanSiteMode })

      const fillResult = isBeisen
        ? await handleAutoFillBeisen({ resumeData, jobInfo })
        : await handleAutoFillCommon({ resumeData, jobInfo })

      // 将处理器返回的结果同步到组件状态
      setPageLang(fillResult.lang)          // 页面语言（影响后续标签匹配用中文还是英文）
      setIsFormPage(fillResult.isFormPage)   // 是否为表单页（非表单页不显示填写相关 UI）
      if (fillResult.resumeData) setResumeData(fillResult.resumeData) // 更新简历数据（可能从 mock 切换为接口数据）
      setFormFields(fillResult.formFields)   // 已匹配的字段列表（用于后续高亮/状态展示）
      setFillCompleted(true)                 // 标记填写流程已完成，解锁"保存修改"等按钮
      setHeaderStatus("表单填写完成，请检查后提交")
      hideFillingOverlay()                   // 填写完成，移除遮罩

      // 停止第一次循环扫描，开启第二次循环扫描（传入 sectionResults + expandedResults，分段精确）
      startScanLoop({
        siteMode: scanSiteMode,
        sectionResults: fillResult.sectionResults,
        expandedResults: fillResult.expandedResults,
      })
      
    } catch (e) {
      console.error("OfferPie: 自动填写异常", e)
      hideFillingOverlay()                   // 异常时也移除遮罩
    }
    setTimeout(() => setFilling(false), 1000)
  }

  /**
   * 模拟提交：通过 fillStats 扫描页面字段，过滤出 B2 阶段字段数据，更新到缓存
   * 【注意】弹窗打开时不执行，避免覆盖用户正在编辑的数据
   */
  const handleSaveUserInput = () => {
    // 弹窗打开时直接跳过，不更新缓存
    if (showCacheModal) return
    try {
      const cached = localStorage.getItem("offerpie_unfilled_form")
      if (!cached) { alert("未找到缓存数据，请先执行自动填写"); return }

      const cacheData = JSON.parse(cached)

      // 检测当前网站模式
      const currentHost = window.location.hostname
      const siteMode = currentHost.includes("zhiye.com") ? "beisen" as const : undefined

      // 调用 fillStats 扫描页面所有字段
      const titleStats = scanPageFields({ siteMode })

      // 提取非简历格式字段（B2阶段字段）
      const nonResumeData = extractNonResumeFields(titleStats)

      // 更新缓存中的 unfilledFormData
      const oldSections = cacheData.unfilledFormData as any[] || []
      for (const newSec of nonResumeData) {
        const oldSec = oldSections.find((s: any) => s.title === newSec.title)
        if (!oldSec) {
          oldSections.push(newSec)
          continue
        }

        if (newSec.isExperience) {
          const oldSegments = oldSec.formItems as any[][]
          const newSegments = newSec.formItems as any[][]
          for (let sIdx = 0; sIdx < newSegments.length; sIdx++) {
            if (sIdx >= oldSegments.length) {
              oldSegments.push(newSegments[sIdx])
              continue
            }
            const oldFields = oldSegments[sIdx]
            const newFields = newSegments[sIdx]
            for (const newField of newFields) {
              const oldField = oldFields.find((f: any) => f.label === newField.label)
              if (oldField) {
                if (newField.value) oldField.value = newField.value
              } else {
                oldFields.push(newField)
              }
            }
          }
        } else {
          const oldFields = oldSec.formItems as any[]
          const newFields = newSec.formItems as any[]
          for (const newField of newFields) {
            const oldField = oldFields.find((f: any) => f.label === newField.label)
            if (oldField) {
              if (newField.value) oldField.value = newField.value
            } else {
              oldFields.push(newField)
            }
          }
        }
      }

      cacheData.unfilledFormData = oldSections
      cacheData.timestamp = Date.now()
      localStorage.setItem("offerpie_unfilled_form", JSON.stringify(cacheData))

      // 打印所有字段数据
      // console.log("===== OfferPie: handleSaveUserInput 全量字段数据 =====")
      printFieldStats(titleStats)

      // 打印 B2 字段数据
      // console.log("===== OfferPie: handleSaveUserInput B2阶段字段数据 =====")
      // console.log(JSON.stringify(nonResumeData, null, 2))
      // console.log("===== OfferPie: B2字段数据打印完毕 =====")

      const updatedCount = nonResumeData.reduce((sum, sec) => {
        if (sec.isExperience) {
          return sum + (sec.formItems as any[][]).reduce((s, seg) => s + seg.filter((f: any) => f.value).length, 0)
        }
        return sum + (sec.formItems as any[]).filter((f: any) => f.value).length
      }, 0)
      // console.log(`已保存！B2字段中有值的共 ${updatedCount} 个`)
    } catch (e) {
      console.error("[OfferPie] 模拟提交失败:", e)
      console.log("保存失败，请查看控制台")
    }
  }

  /** 打开"助手已记住的表单"弹窗，从 localStorage 加载数据 */
  const openCacheModal = () => {
    try {
      const cached = localStorage.getItem("offerpie_unfilled_form")
      if (!cached) {
        setCacheModalData([])
      } else {
        const cacheData = JSON.parse(cached)
        setCacheModalData(cacheData.unfilledFormData || [])
      }
    } catch {
      setCacheModalData([])
    }
    setShowCacheModal(true)
  }

  /** 关闭弹窗 */
  const closeCacheModal = () => {
    setShowCacheModal(false)
    setCacheModalData(null)
  }

  /** 弹窗内更新某个字段的值 */
  const updateCacheFieldValue = (sectionIdx: number, segIdx: number | null, fieldIdx: number, newValue: string) => {
    if (!cacheModalData) return
    const updated = [...cacheModalData]
    const section = updated[sectionIdx]
    if (segIdx !== null) {
      // 经历类型：formItems 是二维数组
      ;(section.formItems as any[][])[segIdx][fieldIdx].value = newValue
    } else {
      // 普通类型：formItems 是一维数组
      ;(section.formItems as any[])[fieldIdx].value = newValue
    }
    setCacheModalData(updated)
  }

  /** 弹窗内保存数据到 localStorage */
  const saveCacheModalData = () => {
    try {
      const cached = localStorage.getItem("offerpie_unfilled_form")
      const cacheData = cached ? JSON.parse(cached) : {}
      cacheData.unfilledFormData = cacheModalData || []
      cacheData.timestamp = Date.now()
      localStorage.setItem("offerpie_unfilled_form", JSON.stringify(cacheData))
      alert("已保存表单数据")
    } catch (e) {
      console.error("[OfferPie] 保存缓存数据失败:", e)
      alert("保存失败，请查看控制台")
    }
  }

  /** 弹窗内清空缓存数据（带确认） */
  const clearCacheFromModal = () => {
    const confirmed = window.confirm("是否清空已记录的表单数据？清空后下次填简历那些数据需要您一个个手动填。")
    if (!confirmed) return
    localStorage.removeItem("offerpie_unfilled_form")
    setCacheModalData([])
    alert("已清空缓存数据")
    console.log("[OfferPie] 已清空 offerpie_unfilled_form 缓存")
  }

  // ============ 拖拽逻辑 ============

  /** 鼠标按下：启动长按计时 */
  const handleMouseDown = useCallback((e: React.MouseEvent) => {
    // 如果点击的是交互元素（按钮、链接、输入框等），不启动拖拽
    const target = e.target as HTMLElement
    if (target.closest("button, a, input, textarea, select, [role='button'], .op-credits-link, .op-field-item, .op-cache-modal-mask")) return

    e.preventDefault()
    const state = dragStateRef.current
    state.startX = e.clientX
    state.startY = e.clientY
    state.startOffsetX = dragOffset.x
    state.startOffsetY = dragOffset.y
    state.isLongPress = false

    // 300ms 后认为是长按，开始拖拽
    state.longPressTimer = setTimeout(() => {
      state.isLongPress = true
      state.isDragging = true
      if (containerRef.current) {
        containerRef.current.style.cursor = "grabbing"
      }
    }, 300)

    const handleMouseMove = (ev: MouseEvent) => {
      if (!state.isLongPress) {
        // 还没触发长按，如果移动太远就取消（避免误触）
        const dist = Math.abs(ev.clientX - state.startX) + Math.abs(ev.clientY - state.startY)
        if (dist > 5 && state.longPressTimer) {
          clearTimeout(state.longPressTimer)
          state.longPressTimer = null
        }
        return
      }
      // 长按中拖拽
      const dx = ev.clientX - state.startX
      const dy = ev.clientY - state.startY
      setDragOffset({ x: state.startOffsetX + dx, y: state.startOffsetY + dy })
      if (!hasDragged) setHasDragged(true)
    }

    const handleMouseUp = () => {
      if (state.longPressTimer) {
        clearTimeout(state.longPressTimer)
        state.longPressTimer = null
      }
      state.isDragging = false
      if (containerRef.current) {
        containerRef.current.style.cursor = ""
      }
      document.removeEventListener("mousemove", handleMouseMove)
      document.removeEventListener("mouseup", handleMouseUp)
    }

    document.addEventListener("mousemove", handleMouseMove)
    document.addEventListener("mouseup", handleMouseUp)
  }, [dragOffset, hasDragged])

  /** 鼠标移入：显示拖拽提示气泡（收起状态提示1次，展开状态提示1次，拖动过后不再提示） */
  const handleMouseEnter = useCallback(() => {
    if (hasDragged) return
    if (collapsed) {
      if (collapsedTooltipShownRef.current) return
      collapsedTooltipShownRef.current = true
    } else {
      if (expandedTooltipShownRef.current) return
      expandedTooltipShownRef.current = true
    }
    setShowDragTooltip(true)
    if (dragTooltipTimerRef.current) clearTimeout(dragTooltipTimerRef.current)
    dragTooltipTimerRef.current = setTimeout(() => {
      setShowDragTooltip(false)
    }, 3000)
  }, [hasDragged, collapsed])

  /** 组件卸载时清理拖拽提示定时器 */
  useEffect(() => {
    return () => {
      if (dragTooltipTimerRef.current) clearTimeout(dragTooltipTimerRef.current)
    }
  }, [])

  return (
    <div
      className={`op-container ${collapsed ? "op-container--collapsed" : ""}`}
      ref={containerRef}
      style={{ transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)` }}
      onMouseDown={handleMouseDown}
      onMouseEnter={handleMouseEnter}
    >
      {/* 拖拽提示气泡 */}
      {showDragTooltip && (
        <div className="op-drag-tooltip">长按可以拖动助手位置</div>
      )}

      {/* 收起状态：只显示 logo 圆圈 */}
      {collapsed ? (
        <div className="op-collapsed-logo" onClick={() => setCollapsed(false)}>
          <img src={logoImg} alt="OfferPie" width={28} height={31} />
        </div>
      ) : (
        <>
      {/* 填写中遮罩：覆盖整个面板，阻止用户操作 */}
      {filling && <div className="op-filling-overlay" />} 
      <div className="op-inner">
      {/* 新顶部：logo + 提示文字 + 收起箭头 */}
      <div className="op-header">
        <div className="op-header-left">
          <img src={logoImg} alt="OfferPie" width={28} height={31} className="op-header-logo" />
          <span className="op-header-status">{headerStatus}</span>
        </div>
        <button className="op-collapse-btn" onClick={() => setCollapsed(true)}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="6 9 12 15 18 9" />
          </svg>
        </button>
      </div>

      {/* 未登录状态：显示登录提示 */}
      {!isLoggedIn && isLoggedIn !== null && (
        <div className="op-login-prompt">
          <p className="op-login-text">请先前往 Offer派 官网进行登录</p>
          <button
            className="op-login-btn"
            onClick={() => {
              window.open("http://localhost:5173/jobs", "_blank")
            }}
          >
            前往 Offer派
          </button>
        </div>
      )}

      {/* 已登录状态：显示完整功能 */}
      {isLoggedIn && (
        <>
          {/* 职位信息卡片 */}
          <div className="op-job-card">
            
            <div className="op-job-info">
              <div className="op-job-title">{jobInfo?.title || "未匹配到岗位信息"}</div>
              <div className="op-job-meta">
                {jobInfo
                  ? [jobInfo.companyName || jobInfo.companyShortName]
                      .filter(Boolean)
                      .join(" · ") || "—"
                  : "当前页面暂未关联岗位"}
              </div>
            </div>
            {jobInfo?.matchScore != null && (
              <div className="op-match-score">
                <svg width="48" height="48" viewBox="0 0 48 48">
                  <circle cx="24" cy="24" r="20" fill="none" stroke="#f0f0f0" strokeWidth="3" />
                  <circle cx="24" cy="24" r="20" fill="none" stroke="#52CAD1" strokeWidth="3"
                    strokeDasharray={`${(jobInfo.matchScore) / 100 * 2 * Math.PI * 20} ${2 * Math.PI * 20}`}
                    strokeLinecap="round" transform="rotate(-90 24 24)" />
                  <text x="24" y="26" textAnchor="middle" fontSize="13" fontWeight="700" fill="#000">
                    {jobInfo.matchScore}%
                  </text>
                </svg>
              </div>
            )}
          </div>

          {/* 自动填写按钮 */}
          <button className="op-autofill-btn" onClick={handleAutoFill} disabled={filling}>
            {filling ? "填写中..." : "开始填写"}
          </button>

          {/* 使用次数信息 */}
          <div className="op-credits-row">
            <span className="op-credits-link" onClick={openCacheModal}>助手已记住的表单</span>
          </div>

          {/* 简历区域 */}
          <div className="op-section-label">简历</div>
          <div className="op-resume-card">
            <div className="op-resume-avatar">
                {resumeData?.main?.name ? '已优化' : ""}

            </div>
            <div className="op-resume-info">
              <span className="op-resume-name">
                {resumeData?.main?.name || "暂无简历"}.pdf
              </span>
            </div>
          </div>

          {/* 按钮 */}

          {/* 填写进度区域 */}
          <div className="op-progress-row">
            <span className="op-progress-label">填写进度</span>
            <span className="op-progress-value">
              {fieldStats.length > 0
                ? `${fieldStats.reduce((s, t) => s + t.fields.filter((f) => f.color === "green" || f.color === "greenTwo").length, 0)}/${fieldStats.reduce((s, t) => s + t.fields.length, 0)}`
                : "0/0"}
            </span>
          </div>
          <div className="op-progress-bar-bg">
            <div
              className="op-progress-bar-fill"
              style={{
                width: fieldStats.length > 0
                  ? `${Math.round(fieldStats.reduce((s, t) => s + t.fields.filter((f) => f.color === "green" || f.color === "greenTwo").length, 0) / Math.max(fieldStats.reduce((s, t) => s + t.fields.length, 0), 1) * 100)}%`
                  : "0%"
              }}
            />
          </div>

          {/* 已识别字段列表 */}
          {fieldStats.length > 0 && (() => {
            /** 点击字段名时滚动到对应输入框 */
            const scrollToField = (el: Element | null) => {
              if (!el || !(el instanceof HTMLElement)) return
              el.scrollIntoView({ behavior: "smooth", block: "center" })
              // 闪烁高亮提示
              const origOutline = el.style.outline
              el.style.outline = "2px solid #52cad1"
              setTimeout(() => { el.style.outline = origOutline }, 1500)
            }

            return (
              <>
                {/* 已识别字段区域（合并展示所有字段） */}
                <div className="op-field-section">
                  <div className="op-field-section-title">
                    <span className="op-field-section-dot op-field-section-dot--green" />
                    已识别字段
                    <span className="op-field-section-required-count">（剩余必填:{fieldStats.reduce((s, t) => s + t.fields.filter((f) => f.color === "red").length, 0)}）</span>
                  </div>
                  <div className="op-field-list" ref={fieldListRef}>
                    {(() => {
                      let globalIdx = 0
                      return fieldStats.map((ts) => {
                        if (ts.fields.length === 0) return null
                        return (
                          <div key={ts.titleText} className="op-field-group">
                            <div className="op-field-group-title">{ts.titleText}</div>
                            {ts.isExpType && ts.segmentCount > 1
                              ? Array.from({ length: ts.segmentCount }, (_, sIdx) => {
                                  const segFields = ts.fields.filter((f) => f.segmentIndex === sIdx)
                                  if (segFields.length === 0) return null
                                  return (
                                    <div key={sIdx}>
                                      <div className="op-field-group-segment">经历{sIdx + 1}</div>
                                      {segFields.map((f, idx) => {
                                        const isFilled = f.color === "green" || f.color === "greenTwo"
                                        const fieldIdx = globalIdx++
                                        return (
                                          <div
                                            key={`${f.labelText}-${sIdx}-${idx}`}
                                            className="op-field-item"
                                            data-field-idx={fieldIdx}
                                            onClick={() => scrollToField(f.inputElement)}
                                          >
                                            {isFilled ? (
                                              <svg className="op-field-item-icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
                                                <circle cx="12" cy="12" r="11" fill="#52cad1" />
                                                <path d="M7 12.5l3 3 7-7" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
                                              </svg>
                                            ) : (
                                              <svg className="op-field-item-icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
                                                <circle cx="12" cy="12" r="10" stroke="#999" strokeWidth="2.5" />
                                              </svg>
                                            )}
                                            <span className="op-field-item-name">{f.labelText}</span>
                                            {f.color === "red" && <span className="op-field-item-required">必填</span>}
                                          </div>
                                        )
                                      })}
                                    </div>
                                  )
                                })
                              : ts.fields.map((f, idx) => {
                                  const isFilled = f.color === "green" || f.color === "greenTwo"
                                  const fieldIdx = globalIdx++
                                  return (
                                    <div
                                      key={`${f.labelText}-${idx}`}
                                      className="op-field-item"
                                      data-field-idx={fieldIdx}
                                      onClick={() => scrollToField(f.inputElement)}
                                    >
                                      {isFilled ? (
                                        <svg className="op-field-item-icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
                                          <circle cx="12" cy="12" r="11" fill="#52cad1" />
                                          <path d="M7 12.5l3 3 7-7" stroke="#fff" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
                                        </svg>
                                      ) : (
                                        <svg className="op-field-item-icon" width="16" height="16" viewBox="0 0 24 24" fill="none">
                                          <circle cx="12" cy="12" r="10" stroke="#999" strokeWidth="2.5" />
                                        </svg>
                                      )}
                                      <span className="op-field-item-name">{f.labelText}</span>
                                      {f.color === "red" && <span className="op-field-item-required">必填</span>}
                                    </div>
                                  )
                                })
                            }
                          </div>
                        )
                      })
                    })()}
                  </div>
                </div>
              </>
            )
          })()}
        </>
      )}
      </div>

      {/* 助手已记住的表单 弹窗 */}
      {showCacheModal && (() => {
        // 因为 op-container 有 transform，内部的 fixed 定位会相对于容器而非视口
        // 需要计算反向偏移让弹窗遮罩覆盖整个视口
        const containerEl = containerRef.current
        const rect = containerEl?.getBoundingClientRect()
        const maskStyle: React.CSSProperties = rect ? {
          position: "fixed" as const,
          top: -rect.top,
          left: -rect.left,
          width: "100vw",
          height: "100vh",
        } : {}
        return (
        <div className="op-cache-modal-mask" style={maskStyle} onClick={closeCacheModal}>
          <div className="op-cache-modal" onClick={(e) => e.stopPropagation()}>
            <div className="op-cache-modal-header">
              <span className="op-cache-modal-title">助手已记住的表单</span>
              <button className="op-cache-modal-close" onClick={closeCacheModal}>✕</button>
            </div>
            <div className="op-cache-modal-body">
              {(!cacheModalData || cacheModalData.length === 0) ? (
                <div className="op-cache-modal-empty">暂无缓存数据</div>
              ) : (
                cacheModalData.map((section: any, sIdx: number) => (
                  <div key={sIdx} className="op-cache-modal-section">
                    <div className="op-cache-modal-section-title">{section.title}</div>
                    {section.isExperience ? (
                      // 经历类型：formItems 是二维数组，每段经历分开展示
                      (section.formItems as any[][]).map((segFields: any[], segIdx: number) => (
                        <div key={segIdx} className="op-cache-modal-segment">
                          <div className="op-cache-modal-segment-title">经历{segIdx + 1}</div>
                          <div className="op-cache-modal-fields">
                            {segFields.map((field: any, fIdx: number) => {
                              // 标签名包含"内容"二字的字段用 textarea 单独一行
                              const isLongText = field.label && field.label.includes("内容")
                              if (isLongText) {
                                return (
                                  <div key={fIdx} className="op-cache-modal-field op-cache-modal-field--full">
                                    <label className="op-cache-modal-label">{field.label}</label>
                                    <textarea
                                      className="op-cache-modal-textarea"
                                      rows={3}
                                      value={field.value || ""}
                                      onChange={(e) => updateCacheFieldValue(sIdx, segIdx, fIdx, e.target.value)}
                                    />
                                  </div>
                                )
                              }
                              return (
                                <div key={fIdx} className="op-cache-modal-field">
                                  <label className="op-cache-modal-label">{field.label}</label>
                                  <input
                                    className="op-cache-modal-input"
                                    type="text"
                                    value={field.value || ""}
                                    onChange={(e) => updateCacheFieldValue(sIdx, segIdx, fIdx, e.target.value)}
                                  />
                                </div>
                              )
                            })}
                          </div>
                        </div>
                      ))
                    ) : (
                      // 普通类型：formItems 是一维数组
                      <div className="op-cache-modal-fields">
                        {(section.formItems as any[]).map((field: any, fIdx: number) => (
                          <div key={fIdx} className="op-cache-modal-field">
                            <label className="op-cache-modal-label">{field.label}</label>
                            <input
                              className="op-cache-modal-input"
                              type="text"
                              value={field.value || ""}
                              onChange={(e) => updateCacheFieldValue(sIdx, null, fIdx, e.target.value)}
                            />
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                ))
              )}
            </div>
            <div className="op-cache-modal-footer">
              <button className="op-cache-modal-btn op-cache-modal-btn--clear" onClick={clearCacheFromModal}>清空缓存</button>
              <button className="op-cache-modal-btn op-cache-modal-btn--save" onClick={saveCacheModalData}>确认保存</button>
            </div>
          </div>
        </div>
        )
      })()}
        </>
      )}
    </div>
  )
}

