import { createContext, useContext, useEffect, useMemo, useState, useCallback } from 'react'

const STORAGE_KEY = 'process_files_v3_process_documents'
const FilesContext = createContext(null)

function load() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY)
    if (!raw) return []
    const parsed = JSON.parse(raw)
    if (!Array.isArray(parsed)) return []
    const realFiles = parsed.filter(file => file?.source !== 'seed')
    if (realFiles.length !== parsed.length) save(realFiles)
    return realFiles
  } catch { return null }
}
function save(list) {
  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(list)) } catch {}
}

function sameId(a, b) {
  if (a == null || b == null) return false
  return String(a) === String(b)
}

function normalizeFile(file) {
  const name = file.name || '未命名流程文件'
  const ext = file.ext || (name.includes('.') ? name.split('.').pop() : 'md')
  const description = file.description ?? file.summary ?? ''
  return {
    id: file.id ?? `file_${Date.now().toString(36)}`,
    name,
    ext,
    size: file.size || 0,
    description,
    summary: description,
    content: file.content || '',
    category_id: file.category_id ?? null,
    node_path: file.node_path || '',
    status: file.status || 'draft',
    version: file.version || 'v0.1.0',
    source: file.source || 'manual',
    related_skill_ids: Array.isArray(file.related_skill_ids) ? file.related_skill_ids : [],
    uploader: file.uploader || '当前用户',
    owner: file.owner || file.uploader || '当前用户',
    owner_email: file.owner_email || '',
    owner_phone: file.owner_phone || '',
    created_at: file.created_at || file.updated_at || new Date().toISOString(),
    updated_at: file.updated_at || new Date().toISOString(),
  }
}

export function FilesProvider({ children }) {
  const [files, setFiles] = useState(() => (load() || []).map(normalizeFile))

  useEffect(() => {
    setFiles(prev => {
      const realFiles = prev.filter(file => file?.source !== 'seed')
      return realFiles.length === prev.length ? prev : realFiles
    })
  }, [])

  useEffect(() => { save(files) }, [files])

  const filesByCategory = useMemo(() => {
    const map = new Map()
    files.forEach(f => {
      if (!map.has(f.category_id)) map.set(f.category_id, [])
      map.get(f.category_id).push(f)
    })
    return map
  }, [files])

  // 拿某节点 + 所有子孙节点上的文件（用于 Skill 选 L1/L2 时把下面 L3 的文件一并捞出来）
  const getFilesUnder = useCallback((rootId, flatNodes) => {
    if (rootId == null) return []
    const ids = new Set([rootId])
    let added = true
    while (added) {
      added = false
      flatNodes.forEach(n => {
        if (n.parent_id != null && ids.has(n.parent_id) && !ids.has(n.id)) {
          ids.add(n.id); added = true
        }
      })
    }
    return files.filter(f => ids.has(f.category_id))
  }, [files])

  const addFile = useCallback((payload) => {
    let newId = ''
    setFiles(prev => {
      newId = `file_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`
      const newFile = normalizeFile({
        id: newId,
        created_at: new Date().toISOString(),
        ...payload,
        ext: payload.ext || (payload.name?.split('.').pop() || 'txt'),
        updated_at: new Date().toISOString()
      })
      return [newFile, ...prev]
    })
    return newId
  }, [])

  const updateFile = useCallback((id, patch) => {
    setFiles(prev => prev.map(f => sameId(f.id, id)
      ? normalizeFile({ ...f, ...patch, summary: patch.description ?? patch.summary ?? f.summary, updated_at: new Date().toISOString() })
      : f
    ))
  }, [])

  const deleteFile = useCallback((id) => {
    setFiles(prev => prev.filter(f => !sameId(f.id, id)))
  }, [])

  const findFile = useCallback((id) => files.find(f => sameId(f.id, id)), [files])

  const value = { files, filesByCategory, getFilesUnder, addFile, updateFile, deleteFile, findFile }
  return <FilesContext.Provider value={value}>{children}</FilesContext.Provider>
}

export function useFiles() {
  const ctx = useContext(FilesContext)
  if (!ctx) throw new Error('useFiles must be used within FilesProvider')
  return ctx
}
