import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { apiFetch } from '@/lib/tauri'
import { terminalApiUrl } from '../config/endpoints'

// ── Types (mirror server/services/session-state.ts) ──

export type AgentStatus =
  | 'idle'
  | 'thinking'
  | 'reading'
  | 'writing'
  | 'toolUse'
  | 'permissionRequest'
  | 'interrupted'
  | 'error'
  | 'sessionStart'
  | 'sessionEnd'

export interface ActiveTool {
  name: string
  input: unknown
  startedAt: number
}

export interface PendingApproval {
  requestId: string
  type: 'permission' | 'plan'
  toolName?: string
  toolInput?: unknown
  cwd?: string
  lastAssistantText?: string
  timestamp: number
}

export interface HookHistoryEntry {
  event: string
  timestamp: number
  detail?: string
}

export interface SessionNotification {
  id: string
  event: string
  title: string
  detail: string
  type: 'info' | 'success' | 'warning' | 'error'
  timestamp: number
  persistent: boolean
  expiresAt: number | null
}

export interface AgentTerminalInfo {
  ptySessionId: string | null
  alive: boolean
  bufferSize: number
  connectedClients: number
}

export interface LastError {
  tool: string
  message: string
  interrupted: boolean
  timestamp: number
}

export interface AgentSessionState {
  agent: string
  sessionId: string | null
  model: string | null
  cwd: string | null
  transcriptPath: string | null
  permissionMode: string | null
  status: AgentStatus
  currentTool: ActiveTool | null
  lastActivity: number
  lastStopResponse: string | null
  lastError: LastError | null
  pendingApprovals: PendingApproval[]
  terminal: AgentTerminalInfo
  notifications: SessionNotification[]
  hookHistory: HookHistoryEntry[]
  lastHookEvent: string | null
  lastHookDetail: string | null
}

// WS message types
interface SessionStateSnapshot {
  type: 'session-state-snapshot'
  agents: Record<string, AgentSessionState>
}

interface SessionStatePatch {
  type: 'session-state-patch'
  agent: string
  patch: Partial<AgentSessionState>
  event: string
  timestamp: number
}

interface TerminalRegistryChange {
  type: 'terminal-registry-change'
  registry: TerminalRegistryEntry[]
  timestamp: number
}

export interface TerminalRegistryEntry {
  ephemeralSessionId: string
  transcriptSessionId: string
  agent: string
  label: string
  command: string
  createdAt: string
  alive: boolean
  clients: number
  bufferSize: number
}

type SessionStateMessage = SessionStateSnapshot | SessionStatePatch | TerminalRegistryChange

// ── Store ──

export const useSessionState = defineStore('session-state', () => {
  const agents = ref<Record<string, AgentSessionState>>({})
  const terminalRegistry = ref<TerminalRegistryEntry[]>([])
  const connected = ref(false)
  const lastUpdate = ref(0)

  // ── Computed helpers ──

  const agentList = computed(() => Object.values(agents.value))

  const agentNames = computed(() => Object.keys(agents.value))

  function getAgent(name: string) {
    return computed(() => agents.value[name] ?? null)
  }

  const anyPendingApprovals = computed(() =>
    agentList.value.some(a => a.pendingApprovals.length > 0)
  )

  const totalPendingApprovals = computed(() =>
    agentList.value.reduce((sum, a) => sum + a.pendingApprovals.length, 0)
  )

  const allPendingApprovals = computed(() =>
    agentList.value.flatMap(a =>
      a.pendingApprovals.map(p => ({ ...p, agent: a.agent }))
    )
  )

  const isProcessing = computed(() =>
    agentList.value.some(a => !['idle', 'sessionStart', 'sessionEnd'].includes(a.status))
  )

  const hasErrors = computed(() =>
    agentList.value.some(a => a.status === 'error' || a.status === 'interrupted')
  )

  const visibleNotifications = computed(() => {
    const now = Date.now()
    return agentList.value
      .flatMap(a => a.notifications.map(n => ({ ...n, agent: a.agent })))
      .filter(n => n.persistent || !n.expiresAt || n.expiresAt > now)
      .sort((a, b) => b.timestamp - a.timestamp)
      .slice(0, 10)
  })

  // ── Message handler ──

  function handleMessage(msg: SessionStateMessage) {
    if (msg.type === 'session-state-snapshot') {
      agents.value = { ...msg.agents }
      lastUpdate.value = Date.now()
    } else if (msg.type === 'session-state-patch') {
      const current = agents.value[msg.agent]
      if (current) {
        agents.value = {
          ...agents.value,
          [msg.agent]: { ...current, ...msg.patch }
        }
      } else {
        // New agent appeared — treat patch as full state if it has required fields
        agents.value = {
          ...agents.value,
          [msg.agent]: msg.patch as AgentSessionState
        }
      }
      lastUpdate.value = msg.timestamp
    } else if (msg.type === 'terminal-registry-change') {
      terminalRegistry.value = msg.registry
      lastUpdate.value = msg.timestamp
    }
  }

  // ── Actions ──

  async function respondApproval(requestId: string, decision: string, reason?: string) {
    await apiFetch('/api/hooks-approval/respond', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ requestId, decision, reason })
    })
  }

  async function respondPlanApproval(requestId: string, decision: string, reason?: string) {
    await apiFetch('/api/hooks-approval/respond-plan', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ requestId, decision, reason })
    })
  }

  async function refreshAgentState(agent: string) {
    try {
      const res = await apiFetch(terminalApiUrl(`/session-state/${agent}`))
      if (!res.ok) return
      const state = await res.json() as AgentSessionState
      agents.value = { ...agents.value, [agent]: state }
      lastUpdate.value = Date.now()
    } catch { /* silent — WS patches will catch up */ }
  }

  function setConnected(value: boolean) {
    connected.value = value
  }

  return {
    agents,
    terminalRegistry,
    connected,
    lastUpdate,
    agentList,
    agentNames,
    getAgent,
    anyPendingApprovals,
    totalPendingApprovals,
    allPendingApprovals,
    isProcessing,
    hasErrors,
    visibleNotifications,
    handleMessage,
    refreshAgentState,
    respondApproval,
    respondPlanApproval,
    setConnected,
  }
})
