import { defineStore } from 'pinia'
import { apiFetch } from '../services/api'
import { createMutationRequestContext } from '../services/mutationContext'
import type {
  OpenClawWizardAnswer,
  OpenClawWizardMode,
  OpenClawWizardResult,
} from '../types/openclaw-wizard'

interface ErrorPayload {
  detail?: string
  message?: string
  recovery?: string
  title?: string
}

async function readWizardResult(
  path: string,
  init?: RequestInit,
): Promise<OpenClawWizardResult> {
  const response = await apiFetch(path, init)
  const payload = await response.json().catch(() => null) as
    | OpenClawWizardResult
    | ErrorPayload
    | null
  if (!response.ok) {
    const failure = payload as ErrorPayload | null
    throw new Error(
      failure?.recovery
      || failure?.detail
      || failure?.message
      || failure?.title
      || `OpenClaw wizard request failed with HTTP ${response.status}.`,
    )
  }

  const result = payload as OpenClawWizardResult | null
  if (!result || typeof result.ok !== 'boolean') {
    throw new Error('OpenClaw wizard returned an invalid response.')
  }
  if (!result.ok) {
    throw new Error(result.recovery || result.error || result.message)
  }
  return result
}

function mutationHeaders(operation: string): Headers {
  return createMutationRequestContext(operation).headers
}

export const useOpenClawWizardStore = defineStore('openclaw-wizard', {
  state: () => ({
    result: null as OpenClawWizardResult | null,
    action: '' as '' | 'start' | 'next' | 'refresh' | 'cancel',
    error: '',
    announcement: '',
  }),
  getters: {
    busy: state => Boolean(state.action),
    sessionId: state => state.result?.sessionId ?? null,
    step: state => state.result?.step ?? null,
    active: state => Boolean(
      state.result?.sessionId
      && !state.result.done
      && state.result.status !== 'cancelled'
      && state.result.status !== 'error',
    ),
  },
  actions: {
    async start(mode: OpenClawWizardMode) {
      this.action = 'start'
      this.error = ''
      try {
        const result = await readWizardResult(
          '/api/v1/openclaw/setup/wizard/start',
          {
            method: 'POST',
            headers: mutationHeaders('openclaw-wizard-start'),
            body: JSON.stringify({ mode, confirmed: true }),
          },
        )
        this.result = result
        this.announcement = result.message
        return result
      } catch (error) {
        this.error = error instanceof Error
          ? error.message
          : 'OpenClaw wizard could not be started.'
        throw error
      } finally {
        this.action = ''
      }
    },

    async next(answer: OpenClawWizardAnswer) {
      const sessionId = this.sessionId
      const currentStep = this.step
      if (!sessionId || !currentStep) {
        throw new Error('No active OpenClaw wizard step is available.')
      }
      if (currentStep.sensitive || !currentStep.canAnswer) {
        throw new Error(
          currentStep.blockedReason
          || 'This OpenClaw step cannot be answered in the browser.',
        )
      }
      if (answer.stepId !== currentStep.id) {
        throw new Error('The answer no longer belongs to the current OpenClaw step.')
      }

      this.action = 'next'
      this.error = ''
      try {
        const result = await readWizardResult(
          '/api/v1/openclaw/setup/wizard/next',
          {
            method: 'POST',
            headers: mutationHeaders('openclaw-wizard-next'),
            body: JSON.stringify({
              sessionId,
              stepId: answer.stepId,
              value: answer.value,
              hasAnswer: answer.hasAnswer,
            }),
          },
        )
        this.result = result
        this.announcement = result.message
        return result
      } catch (error) {
        this.error = error instanceof Error
          ? error.message
          : 'OpenClaw wizard could not continue.'
        throw error
      } finally {
        this.action = ''
      }
    },

    async refresh() {
      const sessionId = this.sessionId
      if (!sessionId) throw new Error('No OpenClaw wizard session is available.')

      this.action = 'refresh'
      this.error = ''
      try {
        const result = await readWizardResult(
          `/api/v1/openclaw/setup/wizard/${encodeURIComponent(sessionId)}`,
        )
        const currentStep = this.result?.step ?? null
        this.result = {
          ...result,
          step: result.step ?? (result.done ? null : currentStep),
        }
        this.announcement = result.message
        return this.result
      } catch (error) {
        this.error = error instanceof Error
          ? error.message
          : 'OpenClaw wizard status could not be loaded.'
        throw error
      } finally {
        this.action = ''
      }
    },

    async cancel() {
      const sessionId = this.sessionId
      if (!sessionId) throw new Error('No OpenClaw wizard session is available.')

      this.action = 'cancel'
      this.error = ''
      try {
        const result = await readWizardResult(
          `/api/v1/openclaw/setup/wizard/${encodeURIComponent(sessionId)}/cancel`,
          {
            method: 'POST',
            headers: mutationHeaders('openclaw-wizard-cancel'),
          },
        )
        this.result = result
        this.announcement = result.message
        return result
      } catch (error) {
        this.error = error instanceof Error
          ? error.message
          : 'OpenClaw wizard could not be cancelled.'
        throw error
      } finally {
        this.action = ''
      }
    },

    clearCompleted() {
      if (this.active) return
      this.result = null
      this.error = ''
      this.announcement = ''
    },
  },
})
