/**
 * AWOOOI Terminal Store
 * ==========================
 * Phase 19 - Omni-Terminal SSE State Machine
 *
 * 核心功能:
 * 1. 7-State SSE 連線狀態機
 * 2. 混合模式 SSE (POST intent + GET stream)
 * 3. 指數退避重連
 * 4. Last-Event-ID 斷點續傳
 *
 * @see ADR-031 Omni-Terminal SSE Architecture
 * @see lib/constants/sse-states.ts
 *
 * @author Claude Code (首席架構師)
 * @version 2.0.0
 * @date 2026-03-28 (台北時間)
 */

import { create } from 'zustand'
import {
  type SSEConnectionState,
  type TerminalSession,
  type TerminalEventType,
  type SSEEventData,
  isValidTransition,
  getReconnectDelay,
  shouldRetry,
  createSession,
  getStateInfo,
} from '@/lib/constants/sse-states'
import {
  trackIntentSubmit,
  trackIntentComplete,
  trackSSEConnection,
  setTerminalContext,
  clearTerminalContext,
} from '@/lib/telemetry'

// =============================================================================
// Types
// =============================================================================

export type MessageRole = 'system' | 'user' | 'assistant'
export type MessageType = 'text' | 'tool_call' | 'thought' | 'render_ui'

export interface TerminalMessage {
  id: string
  role: MessageRole
  type: MessageType
  content: string
  payload?: Record<string, unknown>
  timestamp: Date
}

/** Ghost Payload - 空間感知上下文 */
export interface SpatialContext {
  /** 當前頁面路由 */
  currentPage: string
  /** 聚焦的實體 ID (incident/approval) */
  focusedEntityId?: string
}

/** Intent 請求回應 (snake_case from backend) */
interface IntentResponse {
  session_id: string
  stream_url: string
  created_at: string
}

// =============================================================================
// Store State
// =============================================================================

interface TerminalState {
  // UI 狀態
  isOpen: boolean

  // SSE 連線狀態機
  connectionState: SSEConnectionState
  session: TerminalSession | null
  reconnectAttempt: number

  // 訊息
  messages: TerminalMessage[]

  // 內部引用
  _eventSource: EventSource | null
  _abortController: AbortController | null

  // Actions - UI
  toggleTerminal: () => void
  openTerminal: () => void
  closeTerminal: () => void

  // Actions - SSE 狀態機
  transitionTo: (newState: SSEConnectionState) => void
  connect: () => Promise<void>
  disconnect: () => void

  // Actions - 訊息
  sendIntent: (text: string, context?: SpatialContext) => Promise<void>
  appendMessage: (message: Omit<TerminalMessage, 'id' | 'timestamp'>) => void
  updateLastMessage: (contentChunk: string) => void
  clearMessages: () => void

  // Actions - 內部
  _subscribeToStream: (sessionId: string) => Promise<void>
  _handleSSEEvent: (event: MessageEvent) => void
  _handleSSEError: (error: Event) => void
  _reconnect: () => void

  // Selectors (computed)
  getStateInfo: () => ReturnType<typeof getStateInfo>
}

// =============================================================================
// API Base URL
// =============================================================================

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || ''

// =============================================================================
// Store Implementation
// =============================================================================

export const useTerminalStore = create<TerminalState>((set, get) => ({
  // ---------------------------------------------------------------------------
  // Initial State
  // ---------------------------------------------------------------------------
  isOpen: false,
  connectionState: 'disconnected',
  session: null,
  reconnectAttempt: 0,
  messages: [
    {
      id: 'sys-init',
      role: 'system',
      type: 'text',
      content: 'AWOOOI OS [Version 2.0.0]\n(c) WOOO Corporation. All rights reserved.',
      timestamp: new Date(),
    },
    {
      id: 'sys-ready',
      role: 'system',
      type: 'text',
      content: 'System ready. Press ⌘J to toggle terminal.',
      timestamp: new Date(),
    },
  ],
  _eventSource: null,
  _abortController: null,

  // ---------------------------------------------------------------------------
  // UI Actions
  // ---------------------------------------------------------------------------
  toggleTerminal: () => set((state) => ({ isOpen: !state.isOpen })),
  openTerminal: () => set({ isOpen: true }),
  closeTerminal: () => {
    get().disconnect()
    set({ isOpen: false })
  },

  // ---------------------------------------------------------------------------
  // SSE State Machine
  // ---------------------------------------------------------------------------
  transitionTo: (newState: SSEConnectionState) => {
    const currentState = get().connectionState

    // 驗證狀態轉換
    if (!isValidTransition(currentState, newState)) {
      console.warn(
        `[Terminal] Invalid state transition: ${currentState} → ${newState}`
      )
      return
    }

    console.log(`[Terminal] State: ${currentState} → ${newState}`)
    set({ connectionState: newState })

    // 錯誤狀態自動觸發重連
    if (newState === 'error') {
      const { reconnectAttempt } = get()
      if (shouldRetry(reconnectAttempt)) {
        const delay = getReconnectDelay(reconnectAttempt)
        console.log(`[Terminal] Reconnecting in ${delay}ms (attempt ${reconnectAttempt + 1})`)
        setTimeout(() => get()._reconnect(), delay)
      }
    }
  },

  connect: async () => {
    // Note: In Hybrid SSE mode, connect() is for reconnection scenarios only
    // The actual connection happens in _subscribeToStream() after POST /intent
    const state = get()

    // 已連接則跳過
    if (state.connectionState === 'connected' || state.connectionState === 'streaming') {
      return
    }

    // 沒有有效 session 則無法連接
    if (!state.session?.sessionId) {
      console.warn('[Terminal] No valid session for reconnection')
      return
    }

    // 嘗試重新訂閱現有 session
    await get()._subscribeToStream(state.session.sessionId)
  },

  /**
   * 訂閱 SSE 串流 (內部方法)
   * ADR-031: Hybrid SSE 模式 - POST intent 後才訂閱
   */
  _subscribeToStream: async (sessionId: string) => {
    const state = get()

    // 開始訂閱
    state.transitionTo('subscribing')

    // 追蹤 SSE 連線開始 (Phase 19.O)
    trackSSEConnection({
      state: 'connecting',
      sessionId,
    })

    try {
      const streamUrl = `${API_BASE_URL}/api/v1/terminal/stream/${sessionId}`
      const lastEventId = state.session?.lastEventId

      const eventSource = new EventSource(
        lastEventId ? `${streamUrl}?last_event_id=${lastEventId}` : streamUrl
      )

      // 設定事件處理器
      eventSource.onopen = () => {
        console.log('[Terminal] SSE connected to', sessionId)
        get().transitionTo('connected')
        // 進入串流狀態 (正在處理)
        get().transitionTo('streaming')

        // 追蹤 SSE 連線成功 (Phase 19.O)
        trackSSEConnection({
          state: 'connected',
          sessionId,
        })
      }

      eventSource.onmessage = (event) => {
        get()._handleSSEEvent(event)
      }

      eventSource.onerror = (error) => {
        get()._handleSSEError(error)
      }

      // 監聽特定事件類型
      const eventTypes: TerminalEventType[] = [
        'terminal_thought',
        'terminal_tool_call',
        'terminal_render_ui',
        'terminal_action_request',
        'terminal_action_result',
        'terminal_complete',
        'terminal_error',
        'terminal_heartbeat',
        'connected',
        'heartbeat',
      ]

      eventTypes.forEach((type) => {
        eventSource.addEventListener(type, (event) => {
          get()._handleSSEEvent(event as MessageEvent)
        })
      })

      set({ _eventSource: eventSource })
    } catch (error) {
      console.error('[Terminal] SSE subscription error:', error)
      get().transitionTo('error')
    }
  },

  disconnect: () => {
    const { _eventSource, _abortController } = get()

    if (_eventSource) {
      _eventSource.close()
    }

    if (_abortController) {
      _abortController.abort()
    }

    set({
      connectionState: 'disconnected',
      _eventSource: null,
      _abortController: null,
      session: null,
      reconnectAttempt: 0,
    })

    console.log('[Terminal] Disconnected')
  },

  // ---------------------------------------------------------------------------
  // Message Actions
  // ---------------------------------------------------------------------------
  sendIntent: async (text: string, context?: SpatialContext) => {
    if (!text.trim()) return

    const state = get()
    const intentStartTime = Date.now()

    // 樂觀更新 UI - 顯示使用者輸入
    state.appendMessage({
      role: 'user',
      type: 'text',
      content: text,
    })

    // 關閉現有 SSE 連線 (每次 intent 是新的 session)
    if (state._eventSource) {
      state._eventSource.close()
      set({ _eventSource: null })
    }

    // 進入連接狀態
    state.transitionTo('connecting')

    // 追蹤 Intent 提交 (Phase 19.O 可觀測性)
    trackIntentSubmit({
      intentType: 'user_input',
      inputLength: text.length,
    })

    try {
      const abortController = new AbortController()
      set({ _abortController: abortController })

      // Step 1: POST intent 到後端建立 session
      // Phase 20: CSRF Protection — 先取得 token 再提交
      const csrfRes = await fetch(`${API_BASE_URL}/api/v1/csrf/token`, { method: 'GET', credentials: 'include' })
      if (!csrfRes.ok) throw new Error(`CSRF fetch failed: ${csrfRes.status}`)
      const csrfData = await csrfRes.json()
      const csrfHeaders: Record<string, string> = csrfData.token ? { 'X-CSRF-Token': String(csrfData.token) } : {}
      const response = await fetch(`${API_BASE_URL}/api/v1/terminal/intent`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...csrfHeaders,
        },
        body: JSON.stringify({
          intent: text,
          context: {
            current_page: context?.currentPage ??
              (typeof window !== 'undefined' ? window.location.pathname : '/'),
            focused_entity_id: context?.focusedEntityId,
          },
        }),
        signal: abortController.signal,
      })

      if (!response.ok) {
        throw new Error(`Intent failed: ${response.status}`)
      }

      const data: IntentResponse = await response.json()

      // Step 2: 建立 session 並訂閱 SSE
      set({
        session: createSession(data.session_id),
        reconnectAttempt: 0,
      })

      // 設定 Sentry 上下文 (Phase 19.O)
      setTerminalContext(data.session_id, 'user_input')

      // Step 3: 訂閱 SSE 串流
      await get()._subscribeToStream(data.session_id)

      // 追蹤 Intent 完成 (Phase 19.O)
      trackIntentComplete({
        intentType: 'user_input',
        inputLength: text.length,
        sessionId: data.session_id,
        duration: Date.now() - intentStartTime,
        success: true,
      })
    } catch (error) {
      if ((error as Error).name === 'AbortError') {
        console.log('[Terminal] Intent aborted')
        set({ connectionState: 'disconnected' })
        clearTerminalContext()
        return
      }

      console.error('[Terminal] Intent error:', error)
      get().appendMessage({
        role: 'system',
        type: 'text',
        content: `Error: ${(error as Error).message}`,
      })

      // 追蹤 Intent 失敗 (Phase 19.O)
      trackIntentComplete({
        intentType: 'user_input',
        inputLength: text.length,
        duration: Date.now() - intentStartTime,
        success: false,
      })

      // 進入錯誤狀態 (會觸發自動重連)
      set({ connectionState: 'error' })
    }
  },

  appendMessage: (msg) =>
    set((state) => ({
      messages: [
        ...state.messages,
        {
          ...msg,
          id: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
          timestamp: new Date(),
        },
      ],
    })),

  updateLastMessage: (contentChunk: string) =>
    set((state) => {
      const messages = [...state.messages]
      if (messages.length === 0) return state

      const lastMsg = messages[messages.length - 1]
      if (lastMsg.role === 'assistant') {
        lastMsg.content += contentChunk
        return { messages }
      }
      return state
    }),

  clearMessages: () =>
    set({
      messages: [
        {
          id: 'sys-cleared',
          role: 'system',
          type: 'text',
          content: 'Terminal cleared.',
          timestamp: new Date(),
        },
      ],
    }),

  // ---------------------------------------------------------------------------
  // Internal Handlers
  // ---------------------------------------------------------------------------
  _handleSSEEvent: (event: MessageEvent) => {
    const state = get()

    try {
      const data: SSEEventData = JSON.parse(event.data)

      // 更新 lastEventId
      if (data.id && state.session) {
        set((s) => ({
          session: s.session ? { ...s.session, lastEventId: data.id! } : null,
        }))
      }

      // 根據事件類型處理
      switch (data.type) {
        case 'terminal_thought':
          state.appendMessage({
            role: 'assistant',
            type: 'thought',
            content: (data.data.msg as string) || '',
            payload: data.data,
          })
          break

        case 'terminal_tool_call':
          state.appendMessage({
            role: 'assistant',
            type: 'tool_call',
            content: `[Tool] ${data.data.tool}`,
            payload: data.data,
          })
          break

        case 'terminal_render_ui':
          state.appendMessage({
            role: 'assistant',
            type: 'render_ui',
            content: '',
            payload: data.data,
          })
          break

        case 'terminal_action_request':
          state.appendMessage({
            role: 'assistant',
            type: 'render_ui',
            content: '',
            payload: {
              component: 'ApprovalCard',
              props: data.data,
            },
          })
          break

        case 'terminal_complete':
          // 串流完成，回到 connected 狀態
          if (state.connectionState === 'streaming') {
            state.transitionTo('connected')
          }
          break

        case 'terminal_error':
          state.appendMessage({
            role: 'system',
            type: 'text',
            content: `Error: ${data.data.message || 'Unknown error'}`,
          })
          state.transitionTo('error')
          break

        case 'terminal_heartbeat':
        case 'heartbeat':
          // 心跳，更新活動時間
          if (state.session) {
            set((s) => ({
              session: s.session
                ? { ...s.session, lastActivityAt: new Date() }
                : null,
            }))
          }
          break

        default:
          console.log('[Terminal] Unknown event type:', data.type)
      }
    } catch (error) {
      console.error('[Terminal] Failed to parse SSE event:', error)
    }
  },

  _handleSSEError: (error: Event) => {
    const state = get()
    console.error('[Terminal] SSE error:', error)

    // 追蹤 SSE 錯誤 (Phase 19.O)
    trackSSEConnection({
      state: 'error',
      sessionId: state.session?.sessionId,
      error: 'SSE connection error',
      retryCount: state.reconnectAttempt,
    })

    // 關閉現有連接
    if (state._eventSource) {
      state._eventSource.close()
      set({ _eventSource: null })
    }

    // 進入錯誤狀態 (會自動觸發重連)
    state.transitionTo('error')
  },

  _reconnect: () => {
    const state = get()

    // 更新重連計數
    set((s) => ({ reconnectAttempt: s.reconnectAttempt + 1 }))

    // 追蹤 SSE 重連 (Phase 19.O)
    trackSSEConnection({
      state: 'reconnecting',
      sessionId: state.session?.sessionId,
      retryCount: state.reconnectAttempt + 1,
    })

    // 進入重連狀態
    state.transitionTo('reconnecting')

    // 嘗試重新連接
    state.connect()
  },

  // ---------------------------------------------------------------------------
  // Selectors
  // ---------------------------------------------------------------------------
  getStateInfo: () => getStateInfo(get().connectionState),
}))

// =============================================================================
// Selector Hooks (Optimized Re-renders)
// =============================================================================

/** 取得連線狀態 */
export const useConnectionState = () =>
  useTerminalStore((s) => s.connectionState)

/** 取得狀態資訊 (label, color, etc.) */
export const useConnectionStateInfo = () =>
  useTerminalStore((s) => getStateInfo(s.connectionState))

/** 是否已連接 (可發送訊息) */
export const useIsConnected = () =>
  useTerminalStore((s) => {
    const info = getStateInfo(s.connectionState)
    return info.isConnected
  })

/** 是否正在串流 */
export const useIsStreaming = () =>
  useTerminalStore((s) => s.connectionState === 'streaming')

/** Terminal 是否開啟 */
export const useIsTerminalOpen = () =>
  useTerminalStore((s) => s.isOpen)

/** 訊息列表 */
export const useTerminalMessages = () =>
  useTerminalStore((s) => s.messages)
