import { BadRequestException, ConflictException, NotFoundException } from '@nestjs/common';
import { AiReview } from './entities/ai-review.entity';
import type { AiReviewSectionType } from './entities/ai-review.entity';
import type { AiChatServiceContext } from './ai-chat.types';
import { reviewSectionType } from './ai-chat.types';
import type { AuthenticatedUser } from '../authorization';

async function loadReviewForConfirm(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  reviewId: string,
): Promise<AiReview> {
  const review = await context.reviewService.findOwned(reviewId, user.id);
  if (review.status === 'submitted') {
    throw new ConflictException('导入已全部确认，无需重复确认');
  }
  if (review.status === 'expired') {
    throw new ConflictException('导入预览已失效，请重新生成预览');
  }
  return review;
}

async function finalizeReview(
  context: AiChatServiceContext,
  updated: AiReview,
): Promise<Record<string, unknown>> {
  await context.markReviewSubmittedOnMessage(
    updated.assistantMessageId,
    updated.conversationId,
    updated,
  );
  return context.reviewService.serialize(updated);
}

async function logImportOp(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  action: string,
  detail: string,
): Promise<void> {
  await context.opLog?.log({
    userId: user.id,
    username: user.username,
    module: '批量导入',
    action,
    detail,
    targetType: 'ai_review',
    status: 'success',
  });
}

export function assertReviewImportPermissions(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  review: AiReview,
  sectionKey?: string,
  sectionType?: AiReviewSectionType,
): void {
  const sectionPermission: Record<AiReviewSectionType, string> = {
    students: 'student:create',
    rooms: 'room:create',
    transfers: 'occupancy:transfer',
    checkins: 'occupancy:checkin',
  };
  const ability = context.abilityFactory.createForUser(user);
  const sections = context.reviewService.parseSections(review.sectionsJson);
  const types = new Set<AiReviewSectionType>();
  if (sectionType) {
    types.add(sectionType);
  } else if (sectionKey) {
    const section = sections.find((item) => item.key === sectionKey);
    if (!section) throw new NotFoundException(`分表不存在: ${sectionKey}`);
    types.add(reviewSectionType(section));
  } else {
    for (const section of sections) types.add(reviewSectionType(section));
  }
  for (const type of types) {
    context.authorization.assertPermission(ability, sectionPermission[type]);
  }
}

export async function confirmReviewStep(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  reviewId: string,
  sectionKey: string,
): Promise<Record<string, unknown>> {
  const review = await loadReviewForConfirm(context, user, reviewId);
  assertReviewImportPermissions(context, user, review, sectionKey);
  const { review: updated, message } = await context.reviewService.submitSection(
    review.id,
    user.id,
    sectionKey,
  );
  await logImportOp(
    context,
    user,
    '确认导入分表',
    `「${review.title}」分表「${sectionKey}」：${message}`,
  );
  return finalizeReview(context, updated);
}

export async function confirmReviewGroup(
  context: AiChatServiceContext,
  user: AuthenticatedUser,
  reviewId: string,
  type: AiReviewSectionType,
): Promise<Record<string, unknown>> {
  if (type !== 'students' && type !== 'rooms' && type !== 'transfers' && type !== 'checkins') {
    throw new BadRequestException(`业务类型不支持: ${String(type)}`);
  }
  const review = await loadReviewForConfirm(context, user, reviewId);
  assertReviewImportPermissions(context, user, review, undefined, type);
  const { review: updated } = await context.reviewService.submitGroup(review.id, user.id, type);
  const sectionTitles = context.reviewService
    .parseSections(updated.sectionsJson)
    .filter((section) => section.type === type)
    .map((section) => section.title)
    .join('、');
  await logImportOp(
    context,
    user,
    '确认导入分组',
    `「${review.title}」分组「${type}」：${sectionTitles}`,
  );
  return finalizeReview(context, updated);
}
