import { ref } from 'vue'
import { createIdempotentCommand, type IdempotentCommand } from '../commands/idempotency'
export interface OptimisticCommandRequest<T> extends IdempotentCommand<T> { etag?: string }
export interface OptimisticCommandResponse<TResult> { data: TResult; etag?: string; correlationId?: string }
export function useOptimisticCommand<TPayload, TResult>(execute: (request: OptimisticCommandRequest<TPayload>, headers: Record<string,string>) => Promise<OptimisticCommandResponse<TResult>>) {
  const pending = ref(false); const conflict = ref(false); const lastCorrelationId = ref<string>()
  async function run(request: OptimisticCommandRequest<TPayload>): Promise<OptimisticCommandResponse<TResult>> {
    if (pending.value) throw new Error('Command is already in progress')
    pending.value=true; conflict.value=false
    try {
      const headers: Record<string,string> = { 'Idempotency-Key': request.idempotencyKey }
      if (request.etag) headers['If-Match']=request.etag
      const response=await execute(request,headers); lastCorrelationId.value=response.correlationId; return response
    } catch (error: unknown) {
      const status=(error as { response?: { status?: number } })?.response?.status
      if (status===409 || status===412) conflict.value=true
      throw error
    } finally { pending.value=false }
  }
  function createRequest(payload: TPayload, etag?: string): OptimisticCommandRequest<TPayload> {
    return Object.freeze({ ...createIdempotentCommand(payload), etag })
  }
  return { pending, conflict, lastCorrelationId, createRequest, run }
}
