import { createContext, useContext, useEffect, useMemo, useState, useCallback } from 'react'
import { listSkills, createSkillApi, updateSkillApi, deleteSkillApi, publishSkillApi, offlineSkillApi } from '../services/api.js'

const SkillsContext = createContext(null)

// Lite 模板标准状态：draft（草稿）→ published（已上线）→ archived（已下线/归档）
export const SKILL_STATUS = {
  draft:     { label: '草稿',    color: 'bg-gray-100 text-gray-600' },
  published: { label: '已上线',  color: 'bg-emerald-100 text-emerald-700' },
  archived:  { label: '已下线',  color: 'bg-rose-100 text-rose-700' },
  offline:   { label: '已下线',  color: 'bg-rose-100 text-rose-700' },
}

function load() {
  // 已废弃：Skill 数据全部走后端 API，本函数仅为历史兼容保留
  return null
}
function save(_list) {
  // 已废弃：Skill 数据全部走后端 API
}

// ID 匹配辅助：兼容后端字符串 ID 与历史数字 ID
function sameId(a, b) {
  if (a == null || b == null) return false
  return String(a) === String(b)
}

// 默认 system prompt 模板（基于关联节点 + 文件生成）
function defaultSystemPrompt(name, nodePath, fileNames) {
  return `你是「${name}」，一个聚焦在「${nodePath || '通用流程'}」的智能助手。

工作目标：
1. 基于上下文文件回答用户的流程相关问题，给出可执行的建议；
2. 引用文件原文时给出文件名 + 简要原文；
3. 当用户的问题超出当前节点范围时，主动告知并指引到对应流程节点。

你的上下文文件：
${fileNames.length ? fileNames.map((n, i) => `  ${i + 1}. ${n}`).join('\n') : '  （暂未绑定文件）'}

请用专业、简洁的中文回答，结构化输出。`
}

export function SkillsProvider({ children }) {
  const [skills, setSkills] = useState([])
  const [loading, setLoading] = useState(true)

  // 加载真实后端 Skill 列表
  useEffect(() => {
    async function load() {
      try {
        const res = await listSkills()
        if (res && res.list) {
          setSkills(res.list)
        }
      } catch (e) {
        console.error('加载 Skills 失败:', e)
        // 降级到空列表，避免上层取 .filter / .length 时报错导致白屏
        setSkills([])
      } finally {
        setLoading(false)
      }
    }
    load()
  }, [])

  const findById = useCallback((id) => skills.find(s => sameId(s.id, id)), [skills])

  // 创建 Skill：调后端 API
  const createSkill = useCallback(async (data) => {
    try {
      const res = await createSkillApi(data)
      if (res && res.id) {
        setSkills(prev => [{ ...res, ...data }, ...prev])
        return res.id
      }
    } catch (e) {
      console.error('创建 Skill 失败:', e)
      throw e
    }
    return null
  }, [])

  const updateSkill = useCallback(async (id, patch) => {
    try {
      await updateSkillApi(id, patch)
      setSkills(prev => prev.map(s => sameId(s.id, id)
        ? { ...s, ...patch, updated_at: new Date().toISOString() }
        : s
      ))
    } catch (e) {
      console.error('更新 Skill 失败:', e)
      throw e
    }
  }, [])

  const deleteSkill = useCallback(async (id) => {
    try {
      await deleteSkillApi(id)
      setSkills(prev => prev.filter(s => !sameId(s.id, id)))
    } catch (e) {
      console.error('删除 Skill 失败:', e)
      throw e
    }
  }, [])

  const appendMessage = useCallback((id, msg) => {
    setSkills(prev => prev.map(s => sameId(s.id, id)
      ? { ...s, messages: [...(s.messages || []), msg], updated_at: new Date().toISOString() }
      : s
    ))
  }, [])

  const clearMessages = useCallback((id) => {
    setSkills(prev => prev.map(s => sameId(s.id, id) ? { ...s, messages: [] } : s))
  }, [])

  const addEvalRecord = useCallback((id, record) => {
    setSkills(prev => prev.map(s => sameId(s.id, id)
      ? { ...s, eval_records: [record, ...(s.eval_records || [])], updated_at: new Date().toISOString() }
      : s
    ))
  }, [])

  const publish = useCallback(async (id) => {
    try {
      await publishSkillApi(id)
      setSkills(prev => prev.map(s => sameId(s.id, id)
        ? { ...s, status: 'published', published_at: new Date().toISOString(), version: bumpVersion(s.version), updated_at: new Date().toISOString() }
        : s
      ))
    } catch (e) {
      console.error('发布 Skill 失败:', e)
      throw e
    }
  }, [])

  const offline = useCallback(async (id) => {
    try {
      await offlineSkillApi(id)
      setSkills(prev => prev.map(s => sameId(s.id, id)
        ? { ...s, status: 'archived', updated_at: new Date().toISOString() }
        : s
      ))
    } catch (e) {
      console.error('下线 Skill 失败:', e)
      throw e
    }
  }, [])

  const summary = useMemo(() => ({
    total: skills.length,
    draft: skills.filter(s => s.status === 'draft').length,
    published: skills.filter(s => s.status === 'published').length,
    archived: skills.filter(s => s.status === 'archived' || s.status === 'offline').length,
    offline: skills.filter(s => s.status === 'archived' || s.status === 'offline').length
  }), [skills])

  const value = {
    skills, summary, findById,
    createSkill, updateSkill, deleteSkill,
    appendMessage, clearMessages,
    addEvalRecord, publish, offline
  }

  return <SkillsContext.Provider value={value}>{children}</SkillsContext.Provider>
}

function bumpVersion(v) {
  // v0.1.0 → v0.2.0；v1.0.0 → v1.1.0
  if (!v) return 'v1.0.0'
  const m = /^v(\d+)\.(\d+)\.(\d+)$/.exec(v)
  if (!m) return 'v1.0.0'
  return `v${m[1]}.${Number(m[2]) + 1}.0`
}

export function useSkills() {
  const ctx = useContext(SkillsContext)
  if (!ctx) throw new Error('useSkills must be used within SkillsProvider')
  return ctx
}
