/**
 * OpenClaw command and connection-mode facade.
 *
 * Vue Query owns runtime reads. This active Pinia store remains because Iris
 * polling and Run Control share connection mode, while privileged task,
 * session and approval mutations need one common command boundary.
 */
import { defineStore } from 'pinia'
import { apiFetch } from '../services/api'
import { createMutationRequestContext } from '../services/mutationContext'
import { refreshOpenClawOverview } from '../api/openclawRuntime'
import { reportOperationEnvelope } from '../services/operationResults'
import type {
  OpenClawApproval,
  OpenClawOperation,
  OpenClawTask,
} from '../types/openclaw'

interface OpenClawErrorPayload {
  detail?: string
  title?: string
  message?: string
  recovery?: string
  state?: string
}

class OpenClawRequestError extends Error {
  constructor(
    message: string,
    readonly status: number,
    readonly state: string | null = null,
    readonly recovery: string | null = null,
  ) {
    super(message)
    this.name = 'OpenClawRequestError'
  }
}

async function readJson<T>(path: string, init?: RequestInit, operationTitle?: string): Promise<T> {
  const response = await apiFetch(path, init)
  const payload = await response.json().catch(() => null) as T | OpenClawErrorPayload | null
  if (operationTitle) reportOperationEnvelope(payload, operationTitle)
  if (!response.ok) {
    const failure = payload as OpenClawErrorPayload | null
    const message = failure?.detail
      || failure?.message
      || failure?.title
      || `Request failed with HTTP ${response.status}`
    throw new OpenClawRequestError(
      failure?.recovery ? `${message} ${failure.recovery}` : message,
      response.status,
      failure?.state ?? null,
      failure?.recovery ?? null,
    )
  }
  return payload as T
}

export const useOpenClawStore = defineStore('openclaw', {
  state: () => ({
    syncMode: 'stopped' as 'stopped' | 'connecting' | 'live' | 'polling',
  }),

  actions: {
    setSyncMode(mode: 'stopped' | 'connecting' | 'live' | 'polling') {
      this.syncMode = mode
    },

    async refreshOverview(_options: { quiet?: boolean } = {}) {
      try {
        return await refreshOpenClawOverview()
      } catch (error) {
        console.warn('[OpenClawStore] overview refresh failed', error)
        return null
      }
    },

    async cancelTask(
      taskId: string,
      reason = 'Stopped from Nexus Mission Control',
    ) {
      const requestContext = createMutationRequestContext('openclaw-task-cancel')
      const result = await readJson<OpenClawOperation<OpenClawTask>>(
        `/api/v1/openclaw/tasks/${encodeURIComponent(taskId)}/cancel`,
        {
          method: 'POST',
          headers: requestContext.headers,
          body: JSON.stringify({ reason }),
        },
        'OpenClaw-Task abgebrochen',
      )
      if (!result.ok) throw new Error(result.recovery || result.message)
      await this.refreshOverview({ quiet: true })
      return result
    },

    async abortSession(sessionKey: string, runId?: string | null) {
      const requestContext = createMutationRequestContext('openclaw-session-abort')
      const result = await readJson<OpenClawOperation<Record<string, unknown>>>(
        '/api/v1/openclaw/sessions/abort',
        {
          method: 'POST',
          headers: requestContext.headers,
          body: JSON.stringify({
            sessionKey,
            runId: runId || null,
            clearQueued: true,
          }),
        },
        'OpenClaw-Session gestoppt',
      )
      if (!result.ok) throw new Error(result.recovery || result.message)
      await this.refreshOverview({ quiet: true })
      return result
    },

    async resolveApproval(approval: OpenClawApproval, decision: string) {
      const requestContext = createMutationRequestContext('openclaw-approval-resolve')
      const result = await readJson<OpenClawOperation<OpenClawApproval>>(
        `/api/v1/openclaw/approvals/${encodeURIComponent(approval.id)}/resolve`,
        {
          method: 'POST',
          headers: requestContext.headers,
          body: JSON.stringify({ kind: approval.kind, decision }),
        },
        'OpenClaw-Freigabe entschieden',
      )
      if (!result.ok) throw new Error(result.recovery || result.message)
      await this.refreshOverview({ quiet: true })
      return result
    },
  },
})
