import { create } from 'zustand'
import { useSessionStore } from './useSessionStore'
import { useConnectionStore } from './useConnectionStore'
import { lastSendMode } from '@/lib/message-send-times'

export type SessionStatusType =
  | 'working'
  | 'planning'
  | 'answering'
  | 'permission'
  | 'command_approval'
  | 'unread'
  | 'completed'
  | 'plan_ready'

export interface SessionStatusEntry {
  status: SessionStatusType
  timestamp: number
  word?: string
  durationMs?: number
}

interface WorktreeStatusState {
  // sessionId → status info (null means no status / cleared)
  sessionStatuses: Record<string, SessionStatusEntry | null>
  // worktreeId → epoch ms of last message activity
  lastMessageTimeByWorktree: Record<string, number>

  // Actions
  setSessionStatus: (
    sessionId: string,
    status: SessionStatusType | null,
    metadata?: { word?: string; durationMs?: number }
  ) => void
  clearSessionStatus: (sessionId: string) => void
  clearWorktreeUnread: (worktreeId: string) => void
  getWorktreeStatus: (worktreeId: string) => SessionStatusType | null
  getConnectionStatus: (connectionId: string) => SessionStatusType | null
  getWorktreeCompletedEntry: (worktreeId: string) => SessionStatusEntry | null
  setLastMessageTime: (worktreeId: string, timestamp: number) => void
  getLastMessageTime: (worktreeId: string) => number | null
}

// Priority ranking for status aggregation (higher number = higher priority)
const STATUS_PRIORITY: Record<SessionStatusType, number> = {
  answering: 8,
  command_approval: 7,
  permission: 6,
  planning: 5,
  working: 4,
  plan_ready: 3,
  completed: 2,
  unread: 1
}

function higherPriority(
  a: SessionStatusType | null,
  b: SessionStatusType | null
): SessionStatusType | null {
  if (!a) return b
  if (!b) return a
  return STATUS_PRIORITY[a] >= STATUS_PRIORITY[b] ? a : b
}

export const useWorktreeStatusStore = create<WorktreeStatusState>((set, get) => ({
  sessionStatuses: {},
  lastMessageTimeByWorktree: {},

  setSessionStatus: (
    sessionId: string,
    status: SessionStatusType | null,
    metadata?: { word?: string; durationMs?: number }
  ) => {
    set((state) => ({
      sessionStatuses: {
        ...state.sessionStatuses,
        [sessionId]: status ? { status, timestamp: Date.now(), ...metadata } : null
      }
    }))
  },

  clearSessionStatus: (sessionId: string) => {
    set((state) => ({
      sessionStatuses: {
        ...state.sessionStatuses,
        [sessionId]: null
      }
    }))
  },

  clearWorktreeUnread: (worktreeId: string) => {
    const { sessionStatuses } = get()
    const sessionStore = useSessionStore.getState()
    const sessions = sessionStore.sessionsByWorktree.get(worktreeId) || []

    const updates: Record<string, null> = {}
    for (const s of sessions) {
      const st = sessionStatuses[s.id]?.status
      if (st === 'unread' || st === 'completed') {
        updates[s.id] = null
      }
    }

    if (Object.keys(updates).length > 0) {
      set((state) => ({
        sessionStatuses: { ...state.sessionStatuses, ...updates }
      }))
    }
  },

  getWorktreeStatus: (worktreeId: string): SessionStatusType | null => {
    const { sessionStatuses } = get()

    // ── Connection status (takes priority over worktree's own sessions) ──
    const connections = useConnectionStore.getState().connections
    const parentConnectionIds = connections
      .filter((c) => c.members.some((m) => m.worktree_id === worktreeId))
      .map((c) => c.id)

    if (parentConnectionIds.length > 0) {
      let bestConnectionStatus: SessionStatusType | null = null
      for (const connId of parentConnectionIds) {
        const connStatus = get().getConnectionStatus(connId)
        if (connStatus) {
          bestConnectionStatus = higherPriority(bestConnectionStatus, connStatus)
        }
      }
      if (bestConnectionStatus !== null) return bestConnectionStatus
    }

    // ── Worktree's own session status (fallback) ──
    const sessionStore = useSessionStore.getState()
    const sessions = sessionStore.sessionsByWorktree.get(worktreeId) || []
    const sessionIds = sessions.map((s) => s.id)

    let hasPlanning = false
    let hasWorking = false
    let hasPlanReady = false
    let hasCompleted = false
    let latestUnread: SessionStatusEntry | null = null

    for (const id of sessionIds) {
      const entry = sessionStatuses[id]
      if (!entry) continue

      // answering/command_approval/permission have the highest priority — return immediately
      if (entry.status === 'answering' || entry.status === 'command_approval' || entry.status === 'permission') return entry.status
      if (entry.status === 'planning') hasPlanning = true
      if (entry.status === 'working') hasWorking = true
      if (entry.status === 'plan_ready') hasPlanReady = true
      if (entry.status === 'completed') hasCompleted = true

      // Track the latest unread
      if (entry.status === 'unread') {
        if (!latestUnread || entry.timestamp > latestUnread.timestamp) {
          latestUnread = entry
        }
      }
    }

    // Priority: answering > planning > working > plan_ready > completed > unread > null
    if (hasPlanning) return 'planning'
    if (hasWorking) return 'working'
    if (hasPlanReady) return 'plan_ready'

    // Derive plan_ready from the mode the user last sent a message in.
    // If the last message was sent in plan mode and the session completed,
    // show "Plan ready". Otherwise show normal "Ready".
    if (hasCompleted) {
      const completedInPlan = sessions.some(
        (s) => sessionStatuses[s.id]?.status === 'completed' && lastSendMode.get(s.id) === 'plan'
      )
      return completedInPlan ? 'plan_ready' : 'completed'
    }

    return latestUnread ? 'unread' : null
  },

  getConnectionStatus: (connectionId: string): SessionStatusType | null => {
    const { sessionStatuses } = get()
    const sessionStore = useSessionStore.getState()
    const sessions = sessionStore.sessionsByConnection.get(connectionId) || []
    const sessionIds = sessions.map((s) => s.id)

    let hasPlanning = false
    let hasWorking = false
    let hasPlanReady = false
    let hasCompleted = false
    let latestUnread: SessionStatusEntry | null = null

    for (const id of sessionIds) {
      const entry = sessionStatuses[id]
      if (!entry) continue

      if (entry.status === 'answering' || entry.status === 'command_approval' || entry.status === 'permission') return entry.status
      if (entry.status === 'planning') hasPlanning = true
      if (entry.status === 'working') hasWorking = true
      if (entry.status === 'plan_ready') hasPlanReady = true
      if (entry.status === 'completed') hasCompleted = true

      if (entry.status === 'unread') {
        if (!latestUnread || entry.timestamp > latestUnread.timestamp) {
          latestUnread = entry
        }
      }
    }

    if (hasPlanning) return 'planning'
    if (hasWorking) return 'working'
    if (hasPlanReady) return 'plan_ready'

    if (hasCompleted) {
      const completedInPlan = sessions.some(
        (s) => sessionStatuses[s.id]?.status === 'completed' && lastSendMode.get(s.id) === 'plan'
      )
      return completedInPlan ? 'plan_ready' : 'completed'
    }

    return latestUnread ? 'unread' : null
  },

  getWorktreeCompletedEntry: (worktreeId: string): SessionStatusEntry | null => {
    const { sessionStatuses } = get()
    const sessionStore = useSessionStore.getState()
    const sessions = sessionStore.sessionsByWorktree.get(worktreeId) || []

    for (const s of sessions) {
      const entry = sessionStatuses[s.id]
      if (entry?.status === 'completed') return entry
    }
    return null
  },

  setLastMessageTime: (worktreeId: string, timestamp: number) => {
    const prev = get().lastMessageTimeByWorktree[worktreeId] ?? 0
    const next = Math.max(prev, timestamp)
    if (next === prev && prev !== 0) return // no change

    set((state) => ({
      lastMessageTimeByWorktree: {
        ...state.lastMessageTimeByWorktree,
        [worktreeId]: next
      }
    }))

    // Persist to SQLite (fire-and-forget)
    window.db?.worktree?.update(worktreeId, { last_message_at: next }).catch(() => {})
  },

  getLastMessageTime: (worktreeId: string) => {
    return get().lastMessageTimeByWorktree[worktreeId] ?? null
  }
}))
