/**
 * Workflow API client
 */

import type {
  WorkflowDefinition,
  WorkflowSummary,
  WorkflowExecution,
} from '@/utils/workflowSerializer'

const API_BASE = '/api/v1'

class WorkflowApiClient {
  private baseUrl: string

  constructor(baseUrl: string = API_BASE) {
    this.baseUrl = baseUrl
  }

  private async request<T>(
    path: string,
    options: RequestInit = {}
  ): Promise<T> {
    const url = `${this.baseUrl}${path}`
    const headers: HeadersInit = {
      'Content-Type': 'application/json',
      ...options.headers,
    }

    const response = await fetch(url, {
      ...options,
      headers,
    })

    if (!response.ok) {
      const error: { status: number; message: string; detail?: string } = {
        status: response.status,
        message: response.statusText,
      }
      try {
        const body = await response.json()
        error.detail = body.detail ?? body.message
        error.message = error.detail ?? error.message
      } catch {
        // response body is not JSON
      }
      throw error
    }

    return response.json() as Promise<T>
  }

  /** List all workflows */
  async listWorkflows(limit: number = 50): Promise<{ workflows: WorkflowSummary[]; total: number }> {
    return this.request(`/workflows?limit=${limit}`)
  }

  /** Create a new workflow */
  async createWorkflow(data: {
    name: string
    stages: unknown[]
    triggers?: unknown[]
    variables_schema?: Record<string, unknown>
    output_schema?: Record<string, unknown>
  }): Promise<WorkflowDefinition> {
    return this.request('/workflows', {
      method: 'POST',
      body: JSON.stringify(data),
    })
  }

  /** Get a workflow by ID */
  async getWorkflow(workflowId: string): Promise<WorkflowDefinition> {
    return this.request(`/workflows/${workflowId}`)
  }

  /** Update a workflow */
  async updateWorkflow(
    workflowId: string,
    data: {
      name: string
      stages: unknown[]
      triggers?: unknown[]
      variables_schema?: Record<string, unknown>
      output_schema?: Record<string, unknown>
    }
  ): Promise<WorkflowDefinition> {
    return this.request(`/workflows/${workflowId}`, {
      method: 'PUT',
      body: JSON.stringify(data),
    })
  }

  /** Delete a workflow */
  async deleteWorkflow(workflowId: string): Promise<void> {
    await this.request(`/workflows/${workflowId}`, {
      method: 'DELETE',
    })
  }

  /** Execute a workflow */
  async executeWorkflow(
    workflowId: string,
    variables?: Record<string, unknown>
  ): Promise<{ execution_id: string; workflow_id: string; status: string }> {
    return this.request(`/workflows/${workflowId}/execute`, {
      method: 'POST',
      body: JSON.stringify({ variables: variables || {} }),
    })
  }

  /** Get execution status */
  async getExecution(executionId: string): Promise<WorkflowExecution> {
    return this.request(`/workflows/executions/${executionId}`)
  }

  /** Approve a paused execution */
  async approveExecution(
    executionId: string,
    approved: boolean,
    comment?: string
  ): Promise<WorkflowExecution> {
    return this.request(`/workflows/executions/${executionId}/approve`, {
      method: 'POST',
      body: JSON.stringify({ approved, comment }),
    })
  }

  /** Cancel an execution */
  async cancelExecution(executionId: string): Promise<WorkflowExecution> {
    return this.request(`/workflows/executions/${executionId}/cancel`, {
      method: 'POST',
    })
  }

  /** Create a WebSocket connection for real-time workflow progress */
  createWorkflowWebSocket(): WebSocket {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    const host = window.location.host
    return new WebSocket(`${protocol}//${host}${this.baseUrl}/workflows/ws`)
  }
}

export const workflowApi = new WorkflowApiClient()
export { WorkflowApiClient }
