import type { InternalAxiosRequestConfig } from '@vben/request';

import {
  defaultResponseInterceptor,
  RequestClient,
} from '@vben/request';
import { useAccessStore } from '@vben/stores';

import {
  bindImportAttachment,
  createImportSession,
} from '#/api/mdm/item/agent';
import { uploadFile } from '#/api/system/storage';

/**
 * 模块数据补录会话服务（Python）不在 /admin-api 下，
 * 开发期由 Vite 代理 /agent-api 转发到 127.0.0.1:8091，且不返回 CommonResult 包装。
 */
const agentClient = new RequestClient({
  baseURL: '/agent-api',
  responseReturn: 'body',
  timeout: 120_000,
});

agentClient.addRequestInterceptor({
  fulfilled: (config: InternalAxiosRequestConfig) => {
    const token = useAccessStore().accessToken;
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
});

// Python 服务直接返回业务 JSON，不套 CommonResult；responseReturn: 'body' 时原样返回响应体。
agentClient.addResponseInterceptor(
  defaultResponseInterceptor({
    codeField: 'code',
    dataField: 'data',
    successCode: 0,
  }),
);

export namespace AgentConversationApi {
  export interface FieldSpec {
    name: string;
    label: string;
    required: boolean;
    kind: string;
  }

  export interface ModuleSpec {
    module_id: string;
    title: string;
    capability: string;
    bridge: string;
    permission: string;
    description: string;
    required_fields: string[];
    fields: FieldSpec[];
  }

  export interface Capabilities {
    version: string;
    formats: string[];
    ocr: boolean;
    cross_file_dedupe: boolean;
    import_modes: string[];
    notes: string[];
    modules: ModuleSpec[];
    durable_tasks?: {
      enabled: boolean;
      events: string;
      fact_source: string;
      transport: string;
    };
  }

  export interface AuthorizedCapability {
    tool: string;
    module: string;
    operation: string;
    allowed_fields: string[];
    scope_summary: string;
    can_execute: boolean;
  }

  export interface AuthorizedCapabilityCatalog {
    policy_revision: string;
    authorization_scope: string;
    scope_summary: string;
    capabilities: AuthorizedCapability[];
  }

  export interface BusinessModelInfo {
    id: number;
    name: string;
    model: string;
    platform: string;
    temperature?: number | null;
    max_tokens?: number | null;
    max_contexts?: number | null;
  }

  export interface Issue {
    code?: string;
    field?: string;
    message: string;
    candidate_id?: string;
  }

  export interface Summary {
    total?: number;
    create?: number;
    skip?: number;
    blocked?: number;
    success?: number;
    failed?: number;
    skipped?: number;
    unknown?: number;
  }

  export interface ReceiptRow {
    candidate_id: string;
    row_no?: number;
    code?: string;
    name?: string;
    action: string;
    status: string;
    target_item_id?: number;
    error_code?: string;
    error_message?: string;
  }

  export interface Receipt {
    command_id: string;
    idempotency_key: string;
    status: string;
    attachment_id: number;
    source_sha256: string;
    preflight_hash: string;
    summary: Summary;
    rows: ReceiptRow[];
    create_time?: string;
    completed_time?: string;
    error_code?: string;
    error_message?: string;
  }

  export interface ModuleCandidate {
    module_id: string;
    title: string;
    capability: string;
    description: string;
  }

  export interface MissingField {
    name: string;
    label: string;
  }

  /** 卡片字段按 kind 复用，未使用的字段为空。 */
  export interface Card {
    kind: string;
    title?: string;
    body?: string;
    module_id?: string;
    module_title?: string;
    capability?: string;
    revision?: number;
    issues?: Issue[];
    warnings?: Issue[];
    repair_guidance?: Array<{ field?: string; guidance: string }>;
    summary?: Summary;
    can_commit?: boolean;
    side_effects?: string[];
    sync_mes?: boolean | null;
    total?: number;
    actions?: string[];
    notice?: string;
    candidates?: ModuleCandidate[];
    missing_fields?: MissingField[];
    columns?: string[];
    command_id?: string;
    status?: string;
    rows?: ReceiptRow[];
  }

  export interface Message {
    message_id: string;
    role: string;
    type: string;
    text: string;
    cards?: Card[];
  }

  export interface Interrupt {
    interrupt_id: string;
    kind: string;
    revision: number;
    validation_revision?: number | null;
    card: Card;
  }

  export interface RowView {
    candidate_id: string;
    values: Record<string, string>;
    issues: unknown[];
    warnings: unknown[];
  }

  export interface ConversationAttachment {
    attachment_id: string;
    /** 仅最新附件解析出文件名；历史附件可能为空。 */
    filename: string;
  }

  export interface Conversation {
    conversation_id: string;
    title: string;
    status: string;
    module_id: string;
    module_title: string;
    capability: string;
    data_scope_summary: string;
    model_id?: number | null;
    policy_revision: string;
    revision: number;
    validation_revision?: number | null;
    sync_mes?: boolean;
    total: number;
    summary: Summary;
    issues: Issue[];
    warnings: Issue[];
    missing_fields: string[];
    columns: string[];
    /** 候选行实际有值的字段，用于渲染明细表。 */
    row_fields: Array<{ name: string; label: string }>;
    attachments: ConversationAttachment[];
    messages: Message[];
    interrupts: Interrupt[];
    /** 未提交时后端返回空对象 {}，提交后才有完整回执。 */
    receipt?: null | Partial<Receipt>;
    last_error: string;
    rows: RowView[];
    created_at: string;
    updated_at: string;
    finished: boolean;
    commit_enabled: boolean;
    mes_sync_default: boolean;
  }

  export interface ConversationSummary {
    conversation_id: string;
    title: string;
    status: string;
    module_id: string;
    module_title: string;
    revision: number;
    created_at: string;
    updated_at: string;
  }

  export interface PageResult {
    items: ConversationSummary[];
    total: number;
    page: number;
    page_size: number;
  }

  export interface ConversationEvent {
    conversation_id: string;
    payload: Record<string, unknown>;
    seq: number;
    type:
      | 'card'
      | 'error'
      | 'message'
      | 'progress'
      | 'receipt'
      | 'resync'
      | 'status';
  }

  export interface CreateReq {
    title?: string;
    text?: string;
    attachment_id?: string;
    module_id?: string;
    model_id?: number;
    constraints?: ConversationConstraints;
  }

  export interface ConversationConstraints {
    scenario_paths: string[];
    time_start?: string;
    time_end?: string;
    record_limit?: number;
    industry?: string;
    skip_rest_days?: boolean;
    rest_day_description?: string;
    region?: string;
    instruction?: string;
    priority_fields: string[];
  }

  export interface ActionReq {
    interrupt_id: string;
    revision: number;
    action: string;
    payload: Record<string, unknown>;
    model_id?: number;
  }

  export interface MessageReq {
    text?: string;
    attachment_id?: string;
    model_id?: number;
  }
}

export namespace AgentTaskApi {
  export interface Progress {
    mode: 'determinate' | 'indeterminate';
    completed: number;
    total: null | number;
    percent: null | number;
    unit?: string;
  }

  export interface Result {
    attachment_id?: number;
    attachment_ids?: number[];
    candidate_count?: number;
    continuation_supported?: boolean;
    evidence_ref?: {
      backend: string;
      candidate_count?: number;
      revision: string;
      task_id: string;
    } | null;
    filename?: string;
    filenames?: string[];
    module_id?: string;
    module_title?: string;
    result_kind?: string;
    source_sha256?: string;
    source_sha256s?: string[];
    review_summary?: {
      conflict_groups: number;
      exact_duplicates_merged: number;
      incomplete_keys: number;
      requires_review: boolean;
    };
    warnings?: string[];
  }

  export interface Task {
    task_id: string;
    owner_id: string;
    kind: string;
    status: string;
    stage: string;
    attempt: number;
    sequence: number;
    progress: Progress;
    message: string;
    result: null | Result;
    error: null | { code?: string; message?: string };
    allowed_actions: string[];
    created_at: null | string;
    updated_at: null | string;
    started_at: null | string;
    finished_at: null | string;
  }

  export interface PageResult {
    items: Task[];
    total: number;
    page: number;
    page_size: number;
  }

  export interface CreateReq {
    attachment_id?: number;
    attachment_ids?: number[];
    module_id?: string;
    constraints?: AgentConversationApi.ConversationConstraints;
  }
}

/** 能力声明：支持的格式、模块与限制 */
export function getAgentCapabilities() {
  return agentClient.get<AgentConversationApi.Capabilities>('/v1/capabilities');
}

/** 读取当前登录用户经 Java 后端裁剪后的可查询、可操作能力。 */
export function getAuthorizedAgentCapabilities() {
  return agentClient.get<AgentConversationApi.AuthorizedCapabilityCatalog>(
    '/v1/authorization/capabilities',
  );
}

/** 当前数据补录链路实际使用的业务模型；不返回 API 密钥或服务地址。 */
export function getActiveBusinessModel() {
  return agentClient.get<AgentConversationApi.BusinessModelInfo>('/v1/model');
}

/** 可切换的业务模型列表，按后端排序返回，默认使用第一个。 */
export function getAgentModels() {
  return agentClient.get<AgentConversationApi.BusinessModelInfo[]>('/v1/models');
}

/** 分页读取当前用户的持久后台任务。 */
export function listAgentTasks(params?: {
  page?: number;
  page_size?: number;
  status?: string;
}) {
  return agentClient.get<AgentTaskApi.PageResult>('/v1/tasks', { params });
}

/** 创建文档后台分析任务，服务端立即返回 HTTP 202 快照。 */
export function createDocumentTask(data: AgentTaskApi.CreateReq) {
  return agentClient.post<AgentTaskApi.Task>('/v1/tasks/document-onboarding', data);
}

/** 读取任务事实快照。 */
export function getAgentTask(taskId: string) {
  return agentClient.get<AgentTaskApi.Task>(`/v1/tasks/${taskId}`);
}

/** 取消任务并撤销短期委托票据。 */
export function cancelAgentTask(taskId: string) {
  return agentClient.delete<AgentTaskApi.Task>(`/v1/tasks/${taskId}`);
}

/** 使用认证请求读取任务 SSE；游标用于断线续传。 */
export async function streamAgentTaskEvents(
  taskId: string,
  since: number,
  signal: AbortSignal,
  onEvent: (event: AgentTaskApi.Task) => void,
) {
  const token = useAccessStore().accessToken;
  const response = await fetch(
    `/agent-api/v1/tasks/${encodeURIComponent(taskId)}/events?since=${since}`,
    {
      credentials: 'same-origin',
      headers: {
        Accept: 'text/event-stream',
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
      },
      signal,
    },
  );
  if (!response.ok) throw new Error(`任务事件连接失败（HTTP ${response.status}）`);
  if (!response.body) throw new Error('当前浏览器不支持流式事件');
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let cursor = since;
  while (true) {
    const { done, value } = await reader.read();
    buffer += decoder.decode(value, { stream: !done }).replaceAll('\r\n', '\n');
    const frames = buffer.split('\n\n');
    buffer = frames.pop() ?? '';
    for (const frame of frames) {
      const data = frame
        .split('\n')
        .filter((line) => line.startsWith('data:'))
        .map((line) => line.slice(5).trimStart())
        .join('\n');
      if (!data) continue;
      const event = JSON.parse(data) as AgentTaskApi.Task;
      if (!Number.isSafeInteger(event.sequence) || event.sequence <= cursor) continue;
      cursor = event.sequence;
      onEvent(event);
    }
    if (done) break;
  }
  return cursor;
}

/** 会话列表 */
export function listAgentConversations(params?: {
  page?: number;
  page_size?: number;
  status?: string;
}) {
  return agentClient.get<AgentConversationApi.PageResult>(
    '/v1/conversations',
    { params },
  );
}

/** 新建补录会话 */
export function createAgentConversation(data: AgentConversationApi.CreateReq) {
  return agentClient.post<AgentConversationApi.Conversation>(
    '/v1/conversations',
    data,
  );
}

/** 读取会话 */
export function getAgentConversation(conversationId: string) {
  return agentClient.get<AgentConversationApi.Conversation>(
    `/v1/conversations/${conversationId}`,
  );
}

/** 删除会话：同时清理检查点、事件与 Java 侧补录附件 */
export function deleteAgentConversation(conversationId: string) {
  return agentClient.delete<{
    attachments_deleted: number;
    conversation_id: string;
    deleted: boolean;
  }>(`/v1/conversations/${conversationId}`);
}

/**
 * 读取会话附件。mode 为 inline 时 PDF/图片由浏览器直接预览，
 * 其余类型服务端会自动降级为下载。
 */
export function downloadAgentConversationAttachment(
  conversationId: string,
  attachmentId: string,
  mode: 'download' | 'inline',
) {
  return agentClient.download<{
    data: Blob;
    headers: Record<string, string>;
  }>(`/v1/conversations/${conversationId}/attachment`, {
    params: { attachment_id: attachmentId, mode },
    responseReturn: 'raw',
  });
}

/**
 * 使用 fetch 读取带认证头的 SSE。EventSource 不能设置 Authorization，不能用于本接口。
 * 服务端会主动结束短连接；调用方负责携带返回游标重连。
 */
export async function streamAgentConversationEvents(
  conversationId: string,
  since: number,
  signal: AbortSignal,
  onEvent: (event: AgentConversationApi.ConversationEvent) => void,
  onOpen?: () => void,
) {
  const token = useAccessStore().accessToken;
  const response = await fetch(
    `/agent-api/v1/conversations/${encodeURIComponent(conversationId)}/events?since=${since}`,
    {
      credentials: 'same-origin',
      headers: {
        Accept: 'text/event-stream',
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
      },
      signal,
    },
  );
  if (!response.ok) {
    throw new Error(`事件连接失败（HTTP ${response.status}）`);
  }
  if (!response.body) {
    throw new Error('当前浏览器不支持流式事件');
  }
  onOpen?.();
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  let cursor = since;
  while (true) {
    const { done, value } = await reader.read();
    buffer += decoder.decode(value, { stream: !done }).replaceAll('\r\n', '\n');
    const frames = buffer.split('\n\n');
    buffer = frames.pop() ?? '';
    for (const frame of frames) {
      const data = frame
        .split('\n')
        .filter((line) => line.startsWith('data:'))
        .map((line) => line.slice(5).trimStart())
        .join('\n');
      if (!data) continue;
      const event = JSON.parse(data) as AgentConversationApi.ConversationEvent;
      if (!Number.isSafeInteger(event.seq) || event.seq <= cursor) continue;
      cursor = event.seq;
      onEvent(event);
    }
    if (done) break;
  }
  return cursor;
}

/** 发送文本或附件（用于补充上传文件） */
export function sendAgentMessage(
  conversationId: string,
  data: AgentConversationApi.MessageReq,
) {
  return agentClient.post<AgentConversationApi.Conversation>(
    `/v1/conversations/${conversationId}/messages`,
    data,
  );
}

/** 卡片操作：选择场景、确认映射、修订、确认或取消 */
export function sendAgentAction(
  conversationId: string,
  data: AgentConversationApi.ActionReq,
) {
  return agentClient.post<AgentConversationApi.Conversation>(
    `/v1/conversations/${conversationId}/actions`,
    data,
  );
}

/** 下载导入报表（xlsx） */
export function downloadAgentReport(conversationId: string) {
  return agentClient.download<{
    data: Blob;
    headers: Record<string, string>;
  }>(`/v1/conversations/${conversationId}/report`, {
    responseReturn: 'raw',
  });
}

/**
 * 上传附件到 Java 存储并绑定补录会话，返回 attachmentId。
 * Python 侧通过 Java Bridge 按 attachmentId 读取文件。
 */
export async function uploadAgentAttachment(file: File) {
  const sessionId = await createImportSession();
  const blobs = await uploadFile([file]);
  const blobId = blobs?.[0]?.id;
  if (!blobId) {
    throw new Error('文件上传失败，未取得 blobId');
  }
  return await bindImportAttachment(sessionId, blobId);
}

export { agentImportErrorMessage } from '#/api/mdm/item/agent';
