import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { ExamPaper } from 'src/assessment-evaluation/entities/entities-exam-paper-manager/exam-paper.entity';
import { PagingExamPaperDto } from 'src/assessment-evaluation/dto/dtos-exam-paper-manager/exam-paper/paging-exam-paper.dto';
import { UpdateExamPaperDto } from 'src/assessment-evaluation/dto/dtos-exam-paper-manager/exam-paper/update-exam-paper.dto';
import { CreateExamPaperDto } from 'src/assessment-evaluation/dto/dtos-exam-paper-manager/exam-paper/create-exam-paper.dto';
import { QuestionsForPaper } from 'src/assessment-evaluation/entities/entities-exam-paper-manager/questions-for-paper.entity';
import { TokenDataEntity } from 'src/common/entities/token-data.entity';
import { Exam } from 'src/assessment-evaluation/entities/entities-exam-manager/exam.entity';
// import { ExamPaperClassify } from 'src/assessment-evaluation/entities/entities-exam-paper-manager/exam-paper-classify.entity';

@Injectable()
export class ExamPaperService {
  constructor(
    @InjectRepository(ExamPaper)
    private ExamPaperRep: Repository<ExamPaper>, // @InjectRepository(ExamPaperClassify) // private ExamPaperClassifyRep: Repository<ExamPaperClassify>,
    @InjectRepository(QuestionsForPaper)
    private QuestionsForPaper: Repository<QuestionsForPaper>, // @InjectRepository(ExamPaperClassify) // private ExamPaperClassifyRep: Repository<ExamPaperClassify>,
    @InjectRepository(Exam)
    private ExamRep: Repository<Exam>, // @InjectRepository(ExamPaperClassify) // private ExamPaperClassifyRep: Repository<ExamPaperClassify>,
  ) {}

  /* 
    创建试卷
  */
  async create(CreateExamPaperDto: any) {
    // const hasDifficultyLevel = await this.ExamPaperClassifyRep.findOneBy({
    //   delFlag: 0,
    //   id: createQuestionDto.difficultyLevel,
    // });
    // if (!hasDifficultyLevel) {
    //   throw '[classifyId]字段 - 类型不存在';
    // }

    return await this.ExamPaperRep.save(CreateExamPaperDto);
  }
  /*
    获取某个试卷
  */
  async findOne(id: number) {
    const paperInfo = await this.ExamPaperRep.findOneBy({ id });
    let sql = `select
    q.*,
    qfp.exam_paper_id as examPaperId,
    qfp.type as typeId,
    qt.element as element,
    qt.name as type,
    qfp.score as itemScore,
    qfp.is_fixed as isFixed
  from
    questions_for_paper qfp
  left join question q on
    q.id = qfp.question_id
  left join question_type qt on
    qt.id = qfp.type
  where
    qfp.del_flag = 0`;
    if (paperInfo.id) {
      sql += ` and qfp.exam_paper_id=${paperInfo.id}`;
    }
    const paperQuestionsInfo = await this.QuestionsForPaper.query(sql);
    const fixdQuestions = paperQuestionsInfo.filter(
      (item) => item.isFixed == 1,
    );
    const randQuestions = paperQuestionsInfo.filter(
      (item) => item.isFixed == 0,
    );
    // paperInfo['questionInfo'] = {
    //   fixdQuestions,
    //   randQuestions,
    // };
    const item: CreateExamPaperDto = {
      ...paperInfo,
      questionInfo: {
        fixdQuestions,
        randQuestions,
      },
    };
    return item;
  }
  /* 
    分页查询模拟考试
  */
  async pagingSim(
    pagingInfo: PagingExamPaperDto,
    token: TokenDataEntity,
    delFlag = -1,
  ) {
    const { currentPage, pageSize, classifyId, title, isPractive, status } =
      pagingInfo;
    type PagingParamsMap = {
      delFlag: number;
      classifyId: number | null;
      title: any | null;
      type: number | null;
      difficultyLevel: number | null;
      isPracticeExam: number;
      status: number | null;
      creator: string | null;
    };

    // eslint-disable-next-line prefer-const
    let whereMap: PagingParamsMap = {
      delFlag: delFlag,
      classifyId: null,
      title: null,
      type: null,
      difficultyLevel: null,
      isPracticeExam: 0,
      status: null,
      creator: null,
    };
    // console.log(pagingInfo, whereMap);
    try {
      let sql = `select
      ep.id as id,
      ep.title as title,
      ep.paper_desc as paperDesc,
      ep.paper_duration  as duration,
      ep.total_score  as totalScore ,
      ep.pass_percent  as passPercent,
      ep.questions_is_random_sort  as questionsIsRandomSort,
      ep.options_is_random_sort  as optionsIsRandomSort,
      ep.question_count  as questionCount,
      ep.status as status,
      ep.is_practice_exam as isPracticeExam,
      users.name as creator ,
      ep.creator as creatorId,
      ep.classify_id as classifyId,
      qc.name as classify,
      ex.id as exam_id,
      soe.id as studentOnlineExamId,
      ex.del_flag as exDel,
      ifnull(durationTable.duration,0) as myDuration,
      ifnull(mistakTable2.mistakes,0)  as mistakes ,
      ifnull(scoreTemp.userScore,0) as myScore,
      date_format(ep.create_time, '%Y-%m-%d %H:%i:%S') as createTime
    from
      exam_paper ep
    left join user users on
      ep.creator = users.id
    left join exam_paper_classify qc on
      ep.classify_id = qc.id
      left join exam ex on ex.exam_paper_id  = ep.id
      left join student_online_exam soe  on soe.exam_id  = ex.id
      
            left join (select oeh2.online_exam_id as online_exam_id,oeh2.create_time ct ,ifnull(scoreSum.userScore,0)as userScore  
	from online_exam_history oeh2 left join (
		select sum(eqr.score) as userScore,eqr.history_id as historyId  
		from exam_questions_result eqr where eqr.del_flag = 0 group by eqr.history_id
	) as scoreSum on 
	scoreSum.historyId = oeh2.id  inner join 
	(select max(oehx.create_time) mtime ,oehx.online_exam_id onlineId,max(oehx.id) nid  from online_exam_history oehx group by oehx.online_exam_id ) stb
	on stb.nid = oeh2.id  where oeh2.is_grade_paper =1) as scoreTemp on scoreTemp.online_exam_id = soe.id 

	left join (select oeh2.online_exam_id as online_exam_id ,ifnull(mistakeTable.mistakes,0)as mistakes  
	from online_exam_history oeh2 left join (
		select count(1) as mistakes,eqr2.history_id as historyId   from exam_questions_result eqr2 
	where eqr2.score< eqr2.question_score and eqr2.del_flag = 0
	group by eqr2.history_id
	) as mistakeTable on 
	mistakeTable.historyId = oeh2.id
	inner join (select max(oehx.create_time) mtime ,oehx.online_exam_id onlineId,max(oehx.id) nid  from online_exam_history oehx group by oehx.online_exam_id ) stb
	on stb.nid = oeh2.id  where oeh2.is_grade_paper =1) as mistakTable2 on mistakTable2.online_exam_id = soe.id 
	
	left join (select (oeh.report_time - unix_timestamp(oeh.create_time)*1000)+0 as duration,oeh.online_exam_id   from online_exam_history oeh 
	inner join (select max(oehx.create_time) mtime ,oehx.online_exam_id onlineId,max(oehx.id) nid  from online_exam_history oehx group by oehx.online_exam_id ) stb
	on stb.nid = oeh.id) as durationTable on durationTable.online_exam_id = soe.id
    where
      ep.del_flag = ${delFlag} `;
      if (isPractive) {
        sql += ` AND ep.is_practice_exam=${isPractive} AND ep.creator = '${token.userId}'`;
        whereMap.isPracticeExam = isPractive;
        whereMap.creator = token.userId;
      } else {
        sql += ` AND ep.is_practice_exam =0`;
      }
      if (status != null) {
        sql += ` AND ep.status=${status}`;
        whereMap.status = status;
      }
      if (classifyId) {
        sql += ` AND ep.classify_id = ${classifyId}`;
        whereMap.classifyId = classifyId;
      }
      if (title) {
        sql += ` AND ep.title LIKE '%${title}%'`;
        whereMap.title = Like(`%${title}%`);
      }
      sql += `
    order by
    ep.id desc limit ?,?`;
      const getPagingQuestions = await this.ExamPaperRep.query(sql, [
        +(currentPage - 1) * pageSize,
        +pageSize,
      ]);
      // console.log(sql);
      const total = await this.ExamPaperRep.countBy(whereMap);
      return { total, currentPage, pageSize, data: getPagingQuestions };
    } catch (err) {
      throw '分页查询失败，错误详情：' + err;
    }
  }

  /* 
    分页查询
  */
  async paging(
    pagingInfo: PagingExamPaperDto,
    token: TokenDataEntity,
    delFlag = 0,
  ) {
    const { currentPage, pageSize, classifyId, title, isPractive, status } =
      pagingInfo;
    type PagingParamsMap = {
      delFlag: number;
      classifyId: number | null;
      title: any | null;
      type: number | null;
      difficultyLevel: number | null;
      isPracticeExam: number;
      status: number | null;
      creator: string | null;
    };

    // eslint-disable-next-line prefer-const
    let whereMap: PagingParamsMap = {
      delFlag: delFlag,
      classifyId: null,
      title: null,
      type: null,
      difficultyLevel: null,
      isPracticeExam: 0,
      status: null,
      creator: null,
    };
    // console.log(pagingInfo, whereMap);
    try {
      let sql = `select
      exam.id as id,
      exam.title as title,
      exam.paper_desc as paperDesc,
      exam.share as share,
      exam.paper_duration  as duration,
      exam.total_score  as totalScore ,
      exam.pass_percent  as passPercent,
      exam.questions_is_random_sort  as questionsIsRandomSort,
      exam.options_is_random_sort  as optionsIsRandomSort,
      exam.question_count  as questionCount,
      exam.status as status,
      exam.is_practice_exam as isPracticeExam,
      users.name as creator ,
      exam.creator as creatorId,
      exam.classify_id as classifyId,
      qc.name as classify,
      date_format(exam.create_time, '%Y-%m-%d %H:%i:%S') as createTime
    from
      exam_paper exam
    left join user users on
      exam.creator = users.id
    left join exam_paper_classify qc on
      exam.classify_id = qc.id
    where
      exam.del_flag = ${delFlag} `;
      if (isPractive) {
        sql += ` AND exam.is_practice_exam=${isPractive} AND exam.creator = '${token.userId}'`;
        whereMap.isPracticeExam = isPractive;
        whereMap.creator = token.userId;
      } else {
        sql += ` AND exam.is_practice_exam =0`;
      }
      if (status != null) {
        sql += ` AND exam.status=${status}`;
        whereMap.status = status;
      }
      if (classifyId) {
        sql += ` AND exam.classify_id = ${classifyId}`;
        whereMap.classifyId = classifyId;
      }
      if (title) {
        sql += ` AND exam.title LIKE '%${title}%'`;
        whereMap.title = Like(`%${title}%`);
      }
      sql += `
    order by
    exam.id desc limit ?,?`;
      const getPagingQuestions = await this.ExamPaperRep.query(sql, [
        +(currentPage - 1) * pageSize,
        +pageSize,
      ]);
      // console.log(sql);
      const total = await this.ExamPaperRep.countBy(whereMap);
      return { total, currentPage, pageSize, data: getPagingQuestions };
    } catch (err) {
      throw '分页查询失败，错误详情：' + err;
    }
  }
  /* 
    更新试卷
  */
  async update(id: number, UpdateExamPaperDto: UpdateExamPaperDto) {
    await this.ExamPaperRep.update(id, UpdateExamPaperDto);
    const item = await this.ExamPaperRep.findOneBy({ delFlag: 0, id });
    return item;
  }

  /* 
    批量移动试卷到分类中
   */
  async batchMovePaperToClassify(ids: number[], classifyId: number) {
    return await this.ExamPaperRep.query(`
    update exam_paper set classify_id=${classifyId} where id in (${ids.join(
      ',',
    )})
    `);
  }
  /**
   * 检查试卷被哪些考试引用
   * @param paperId 试卷ID
   * @returns 引用改试卷的考试列表
   */
  async checkPaperHasQuote(paperId: number) {
    return await this.ExamPaperRep.query(
      `select e.title as title,(case 
      when now()>=e.exam_start_time and now()<=e.exam_end_time 
    then 1 when now()<e.exam_start_time then 0 
    when now()>e.exam_end_time then 2
    end) as status from exam e where e.exam_paper_id  = ? and e.del_flag =0 `,
      [paperId],
    );
  }
  async removeAllQuestionByPaperId(paperId: number) {
    const rows = await this.ExamPaperRep.query(
      `update questions_for_paper set del_flag=1 where del_flag=0 and exam_paper_id=${paperId}`,
    );
    return rows;
  }
  async remove(id: number) {
    await this.ExamPaperRep.query(`delete from exam_paper where id = ${id}`);
    const exam = await this.ExamRep.findOneBy({
      examPaperId: id,
      delFlag: -1,
      classifyId: -1,
    });
    if (exam) {
      await this.ExamPaperRep.query(
        `delete from student_online_exam soe where soe.exam_id = ${exam.id} and soe.del_flag =-1`,
      );
      await this.ExamPaperRep.query(
        `delete from exam where exam_paper_id = ${id} and classify_id = -1 and del_flag  = -1`,
      );
    }
    const rows = await this.removeAllQuestionByPaperId(id);
    return rows;
  }
}
