import { Controller } from "@nestjs/common";
import { GrpcMethod } from "@nestjs/microservices";
import { QuestionsService } from "../questions/questions.service.js";
import type { Question } from "../questions/questions.schema.js";
import type {
  CreateQuestionRequest,
  BatchCreateQuestionsRequest,
  BatchCreateQuestionsResponse,
  GetQuestionRequest,
  ListQuestionsRequest,
  ListQuestionsResponse,
  UpdateQuestionRequest,
  DeleteQuestionRequest,
  PublishQuestionRequest,
  SearchQuestionsRequest,
  SearchQuestionsResponse,
  GrpcQuestion,
  Empty,
} from "./grpc-types.js";

function toGrpcQuestion(q: Question): GrpcQuestion {
  return {
    id: q.id,
    knowledge_point_id: q.knowledgePointId,
    type: q.type,
    content: q.content,
    options: q.options ?? null,
    answer: q.answer,
    explanation: q.explanation ?? "",
    difficulty: q.difficulty,
    status: q.status,
    source: q.source,
    created_by: q.createdBy,
    metadata: q.metadata ?? null,
    created_at: q.createdAt.getTime(),
    updated_at: q.updatedAt.getTime(),
  };
}

@Controller()
export class QuestionGrpcController {
  constructor(private readonly service: QuestionsService) {}

  @GrpcMethod("QuestionService", "CreateQuestion")
  async createQuestion(data: CreateQuestionRequest): Promise<GrpcQuestion> {
    const { id } = await this.service.createQuestion({
      knowledgePointId: data.knowledge_point_id,
      type: data.type,
      content: data.content,
      options: data.options ?? null,
      answer: data.answer,
      explanation: data.explanation,
      difficulty: data.difficulty,
      source: data.source,
      createdBy: data.created_by,
      metadata: data.metadata ?? null,
    });
    const question = await this.service.getQuestion(id);
    return toGrpcQuestion(question);
  }

  @GrpcMethod("QuestionService", "BatchCreateQuestions")
  async batchCreateQuestions(
    data: BatchCreateQuestionsRequest,
  ): Promise<BatchCreateQuestionsResponse> {
    const ids: string[] = [];
    const failed: { index: number; error: string }[] = [];

    for (let i = 0; i < (data.questions ?? []).length; i++) {
      const q = data.questions?.[i];
      if (!q) continue;
      try {
        const { id } = await this.service.createQuestion({
          knowledgePointId: q.knowledge_point_id,
          type: q.type,
          content: q.content,
          options: q.options ?? null,
          answer: q.answer,
          explanation: q.explanation,
          difficulty: q.difficulty,
          source: q.source,
          createdBy: q.created_by,
          metadata: q.metadata ?? null,
        });
        ids.push(id);
      } catch (err) {
        failed.push({
          index: i,
          error: err instanceof Error ? err.message : String(err),
        });
      }
    }

    return { ids, failed };
  }

  @GrpcMethod("QuestionService", "GetQuestion")
  async getQuestion(data: GetQuestionRequest): Promise<GrpcQuestion> {
    const question = await this.service.getQuestion(data.id);
    return toGrpcQuestion(question);
  }

  @GrpcMethod("QuestionService", "ListQuestions")
  async listQuestions(
    data: ListQuestionsRequest,
  ): Promise<ListQuestionsResponse> {
    const pageSize = data.page_size ?? 20;
    const page = data.page_token ? Number(data.page_token) : 1;
    const questions = await this.service.list({
      knowledgePointId: data.knowledge_point_id,
      type: data.type,
      difficulty: data.difficulty,
      status: data.status,
      page,
      pageSize,
    });
    return {
      questions: questions.map(toGrpcQuestion),
      next_page_token: questions.length === pageSize ? String(page + 1) : "",
    };
  }

  @GrpcMethod("QuestionService", "UpdateQuestion")
  async updateQuestion(data: UpdateQuestionRequest): Promise<GrpcQuestion> {
    await this.service.updateQuestion(data.id, {
      content: data.content,
      answer: data.answer,
      status: data.status,
      options: data.options,
      explanation: data.explanation,
      difficulty: data.difficulty ?? undefined,
    });
    const question = await this.service.getQuestion(data.id);
    return toGrpcQuestion(question);
  }

  @GrpcMethod("QuestionService", "DeleteQuestion")
  async deleteQuestion(data: DeleteQuestionRequest): Promise<Empty> {
    await this.service.deleteQuestion(data.id);
    return {};
  }

  @GrpcMethod("QuestionService", "PublishQuestion")
  async publishQuestion(data: PublishQuestionRequest): Promise<Empty> {
    await this.service.updateQuestion(data.id, { status: "published" });
    return {};
  }

  @GrpcMethod("QuestionService", "SearchQuestions")
  async searchQuestions(
    data: SearchQuestionsRequest,
  ): Promise<SearchQuestionsResponse> {
    // P4 阶段：使用 MySQL LIKE 搜索；P5 引入 ES 后替换为全文检索
    const pageSize = data.page_size ?? 20;
    const page = data.page_token ? Number(data.page_token) : 1;
    const questions = await this.service.list({
      knowledgePointId: data.knowledge_point_id,
      type: data.type,
      difficulty: data.difficulty,
      page,
      pageSize,
    });
    return {
      questions: questions.map(toGrpcQuestion),
      total: questions.length,
      next_page_token: questions.length === pageSize ? String(page + 1) : "",
    };
  }
}
