/**
 * AI Assistant plugin API client.
 *
 * All requests use the shared `apiClient` (`baseURL: '/api/v1'`) and target the
 * AI Assistant plugin routes under `/ai/...`.
 */

import { apiDelete, apiGet, apiPost, apiPut } from './client';

// ─── Types ───

export interface AIProvider {
  id: string;
  name: string;
  provider_type: string;
  api_key: string;
  base_url: string;
  is_active: boolean;
  is_default: boolean;
  config: Record<string, unknown>;
  created_at?: string;
  updated_at?: string;
}

export interface AIModel {
  id: string;
  provider_id: string;
  model_id: string;
  display_name: string;
  context_window: number;
  supports_tools: boolean;
  supports_streaming: boolean;
  is_active: boolean;
  config: Record<string, unknown>;
}

export interface AIPreset {
  id: string;
  name: string;
  model_id: string;
  provider_id: string | null;
  temperature: number;
  max_tokens: number;
  top_p: number;
  system_prompt: string;
  config: Record<string, unknown>;
  is_active: boolean;
}

export interface AIAgent {
  id: string;
  name: string;
  description: string;
  system_prompt: string;
  preset_id: string | null;
  tool_ids: string[];
  is_default: boolean;
  is_active: boolean;
  config: Record<string, unknown>;
  created_at?: string;
  updated_at?: string;
}

export interface ChatFolder {
  id: string;
  name: string;
  parent_id: string | null;
  user_id: string;
  created_at?: string;
}

export interface ChatSession {
  id: string;
  user_id: string;
  agent_id: string | null;
  title: string;
  is_pinned: boolean;
  is_sidebar: boolean;
  folder_id: string | null;
  created_at?: string;
  updated_at?: string;
}

export interface ChatMessage {
  id: string;
  session_id: string;
  role: string;
  content: string;
  tool_calls?: Record<string, unknown>[];
  tool_results?: Record<string, unknown>[];
  tokens: number;
  model_used: string;
  created_at?: string;
}

export interface ChatAttachment {
  id: string;
  message_id: string | null;
  session_id: string;
  filename: string;
  mime_type: string;
  size_bytes: number;
}

export interface AITool {
  name: string;
  description: string;
  parameters: Record<string, unknown>;
  plugin_name: string;
  required_permission: string | null;
  category: string;
}

// ─── Providers ───

export const fetchProviders = () => apiGet<AIProvider[]>('/ai/providers');
export const createProvider = (data: Partial<AIProvider>) => apiPost<AIProvider>('/ai/providers', data);
export const updateProvider = (id: string, data: Partial<AIProvider>) => apiPut<AIProvider>(`/ai/providers/${id}`, data);
export const deleteProvider = (id: string) => apiDelete(`/ai/providers/${id}`);

// ─── Models ───

export const fetchModels = (providerId?: string) =>
  apiGet<AIModel[]>('/ai/models', { params: providerId ? { provider_id: providerId } : {} });
export const createModel = (data: Partial<AIModel>) => apiPost<AIModel>('/ai/models', data);
export const updateModel = (id: string, data: Partial<AIModel>) => apiPut<AIModel>(`/ai/models/${id}`, data);
export const deleteModel = (id: string) => apiDelete(`/ai/models/${id}`);

// ─── Presets ───

export const fetchPresets = () => apiGet<AIPreset[]>('/ai/presets');
export const createPreset = (data: Partial<AIPreset>) => apiPost<AIPreset>('/ai/presets', data);
export const updatePreset = (id: string, data: Partial<AIPreset>) => apiPut<AIPreset>(`/ai/presets/${id}`, data);
export const deletePreset = (id: string) => apiDelete(`/ai/presets/${id}`);

// ─── Agents ───

export const fetchAgents = () => apiGet<AIAgent[]>('/ai/agents');
export const createAgent = (data: Partial<AIAgent>) => apiPost<AIAgent>('/ai/agents', data);
export const updateAgent = (id: string, data: Partial<AIAgent>) => apiPut<AIAgent>(`/ai/agents/${id}`, data);
export const deleteAgent = (id: string) => apiDelete(`/ai/agents/${id}`);

// ─── Tools ───

export const fetchTools = () => apiGet<AITool[]>('/ai/tools');

// ─── Folders ───

export const fetchFolders = () => apiGet<ChatFolder[]>('/ai/folders');
export const createFolder = (data: { name: string; parent_id?: string }) => apiPost<ChatFolder>('/ai/folders', data);
export const updateFolder = (id: string, data: Partial<ChatFolder>) => apiPut<ChatFolder>(`/ai/folders/${id}`, data);
export const deleteFolder = (id: string) => apiDelete(`/ai/folders/${id}`);

// ─── Sessions ───

export const fetchSessions = (isSidebar?: boolean) =>
  apiGet<ChatSession[]>('/ai/sessions', { params: isSidebar !== undefined ? { is_sidebar: isSidebar } : {} });
export const createSession = (data: { title?: string; agent_id?: string; is_sidebar?: boolean; folder_id?: string }) =>
  apiPost<ChatSession>('/ai/sessions', data);
export const updateSession = (id: string, data: Partial<ChatSession>) =>
  apiPut<ChatSession>(`/ai/sessions/${id}`, data);
export const deleteSession = (id: string) => apiDelete(`/ai/sessions/${id}`);

// ─── Messages ───

export const fetchMessages = (sessionId: string) =>
  apiGet<ChatMessage[]>(`/ai/sessions/${sessionId}/messages`);

// ─── Attachments ───

export const fetchAttachments = (sessionId: string) =>
  apiGet<ChatAttachment[]>(`/ai/sessions/${sessionId}/attachments`);

export async function uploadAttachment(sessionId: string, file: File): Promise<ChatAttachment> {
  const formData = new FormData();
  formData.append('file', file);
  const csrfToken = sessionStorage.getItem('leocrm_csrf_token');
  const response = await fetch(`/api/v1/ai/sessions/${sessionId}/attachments`, {
    method: 'POST',
    headers: {
      ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}),
    },
    credentials: 'include',
    body: formData,
  });
  if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
  return response.json();
}

export function getAttachmentDownloadUrl(attachmentId: string): string {
  return `/api/v1/ai/attachments/${attachmentId}/download`;
}

// ─── Streaming Chat ───

export interface StreamEvent {
  type: 'token' | 'tool_calls' | 'tool_result' | 'done' | 'error';
  content?: string;
  tool?: string;
  result?: string;
  tools?: string[];
}

export async function* streamChat(
  sessionId: string,
  content: string,
  agentId?: string
): AsyncGenerator<StreamEvent> {
  const csrfToken = sessionStorage.getItem('leocrm_csrf_token');
  const response = await fetch(`/api/v1/ai/sessions/${sessionId}/stream`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...(csrfToken ? { 'X-CSRF-Token': csrfToken } : {}),
    },
    credentials: 'include',
    body: JSON.stringify({ content, agent_id: agentId }),
  });

  if (!response.ok) {
    throw new Error(`Stream failed: ${response.status}`);
  }

  const reader = response.body?.getReader();
  if (!reader) throw new Error('No response body');

  const decoder = new TextDecoder();
  let buffer = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split('\n');
    buffer = lines.pop() || '';

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = line.slice(6).trim();
        if (data === '[DONE]') return;
        try {
          yield JSON.parse(data);
        } catch {
          // skip invalid JSON
        }
      }
    }
  }
}
