/**
 * FF AI Agent API Client (PR2)
 *
 * Backend: backend/src/modules/agent/
 * Routes:
 *   GET    /api/v1/agent/sessions
 *   POST   /api/v1/agent/sessions
 *   GET    /api/v1/agent/sessions/:id
 *   DELETE /api/v1/agent/sessions/:id
 *   POST   /api/v1/agent/messages
 *
 * 注意：apiClient 的全局响应拦截器（lib/api-client.ts）已经做了 `response.data.data` 解包，
 * 返回值就是 controller 里 return 的对象本身。
 */

import apiClient from '@/lib/api-client';

export type AgentSurface = 'WEB' | 'CLI' | 'TEAMS' | 'DESKTOP' | 'IOS' | 'ANDROID';
export type AgentSessionStatus = 'ACTIVE' | 'CLOSED' | 'ARCHIVED';
export type AgentMessageType =
  | 'USER_PROMPT'
  | 'ASSISTANT_TEXT'
  | 'TOOL_USE'
  | 'TOOL_RESULT'
  | 'A2UI_COMPONENT'
  | 'TURN_DONE';

export interface AgentSession {
  id: string;
  organizationId: string;
  createdById: string;
  title: string | null;
  surface: AgentSurface;
  status: AgentSessionStatus;
  projectId: string | null;
  /** 选中的 persona，激活 PERSONA-scoped memory 注入（M1-step2） */
  personaId: string | null;
  /** 多 Agent 拓扑：sub-agent session 指向父 session id；root 为 null */
  parentSessionId: string | null;
  closedAt: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface AgentMessage {
  id: string;
  sessionId: string;
  turnId: string;
  type: AgentMessageType;
  content: string | null;
  payload: unknown;
  model: string | null;
  sequence: number;
  createdAt: string;
}

export interface AgentSessionWithMessages extends AgentSession {
  messages: AgentMessage[];
}

export async function listAgentSessions(params?: {
  limit?: number;
}): Promise<{ items: AgentSession[] }> {
  return (await apiClient.get('/agent/sessions', { params })) as unknown as {
    items: AgentSession[];
  };
}

export async function createAgentSession(input: {
  title?: string;
  projectId?: string;
  personaId?: string;
  organizationId?: string;
}): Promise<AgentSession> {
  return (await apiClient.post('/agent/sessions', input)) as unknown as AgentSession;
}

export async function getAgentSession(sessionId: string): Promise<AgentSessionWithMessages> {
  return (await apiClient.get(`/agent/sessions/${sessionId}`)) as unknown as AgentSessionWithMessages;
}

export async function deleteAgentSession(sessionId: string): Promise<AgentSession> {
  return (await apiClient.delete(`/agent/sessions/${sessionId}`)) as unknown as AgentSession;
}

/** Edit & resubmit: 把 session 内 sequence > afterSequence 的消息硬删，调用方再发新 prompt */
export async function rewindAgentSession(
  sessionId: string,
  afterSequence: number,
): Promise<{ ok: true; deleted: number }> {
  return (await apiClient.post(`/agent/sessions/${sessionId}/rewind`, {
    afterSequence,
  })) as unknown as { ok: true; deleted: number };
}

export async function postAgentMessage(input: {
  sessionId: string;
  prompt: string;
}): Promise<{ turnId: string; messages: AgentMessage[] }> {
  return (await apiClient.post('/agent/messages', input)) as unknown as {
    turnId: string;
    messages: AgentMessage[];
  };
}

export type AgentArtifactType = 'TABLE' | 'CHART' | 'FILE' | 'LINK' | 'TEXT';

export interface AgentArtifact {
  id: string;
  organizationId: string;
  sessionId: string;
  turnId: string | null;
  createdById: string;
  type: AgentArtifactType;
  title: string;
  data: unknown;
  previewUrl: string | null;
  mimeType: string | null;
  sizeBytes: number | null;
  createdAt: string;
}

export async function listAgentArtifacts(sessionId: string): Promise<{ items: AgentArtifact[] }> {
  return (await apiClient.get('/agent/artifacts', { params: { sessionId } })) as unknown as {
    items: AgentArtifact[];
  };
}

export type AgentStreamEvent =
  | { type: 'message'; message: AgentMessage }
  | { type: 'text_delta'; text: string; iter: number }
  | { type: 'routing'; decision: unknown; decisionId: string }
  | { type: 'ask_user'; turnId: string; question: string; options?: string[] }
  | { type: 'done'; turnId: string; totalLatencyMs: number; iterations: number }
  | { type: 'error'; message: string };

/**
 * PR4a SSE 流式发送 —— 用 fetch + ReadableStream + TextDecoder 手工解 SSE 格式
 * （EventSource 不支持 POST body）。
 */
export async function postAgentMessageStream(
  input: { sessionId: string; prompt: string },
  onEvent: (ev: AgentStreamEvent) => void,
  options?: { signal?: AbortSignal; organizationId?: string; token?: string },
): Promise<void> {
  // 从 auth-storage 拿 token / 当前 org（跟 apiClient 拦截器同源）
  const auth = (() => {
    try {
      return JSON.parse(localStorage.getItem('auth-storage') ?? '{}');
    } catch {
      return {};
    }
  })();
  const token = options?.token ?? auth?.state?.token;
  // org 从 organizationContext 来；这里读 localStorage 同名 key（OrganizationContext 写的）
  const currentOrg =
    options?.organizationId ??
    (() => {
      try {
        const o = JSON.parse(localStorage.getItem('current-organization') ?? 'null');
        return o?.id ?? o?.organizationId ?? undefined;
      } catch {
        return undefined;
      }
    })();

  const baseURL = process.env.NEXT_PUBLIC_API_URL || '/api/v1';
  const res = await fetch(`${baseURL}/agent/messages/stream`, {
    method: 'POST',
    signal: options?.signal,
    headers: {
      'Content-Type': 'application/json',
      Accept: 'text/event-stream',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(currentOrg ? { 'X-Organization-Id': String(currentOrg) } : {}),
    },
    body: JSON.stringify(input),
  });
  if (!res.ok || !res.body) {
    throw new Error(`Agent stream failed: HTTP ${res.status}`);
  }

  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    // SSE 用 \n\n 分隔 event；每个 event 多行（event:/data:）
    let sepIdx = buffer.indexOf('\n\n');
    while (sepIdx >= 0) {
      const rawEvent = buffer.slice(0, sepIdx);
      buffer = buffer.slice(sepIdx + 2);
      const lines = rawEvent.split('\n');
      let eventType: string | undefined;
      let dataStr = '';
      for (const line of lines) {
        if (line.startsWith('event:')) eventType = line.slice(6).trim();
        else if (line.startsWith('data:')) dataStr += line.slice(5).trim();
      }
      if (eventType && dataStr) {
        try {
          onEvent(JSON.parse(dataStr) as AgentStreamEvent);
        } catch {
          // ignore malformed
        }
      }
      sepIdx = buffer.indexOf('\n\n');
    }
  }
}
