import { AiReview } from './entities/ai-review.entity';
import type { AiChatServiceContext, AiSseEmitter, ModelToolCall } from './ai-chat.types';
import { buildA2uiArtifact } from './ai-a2ui.artifact';
import { finishToolRun, startToolRun } from './ai-chat.tools';
export async function executeRenderForm(
  context: AiChatServiceContext,
  messageId: number,
  call: ModelToolCall,
  userId: number,
  emit: AiSseEmitter,
): Promise<string> {
  const { run, parsedArgs, startedAt } = await startToolRun(context, messageId, call, emit, {
    toolName: 'render_form',
    skillKey: null,
  });

  try {
    const assistant = await context.messages.findOne({ where: { id: messageId } });
    if (!assistant) throw new Error('assistant message missing');
    const form = await context.formService.createForm(
      { userId, conversationId: assistant.conversationId, assistantMessageId: messageId },
      parsedArgs,
    );
    const expiredForms = await context.formService.expirePreviousForms(
      userId,
      assistant.conversationId,
      form.id,
    );
    await Promise.all(
      expiredForms.map(async (expired) => {
        const oldAssistant = await context.messages.findOne({
          where: { id: expired.assistantMessageId, conversationId: assistant.conversationId },
        });
        const oldA2ui = oldAssistant?.metadata?.a2uiForm;
        if (oldAssistant && oldA2ui && typeof oldA2ui === 'object' && !Array.isArray(oldA2ui)) {
          oldAssistant.metadata = {
            ...oldAssistant.metadata,
            a2uiForm: context.formService.serialize(expired),
          };
          await context.messages.save(oldAssistant);
        }
        const expiredPayload = context.formService.serialize(expired);
        emit('ui.form', { messageId: expired.assistantMessageId, form: expiredPayload });
        emit('ui.artifact', {
          messageId: expired.assistantMessageId,
          artifact: buildA2uiArtifact({
            type: 'form',
            id: expired.id,
            status: 'expired',
            messageId: expired.assistantMessageId,
            conversationId: assistant.conversationId,
            payload: expiredPayload,
          }),
        });
      }),
    );
    assistant.metadata = {
      ...assistant.metadata,
      a2uiForm: context.formService.serialize(form),
    };
    await context.messages.save(assistant);

    await finishToolRun(context, run, call, startedAt, { status: 'success', summary: '已生成表单，等待用户填写' }, emit);
    emit('ui.form', {
      messageId,
      form: context.formService.serialize(form),
    });
    emit('ui.artifact', {
      messageId,
      artifact: buildA2uiArtifact({
        type: 'form',
        id: form.id,
        status: form.status === 'submitted' ? 'submitted' : 'pending',
        messageId,
        conversationId: assistant.conversationId,
        payload: context.formService.serialize(form),
      }),
    });
    return JSON.stringify({
      status: 'success',
      formId: form.id,
      message: '表单已显示给用户，请提示用户填写并提交',
    });
  } catch {
    await finishToolRun(context, run, call, startedAt, { status: 'failed', summary: '表单参数无效', error: '表单参数无效' }, emit);
    return JSON.stringify({ status: 'failed', error: '表单参数无效' });
  }
}

export async function executeRenderReview(
  context: AiChatServiceContext,
  messageId: number,
  call: ModelToolCall,
  userId: number,
  emit: AiSseEmitter,
): Promise<string> {
  const { run, parsedArgs, startedAt } = await startToolRun(context, messageId, call, emit, {
    toolName: 'render_review',
    skillKey: null,
    argumentsData: null,
  });

  try {
    const existingReview = await context.reviewService.findPendingByAssistantMessage(messageId);
    if (existingReview) {
      const denial = `本回合已生成导入预览《${existingReview.title}》，请直接提示用户审阅并确认，不要再次调用 render_review；如需多个分表，应全部合并到同一张预览卡。`;
      await finishToolRun(context, run, call, startedAt, { status: 'failed', summary: denial, error: denial }, emit);
      return JSON.stringify({ status: 'failed', error: denial });
    }
    const assistant = await context.messages.findOne({ where: { id: messageId } });
    if (!assistant) throw new Error('assistant message missing');
    const parsedRecord =
      parsedArgs && typeof parsedArgs === 'object' && !Array.isArray(parsedArgs)
        ? (parsedArgs as Record<string, unknown>)
        : {};
    const attachmentId =
      typeof parsedRecord.attachmentId === 'number' ? parsedRecord.attachmentId : undefined;

    let review: AiReview;
    if (Number.isInteger(attachmentId) && (attachmentId as number) > 0) {
      const [attachment] = await context.attachmentService.requireReadyOwned(userId, [
        attachmentId as number,
      ]);
      if (
        !attachment.mimeType.includes('spreadsheetml') &&
        !attachment.mimeType.includes('excel') &&
        !attachment.mimeType.includes('csv')
      ) {
        throw new Error('附件不是 Excel 文件，无法生成导入预览');
      }
      if (!context.excelReader) throw new Error('Excel 解析器未配置');
      const buffer = await context.attachmentService.readStoredBuffer(attachment);
      const sheets = await context.excelReader.loadSheets(buffer);
      const sections = await context.reviewService.buildSectionsFromWorkbook(sheets, parsedArgs);
      review = await context.reviewService.createReview(
        { userId, conversationId: assistant.conversationId, assistantMessageId: messageId },
        { title: parsedRecord.title, summary: parsedRecord.summary ?? null, sections },
      );
    } else {
      review = await context.reviewService.createReview(
        { userId, conversationId: assistant.conversationId, assistantMessageId: messageId },
        parsedArgs,
      );
    }
    const expiredReviews = await context.reviewService.expirePreviousReviews(
      userId,
      assistant.conversationId,
      review.id,
    );
    await Promise.all(
      expiredReviews.map(async (expired) => {
        const oldAssistant = await context.messages.findOne({
          where: { id: expired.assistantMessageId, conversationId: assistant.conversationId },
        });
        const oldA2ui = oldAssistant?.metadata?.a2uiReview;
        if (oldAssistant && oldA2ui && typeof oldA2ui === 'object' && !Array.isArray(oldA2ui)) {
          oldAssistant.metadata = {
            ...oldAssistant.metadata,
            a2uiReview: context.reviewService.serialize(expired),
          };
          await context.messages.save(oldAssistant);
        }
        emit('ui.review', {
          messageId: expired.assistantMessageId,
          review: context.reviewService.serialize(expired),
        });
        emit('ui.artifact', {
          messageId: expired.assistantMessageId,
          artifact: buildA2uiArtifact({
            type: 'review',
            id: expired.id,
            status: expired.status === 'submitted' ? 'submitted' : 'expired',
            messageId: expired.assistantMessageId,
            conversationId: assistant.conversationId,
            payload: context.reviewService.serialize(expired),
          }),
        });
      }),
    );
    assistant.metadata = {
      ...assistant.metadata,
      a2uiReview: context.reviewService.serialize(review),
    };
    await context.messages.save(assistant);

    await finishToolRun(context, run, call, startedAt, { status: 'success', summary: '已生成导入预览，等待用户确认' }, emit);
    emit('ui.review', {
      messageId,
      review: context.reviewService.serialize(review),
    });
    emit('ui.artifact', {
      messageId,
      artifact: buildA2uiArtifact({
        type: 'review',
        id: review.id,
        status: review.status === 'submitted' ? 'submitted' : 'pending',
        messageId,
        conversationId: assistant.conversationId,
        payload: context.reviewService.serialize(review),
      }),
    });
    return JSON.stringify({
      status: 'success',
      reviewId: review.id,
      message: '导入预览已显示给用户，请提示用户审阅并确认',
    });
  } catch (reason) {
    const errorMessage =
      reason instanceof Error && reason.message ? reason.message.slice(0, 120) : '导入预览参数无效';
    await finishToolRun(context, run, call, startedAt, { status: 'failed', summary: errorMessage, error: errorMessage }, emit);
    return JSON.stringify({ status: 'failed', error: errorMessage });
  }
}

export async function executeRenderChart(
  context: AiChatServiceContext,
  messageId: number,
  call: ModelToolCall,
  emit: AiSseEmitter,
): Promise<string> {
  const { run, parsedArgs, startedAt } = await startToolRun(context, messageId, call, emit, {
    toolName: 'render_chart',
    skillKey: null,
    argumentsData: null,
  });

  try {
    const assistant = await context.messages.findOne({ where: { id: messageId } });
    if (!assistant) throw new Error('assistant message missing');
    const chart = context.chartService.createChart(parsedArgs);
    const existingCharts = assistant.metadata?.a2uiChart;
    const charts = Array.isArray(existingCharts)
      ? [...existingCharts]
      : existingCharts
        ? [existingCharts]
        : [];
    charts.push(context.chartService.serialize(chart));
    assistant.metadata = {
      ...assistant.metadata,
      a2uiChart: charts,
    };
    await context.messages.save(assistant);

    await finishToolRun(context, run, call, startedAt, { status: 'success', summary: '已生成图表' }, emit);
    emit('ui.chart', {
      messageId,
      chart: context.chartService.serialize(chart),
    });
    emit('ui.artifact', {
      messageId,
      artifact: buildA2uiArtifact({
        type: 'chart',
        id: chart.id,
        status: 'pending',
        messageId,
        conversationId: assistant.conversationId,
        payload: context.chartService.serialize(chart),
      }),
    });
    return JSON.stringify({
      status: 'success',
      chartId: chart.id,
      message: '图表已显示给用户',
    });
  } catch {
    await finishToolRun(context, run, call, startedAt, { status: 'failed', summary: '图表参数无效', error: '图表参数无效' }, emit);
    return JSON.stringify({ status: 'failed', error: '图表参数无效' });
  }
}

export {
  compactImportWizard,
  executeStartImportWizard,
} from './ai-chat.tool-actions.import';
