import { useEffect, useMemo, useRef, useState } from 'react'
import { Alert, Button, Card, Empty, Input, Spin, Typography } from '@arco-design/web-react'
import { IconArrowUp, IconAttachment, IconPlus, IconRobot, IconSearch } from '@arco-design/web-react/icon'
import type { AIExpertDTO, AISessionDTO, CreateAISessionInput } from '../../api/ai'
import type { ProjectWorkspace } from './project-types'

const { Text } = Typography

export function ProjectAi({
  activeWorkspace,
  onSelectItem,
  onListSessions,
  onListExperts,
  onCreateSession,
}: {
  activeWorkspace: ProjectWorkspace
  onSelectItem: (title: string) => void
  onListSessions: (projectId: string, signal?: AbortSignal) => Promise<AISessionDTO[]>
  onListExperts: (signal?: AbortSignal) => Promise<AIExpertDTO[]>
  onCreateSession: (projectId: string, input: CreateAISessionInput, signal?: AbortSignal) => Promise<AISessionDTO>
}) {
  const [sessions, setSessions] = useState<AISessionDTO[]>([])
  const [experts, setExperts] = useState<AIExpertDTO[]>([])
  const [selectedSessionID, setSelectedSessionID] = useState<string | null>(null)
  const [selectedExpertID, setSelectedExpertID] = useState<string | null>(null)
  const [expertQuery, setExpertQuery] = useState('')
  const [expertCategory, setExpertCategory] = useState('all')
  const [prompt, setPrompt] = useState('')
  const [loading, setLoading] = useState(true)
  const [loadingExperts, setLoadingExperts] = useState(true)
  const [creating, setCreating] = useState(false)
  const [error, setError] = useState('')
  const projectId = activeWorkspace.project.id
  const projectRef = useRef(projectId)
  const generationRef = useRef(0)
  const listControllerRef = useRef<AbortController | null>(null)
  const createControllerRef = useRef<AbortController | null>(null)
  projectRef.current = projectId

  useEffect(() => {
    const generation = ++generationRef.current
    const controller = new AbortController()
    listControllerRef.current?.abort()
    createControllerRef.current?.abort()
    listControllerRef.current = controller
    createControllerRef.current = null
    setSessions([])
    setExperts([])
    setSelectedSessionID(null)
    setSelectedExpertID(null)
    setExpertQuery('')
    setExpertCategory('all')
    setPrompt(readPromptDraft(projectId))
    setLoading(true)
    setLoadingExperts(true)
    setCreating(false)
    setError('')
    const isCurrent = () => projectRef.current === projectId && generationRef.current === generation && !controller.signal.aborted

    void onListSessions(projectId, controller.signal)
      .then((items) => {
        if (isCurrent()) setSessions(items)
      })
      .catch((requestError: unknown) => {
        if (isCurrent()) setError(requestError instanceof Error ? requestError.message : 'AI 会话加载失败，请稍后重试')
      })
      .finally(() => {
        if (isCurrent()) setLoading(false)
      })

    void onListExperts(controller.signal)
      .then((items) => {
        if (isCurrent()) setExperts(items)
      })
      .catch((requestError: unknown) => {
        if (isCurrent()) setError(requestError instanceof Error ? requestError.message : '专家库加载失败，请稍后重试')
      })
      .finally(() => {
        if (isCurrent()) {
          setLoadingExperts(false)
          listControllerRef.current = null
        }
      })

    return () => {
      generationRef.current += 1
      controller.abort()
      if (listControllerRef.current === controller) listControllerRef.current = null
      createControllerRef.current?.abort()
      createControllerRef.current = null
    }
  }, [onListExperts, onListSessions, projectId])

  useEffect(() => {
    try {
      if (prompt) localStorage.setItem(promptDraftKey(projectId), prompt)
      else localStorage.removeItem(promptDraftKey(projectId))
    } catch {
      // Draft persistence is best effort; an unavailable browser store must not block chat.
    }
  }, [projectId, prompt])

  const selectedSession = useMemo(
    () => sessions.find((session) => session.id === selectedSessionID) ?? null,
    [selectedSessionID, sessions],
  )
  const selectedExpert = useMemo(
    () => experts.find((expert) => expert.id === selectedExpertID) ?? selectedSession?.expert ?? null,
    [experts, selectedExpertID, selectedSession],
  )
  const expertCategories = useMemo(() => {
    const categories = new Map<string, string>()
    experts.forEach((expert) => categories.set(expert.category, expert.categoryName))
    return [...categories.entries()].map(([id, name]) => ({ id, name }))
  }, [experts])
  const visibleExperts = useMemo(() => {
    const keyword = expertQuery.trim().toLocaleLowerCase()
    return experts.filter((expert) => {
      if (expertCategory !== 'all' && expert.category !== expertCategory) return false
      if (!keyword) return true
      return `${expert.name} ${expert.description} ${expert.categoryName}`.toLocaleLowerCase().includes(keyword)
    })
  }, [expertCategory, expertQuery, experts])

  const createSession = async () => {
    const message = prompt.trim()
    if (!selectedExpert) {
      setError('请先选择一位专家')
      return
    }
    if (!message) {
      setError('请输入会话内容')
      return
    }
    const generation = ++generationRef.current
    listControllerRef.current?.abort()
    listControllerRef.current = null
    createControllerRef.current?.abort()
    const controller = new AbortController()
    createControllerRef.current = controller
    const isCurrent = () => projectRef.current === projectId && generationRef.current === generation && !controller.signal.aborted

    setLoading(false)
    setCreating(true)
    setError('')
    try {
      const created = await onCreateSession(projectId, {
        title: sessionTitle(message),
        context: message,
        expertId: selectedExpert.id,
      }, controller.signal)
      if (!isCurrent()) return
      setSessions((current) => [created, ...current.filter((session) => session.id !== created.id)])
      setSelectedSessionID(created.id)
      setSelectedExpertID(created.expert?.id ?? selectedExpert.id)
      setPrompt('')
      onSelectItem(created.title)
    } catch (requestError) {
      if (!isCurrent()) return
      setError(requestError instanceof Error ? requestError.message : 'AI 会话创建失败，请稍后重试')
    } finally {
      if (isCurrent()) {
        setCreating(false)
        createControllerRef.current = null
      }
    }
  }

  function selectSession(session: AISessionDTO) {
    setSelectedSessionID(session.id)
    setSelectedExpertID(session.expert?.id ?? null)
    setError('')
    onSelectItem(session.title)
  }

  function startNewSession() {
    setSelectedSessionID(null)
    setSelectedExpertID(null)
    setExpertQuery('')
    setExpertCategory('all')
    setPrompt('')
    setError('')
  }

  return (
    <div className="project-channel-page project-ai-page">
      {error ? <Alert className="agent-request-error" type="error" content={error} closable onClose={() => setError('')} /> : null}

      <div className="agent-chat-shell">
        <Card className="agent-session-list queue-section" bordered>
          <Button className="agent-new-chat" icon={<IconPlus />} onClick={startNewSession}>新建会话</Button>

          <Spin loading={loading} style={{ width: '100%' }}>
            {sessions.length ? (
              <div className="agent-session-groups">
                <section className="agent-session-group">
                  <Text type="secondary">最近会话</Text>
                  {sessions.map((session) => (
                    <button
                      className={selectedSessionID === session.id ? 'agent-session active' : 'agent-session'}
                      key={session.id}
                      title={session.title}
                      onClick={() => selectSession(session)}
                    >
                      <span className="agent-session-emoji">{session.expert?.emoji || <IconRobot />}</span>
                      <span>{session.title}</span>
                    </button>
                  ))}
                </section>
              </div>
            ) : loading ? null : <Empty className="agent-session-empty" description="暂无会话" />}
          </Spin>
        </Card>

        <Card className="agent-chat-panel queue-section" bordered>
          <div className="agent-chat-main">
            {selectedSession ? (
              <div className="agent-thread">
                <div className="agent-user-message">{selectedSession.context || selectedSession.title}</div>
                <div className="agent-assistant-message">
                  <span className="agent-assistant-avatar" style={{ background: selectedExpert?.color || undefined }}>
                    {selectedExpert?.emoji || <IconRobot />}
                  </span>
                  <div>
                    <Text className="agent-assistant-name">{selectedExpert?.name || '森林AI'}</Text>
                    <p>会话已创建。你可以继续补充问题或项目背景。</p>
                  </div>
                </div>
              </div>
            ) : (
              <ExpertPicker
                experts={visibleExperts}
                categories={expertCategories}
                selectedExpertID={selectedExpertID}
                query={expertQuery}
                category={expertCategory}
                loading={loadingExperts}
                onQueryChange={setExpertQuery}
                onCategoryChange={setExpertCategory}
                onSelect={setSelectedExpertID}
              />
            )}
          </div>

          <div className="agent-composer">
            <Input.TextArea
              value={prompt}
              placeholder={selectedExpert
                ? `向${selectedExpert.name}发送消息，结合“${activeWorkspace.project.name}”项目上下文`
                : '请先从上方选择一位专家'}
              autoSize={{ minRows: 2, maxRows: 7 }}
              onChange={setPrompt}
              onPressEnter={(event) => {
                if (!event.shiftKey) {
                  event.preventDefault()
                  void createSession()
                }
              }}
            />
            <div className="agent-composer-footer">
              <Button className="agent-model-chip" icon={<span>{selectedExpert?.emoji || <IconRobot />}</span>}>
                {selectedExpert?.name || '选择专家'}
              </Button>
              <div className="agent-composer-actions">
                <Button aria-label="添加附件" type="text" shape="circle" icon={<IconAttachment />} />
                <Button
                  aria-label="发送消息"
                  className="agent-send-button"
                  type="primary"
                  shape="circle"
                  icon={<IconArrowUp />}
                  loading={creating}
                  disabled={!selectedExpert || !prompt.trim()}
                  onClick={() => void createSession()}
                />
              </div>
            </div>
            <Text className="agent-composer-hint" type="secondary">AI 生成内容仅作为建议，转为正式对象前仍需确认</Text>
          </div>
        </Card>
      </div>
    </div>
  )
}

function ExpertPicker({
  experts,
  categories,
  selectedExpertID,
  query,
  category,
  loading,
  onQueryChange,
  onCategoryChange,
  onSelect,
}: {
  experts: AIExpertDTO[]
  categories: Array<{ id: string; name: string }>
  selectedExpertID: string | null
  query: string
  category: string
  loading: boolean
  onQueryChange: (value: string) => void
  onCategoryChange: (value: string) => void
  onSelect: (value: string) => void
}) {
  return (
    <div className="agent-expert-picker">
      <div className="agent-expert-heading">
        <span className="agent-empty-icon"><IconRobot /></span>
        <strong>选择专家进行会话</strong>
        <Text type="secondary">选择合适的专业角色，让会话从明确的方法和交付目标开始</Text>
      </div>
      <Input
        className="agent-expert-search"
        prefix={<IconSearch />}
        value={query}
        onChange={onQueryChange}
        placeholder="搜索专家名称、简介或分类"
        allowClear
      />
      <div className="agent-expert-categories">
        <button className={category === 'all' ? 'active' : ''} onClick={() => onCategoryChange('all')}>全部</button>
        {categories.map((item) => (
          <button className={category === item.id ? 'active' : ''} key={item.id} onClick={() => onCategoryChange(item.id)}>{item.name}</button>
        ))}
      </div>
      <Spin className="agent-expert-loading" loading={loading}>
        {experts.length ? (
          <div className="agent-expert-grid">
            {experts.map((expert) => (
              <button
                className={selectedExpertID === expert.id ? 'agent-expert-card active' : 'agent-expert-card'}
                key={expert.id}
                onClick={() => onSelect(expert.id)}
              >
                <span className="agent-expert-avatar" style={{ background: expert.color }}>{expert.emoji || expert.name.slice(0, 1)}</span>
                <span className="agent-expert-copy">
                  <small>{expert.categoryName}</small>
                  <strong>{expert.name}</strong>
                  <span>{expert.description}</span>
                </span>
              </button>
            ))}
          </div>
        ) : loading ? null : <Empty description="没有匹配的专家，换个关键词试试" />}
      </Spin>
    </div>
  )
}

function sessionTitle(message: string) {
  const firstLine = message.split(/\r?\n/, 1)[0].trim()
  const characters = Array.from(firstLine)
  return characters.length > 36 ? `${characters.slice(0, 36).join('')}…` : firstLine
}

function promptDraftKey(projectId: string) {
  return `senlin:ai:prompt:${projectId}`
}

function readPromptDraft(projectId: string) {
  try {
    return localStorage.getItem(promptDraftKey(projectId)) ?? ''
  } catch {
    return ''
  }
}
