import api from '../../api';
import { useUserStore } from '../../store/user/userStore';
import type {
  AiApiResponse,
  AiAttachment,
  AiConversation,
  AiImportPreflight,
  AiImportWizard,
  AiMessagePage,
  AiReviewSchema,
  AiReviewSection,
  AiReviewSectionType,
  AiSkill,
} from './types';

const basePath = '/ai/chat/conversations';

export const aiChatApi = {
  listSkills: async () => (await api.get<AiApiResponse<AiSkill[]>>('/ai/chat/skills')).data,
  listConversations: async () => (await api.get<AiApiResponse<AiConversation[]>>(basePath)).data,
  createConversation: async (input?: { title?: string; lockedSkillKey?: string | null }) =>
    (await api.post<AiApiResponse<AiConversation>>(basePath, input ?? {})).data,
  updateConversation: async (
    id: number,
    input: { title?: string; lockedSkillKey?: string | null },
  ) => (await api.patch<AiApiResponse<AiConversation>>(`${basePath}/${id}`, input)).data,
  deleteConversation: (id: number) => api.delete<void>(`${basePath}/${id}`),
  deleteAllConversations: async () =>
    (await api.delete<{ success: boolean; data: { deleted: number } }>(basePath)).data,
  deleteMessage: async (conversationId: number, messageId: number) =>
    (
      await api.delete<AiApiResponse<{ deletedIds: number[] }>>(
        `${basePath}/${conversationId}/messages/${messageId}`,
      )
    ).data,
  uploadAttachment: async (file: File): Promise<AiAttachment> => {
    const form = new FormData();
    form.append('file', file);
    return (
      await api.post<AiApiResponse<AiAttachment>>('/ai/chat/attachments', form, {
        headers: { 'Content-Type': 'multipart/form-data' },
        timeout: 120_000,
      })
    ).data;
  },
  deleteAttachment: (id: number) => api.delete<void>(`/ai/chat/attachments/${id}`),
  confirmReviewStep: async (
    reviewId: string,
    sectionKey: AiReviewSection['key'],
  ): Promise<AiReviewSchema> =>
    (
      await api.post<AiApiResponse<AiReviewSchema>>(
        `/ai/chat/reviews/${reviewId}/steps/${sectionKey}/confirm`,
      )
    ).data,
  confirmReviewGroup: async (
    reviewId: string,
    type: AiReviewSectionType,
  ): Promise<AiReviewSchema> =>
    (
      await api.post<AiApiResponse<AiReviewSchema>>(
        `/ai/chat/reviews/${reviewId}/types/${type}/confirm`,
      )
    ).data,
  listMessages: async (id: number): Promise<AiMessagePage> => {
    const first = (
      await api.get<AiApiResponse<AiMessagePage>>(`${basePath}/${id}/messages`, {
        params: { page: 1, limit: 100 },
      })
    ).data;
    const pageCount = Math.ceil(first.total / first.limit);
    if (pageCount <= 1) return first;
    const rest = await Promise.all(
      Array.from({ length: pageCount - 1 }, (_, index) =>
        api
          .get<AiApiResponse<AiMessagePage>>(`${basePath}/${id}/messages`, {
            params: { page: index + 2, limit: first.limit },
          })
          .then((response) => response.data),
      ),
    );
    return { ...first, items: [first, ...rest].flatMap((page) => page.items) };
  },
};

export function conversationStreamUrl(id: number): string {
  return `/api${basePath}/${id}/stream`;
}

export interface ResolveImportPreflightInput {
  mapping?: Record<string, Record<string, string>>;
  settings?: {
    organization?: string | null;
    updateExisting?: boolean;
    duplicatePolicy?: 'error' | 'skip';
    skipUnmatched?: boolean;
  };
}

export interface ImportPreflightResolveUpdate {
  preflight?: AiImportPreflight;
  wizard?: AiImportWizard;
}

/**
 * 用户在预检卡内确认映射与策略后，调用服务端 resolve 流直接生成导入向导。
 * 与普通对话不同：不新增用户消息，只原位更新目标消息的预检卡/向导卡。
 */
export async function resolveImportPreflight(
  messageId: number,
  input: ResolveImportPreflightInput,
  onUpdate: (update: ImportPreflightResolveUpdate) => void,
): Promise<void> {
  const token = useUserStore.getState().token;
  const response = await fetch(`/api/ai/chat/import/preflight/${messageId}/resolve/stream`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'text/event-stream',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    body: JSON.stringify({
      clientRequestId: crypto.randomUUID(),
      mapping: input.mapping ?? {},
      settings: input.settings ?? {},
    }),
  });
  if (response.status === 401) {
    useUserStore.getState().logout();
    window.location.href = '/login';
    throw new Error('登录已失效');
  }
  if (!response.ok || !response.body) {
    let message = '导入向导生成失败';
    try {
      const body = (await response.json()) as { message?: string; error?: string };
      message = body?.message ?? body?.error ?? message;
    } catch {
      // 保留默认错误信息
    }
    throw new Error(message);
  }
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';
  for (;;) {
    const { done, value } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    const blocks = buffer.split('\n\n');
    buffer = blocks.pop() ?? '';
    for (const block of blocks) {
      const event = /^event:\s*(.+)$/m.exec(block)?.[1]?.trim() ?? 'message';
      const dataLine = /^data:\s*(.+)$/m.exec(block)?.[1]?.trim();
      if (!dataLine || dataLine === '[DONE]') continue;
      let data: Record<string, unknown>;
      try {
        data = JSON.parse(dataLine) as Record<string, unknown>;
      } catch {
        continue;
      }
      if (event === 'error') {
        const message =
          typeof data.message === 'string' ? data.message : '导入向导生成失败';
        throw new Error(message);
      }
      if (event === 'ui.import_preflight' && data.preflight) {
        onUpdate({ preflight: data.preflight as AiImportPreflight });
      } else if (event === 'ui.import_wizard' && data.wizard) {
        onUpdate({ wizard: data.wizard as AiImportWizard });
      }
    }
  }
}
