import type { AiChatServiceContext, AiSseEmitter } from './ai-chat.types';
import { DEFAULT_TITLE } from './ai-chat.types';
import type { AuthenticatedUser } from '../authorization';
import { suggestNextStepsForPrincipal } from '../agent-context/business-context.service';
import { buildA2uiArtifact } from './ai-a2ui.artifact';
import { A2uiSubmissionsService } from './ai-a2ui-submissions.service';
import { AiA2uiSubmission } from './entities';
import { assertReviewImportPermissions } from './ai-chat.review-confirm';
import { persistExchange, runGenerationAndRelease } from './ai-chat.submissions.runtime';

function submissionsService(
  context: AiChatServiceContext,
): A2uiSubmissionsService {
  return (
    context.a2uiSubmissions ??
    new A2uiSubmissionsService(context.dataSource.getRepository(AiA2uiSubmission))
  );
}

export async function submitForm(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  formId: string,
  dto: { values: Record<string, unknown>; clientRequestId: string; reasoningEffort?: string | null },
  signal: AbortSignal,
  emit: AiSseEmitter,
  onReady: () => void,
): Promise<void> {
  const form = await context.formService.findOwnedPending(formId, user.id);
  const conversation = await context.requireOwnedConversation(user.id, form.conversationId);
  const values = context.formService.validateValues(form, dto.values);
  const effectiveSkillKey = conversation.lockedSkillKey ?? null;
  context.assertSkillAvailable(user, effectiveSkillKey);

  const submissions = submissionsService(context);
  const recorded = await submissions.recordSubmission({
    artifactId: formId,
    clientRequestId: dto.clientRequestId,
    status: 'created',
  });
  if (!recorded.created) {
    emit('error', { message: '该表单已提交过，请勿重复提交' });
    emit('done', {});
    return;
  }

  await context.acquireConversation(conversation.id);
  try {
    const summary = `已提交表单「${form.title}」`;
    const saved = await context.dataSource.transaction(async (manager) =>
      persistExchange(
        context,
        manager,
        conversation,
        user.id,
        summary,
        dto.clientRequestId,
        effectiveSkillKey,
        {
          a2uiSubmit: {
            formId: form.id,
            formTitle: form.title,
            values,
            submissionId: String(recorded.submission.id),
            fieldErrors: [],
          },
        },
        undefined,
        conversation.title === DEFAULT_TITLE ? form.title.slice(0, 30) : undefined,
      ),
    );

    await context.formService.markSubmitted(form, values);
    await context.markFormSubmittedOnMessage(form.assistantMessageId, conversation.id);
    emit('ui.artifact', {
      messageId: form.assistantMessageId,
      artifact: buildA2uiArtifact({
        type: 'form',
        id: form.id,
        status: 'submitted',
        messageId: form.assistantMessageId,
        conversationId: conversation.id,
        payload: { ...context.formService.serialize(form), status: 'submitted' },
      }),
    });

    await runGenerationAndRelease(context, {
      user,
      conversation,
      userMessage: saved.userMessage,
      assistant: saved.assistantMessage,
      clientRequestId: dto.clientRequestId,
      effectiveSkillKey,
      focusContent: summary,
      reasoningEffort: dto.reasoningEffort ?? null,
      signal,
      emit,
      onReady,
    }, conversation.id);
  } finally {
    context.activeConversations.delete(conversation.id);
  }
}

export async function submitReview(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  reviewId: string,
  dto: { clientRequestId: string; reasoningEffort?: string | null },
  signal: AbortSignal,
  emit: AiSseEmitter,
  onReady: () => void,
): Promise<void> {
  const review = await context.reviewService.findOwnedPending(reviewId, user.id);
  const conversation = await context.requireOwnedConversation(user.id, review.conversationId);
  const effectiveSkillKey = conversation.lockedSkillKey ?? null;
  context.assertSkillAvailable(user, effectiveSkillKey);
  assertReviewImportPermissions(context, user, review);

  const submissions = submissionsService(context);
  const recorded = await submissions.recordSubmission({
    artifactId: reviewId,
    clientRequestId: dto.clientRequestId,
    status: 'created',
  });
  if (!recorded.created) {
    emit('error', { message: '该导入预览已确认过，请勿重复提交' });
    emit('done', {});
    return;
  }

  await context.acquireConversation(conversation.id);
  try {
    const { review: updatedReview, result } = await context.reviewService.submitAll(
      review.id,
      user.id,
    );
    const sectionTypes = context.reviewService
      .parseSections(review.sectionsJson)
      .map((section) => section.type)
      .filter(Boolean);
    const completedStageKeys = [
      ...new Set(
        sectionTypes.map((type) =>
          type === 'students'
            ? 'profile'
            : type === 'rooms'
              ? 'room'
              : 'checkin',
        ),
      ),
    ];
    const nextSteps = suggestNextStepsForPrincipal(
      { permissions: user.permissions, isSuperAdmin: user.isSuperAdmin },
      completedStageKeys,
    ).map((step) => ({ key: step.key, label: step.label }));
    const summary = `已确认导入「${review.title}」：${result.message}`;
    await context.opLog?.log({
      userId: user.id,
      username: user.username,
      module: '批量导入',
      action: '确认导入全部',
      detail: `「${review.title}」${result.message}`,
      targetType: 'ai_review',
      status: 'success',
    });
    const saved = await context.dataSource.transaction(async (manager) => {
      const exchange = await persistExchange(
        context,
        manager,
        conversation,
        user.id,
        summary,
        dto.clientRequestId,
        effectiveSkillKey,
        {
          a2uiReviewSubmit: {
            reviewId: review.id,
            reviewTitle: review.title,
            resultMessage: result.message,
            submissionId: String(recorded.submission.id),
            nextSteps,
          },
        },
        undefined,
        conversation.title === DEFAULT_TITLE ? review.title.slice(0, 30) : undefined,
      );
      return { ...exchange, result };
    });

    const serialized = context.reviewService.serialize(updatedReview);
    onReady();
    emit('ui.review', {
      messageId: updatedReview.assistantMessageId,
      review: serialized,
    });
    emit('ui.artifact', {
      messageId: updatedReview.assistantMessageId,
      artifact: buildA2uiArtifact({
        type: 'review',
        id: review.id,
        status: 'submitted',
        messageId: updatedReview.assistantMessageId,
        conversationId: conversation.id,
        payload: serialized,
      }),
    });
    await context.markReviewSubmittedOnMessage(
      updatedReview.assistantMessageId,
      conversation.id,
      updatedReview,
    );

    await runGenerationAndRelease(context, {
      user,
      conversation,
      userMessage: saved.userMessage,
      assistant: saved.assistantMessage,
      clientRequestId: dto.clientRequestId,
      effectiveSkillKey,
      focusContent: saved.result.message,
      reasoningEffort: dto.reasoningEffort ?? null,
      signal,
      emit,
      onReady,
    }, conversation.id);
  } finally {
    context.activeConversations.delete(conversation.id);
  }
}
