import { debugLog } from '#cli/core/debug-log'

type ThinkingStateOptions = Readonly<{
  assistantId: string
  state: {
    sessionId: string
    thinking: {
      active: boolean
      assistantId: string | null
      partId: string | null
    }
  }
  readAssistantStatus: () => string
  setAssistantStatus: (assistantId: string, text: string) => void
}>

export interface ThinkingStateManager {
  isThinking: boolean
  start: (partId?: string) => void
  end: () => void
  forceEnd: () => void
  validate: () => boolean
}

export function createThinkingStateManager(
  opts: ThinkingStateOptions,
): ThinkingStateManager {
  const { assistantId, state, readAssistantStatus, setAssistantStatus } = opts

  return {
    isThinking: false,

    start(partId?: string): void {
      const nextPartId = String(partId ?? '').trim() || null
      this.isThinking = true
      state.thinking.active = true
      state.thinking.assistantId = assistantId
      state.thinking.partId = nextPartId
    },

    end(): void {
      if (!this.isThinking) {
        // Not thinking - ensure state is clean
        if (state.thinking.active) {
          debugLog('thinking_state_inconsistent', {
            session_id: String(state.sessionId ?? ''),
            was_active: true,
          })
          state.thinking.active = false
          state.thinking.assistantId = null
          state.thinking.partId = null
        }
        return
      }

      this.isThinking = false
      state.thinking.active = false
      state.thinking.assistantId = null
      state.thinking.partId = null

      const prev = readAssistantStatus()
      if (/^thinking\b/i.test(prev))
        setAssistantStatus(assistantId, '')
    },

    /**
     * Force end thinking state, called on error/timeout/abort.
     * Ensures clean state even if thinking was active.
     */
    forceEnd(): void {
      const wasThinking = this.isThinking || state.thinking.active

      this.isThinking = false
      state.thinking.active = false
      state.thinking.assistantId = null
      state.thinking.partId = null

      if (wasThinking) {
        const prev = readAssistantStatus()
        if (/^thinking\b/i.test(prev))
          setAssistantStatus(assistantId, '')

        debugLog('thinking_force_ended', {
          session_id: String(state.sessionId ?? ''),
        })
      }
    },

    /**
     * Validate thinking state consistency.
     * Returns true if state is consistent, false otherwise.
     */
    validate(): boolean {
      const localActive = this.isThinking
      const stateActive = state.thinking.active

      if (localActive !== stateActive) {
        debugLog('thinking_state_mismatch', {
          session_id: String(state.sessionId ?? ''),
          local_active: localActive,
          state_active: stateActive,
        })
        return false
      }

      return true
    },
  }
}
