import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';
import { CreateDto } from 'src/common/dto/create.dto';
import { Subject } from 'src/train/entities/subject/subject.entity';
import { SubjectStep } from 'src/train/entities/subject/subject-step.entity';
import { SubjectHasDevice } from 'src/train/entities/subject/subject-has-device.entity';
import { PaginationDTO } from 'src/assessment-evaluation/dto/pagination.dto';
import { Device } from 'src/train/entities/device/device.entity';
import { Resource } from 'src/resource/entities/resource.entity';
import { DeviceNumberPosition } from 'src/train/entities/device/device-number-position.entity';
/* TODO：分页查。修改状态操作。 */
@Injectable()
export class SubjectService {
  constructor(
    // 科目表
    @InjectRepository(Subject)
    private subjectRep: Repository<Subject>,

    // 步骤表
    @InjectRepository(SubjectStep)
    private subjectStepRep: Repository<SubjectStep>,

    // 包含设备表
    @InjectRepository(SubjectHasDevice)
    private subjectHasDeviceRep: Repository<SubjectHasDevice>,
  ) {}
  /**
   * 创建科目
   * @param createItemDto
   * @returns
   */
  async create(createItemDto: CreateSubjectItemDto, token: any) {
    const userId = token.userId;
    // await this.subjectRep.insert(createItemDto);
    // await this.subjectRep.query('START TRANSACTION');
    // try {
    const subject = await this.subjectRep.save(createItemDto, {
      transaction: false,
    });
    const devices = createItemDto.device;
    if (devices && devices.length > 0) {
      const dList = devices.map((item) => ({
        creator: userId,
        updater: userId,
        device: item,
        subject: subject.id,
      }));
      await this.subjectHasDeviceRep.insert(dList);
    }
    const steps = createItemDto.step;
    if (steps && steps.length > 0) {
      const stepList = steps.map((item) => ({
        creator: userId,
        updater: userId,
        subject: subject.id,
        ...item,
      }));
      await this.subjectStepRep.insert(stepList);
    }

    //   await this.subjectRep.query('COMMIT');
    // } catch (error) {
    //   await this.subjectRep.query('ROLLBACK'); // 回滚事务
    //   throw error;
    // }
    return subject;
  }
  /**
   * 更新科目
   * @param id
   * @param updateItemDto
   * @returns
   */
  async update(id: number, updateItemDto: UpdateSubjectItemDto) {
    const userId = updateItemDto.creator;
    await this.subjectHasDeviceRep.delete({ subject: id });
    await this.subjectStepRep.delete({ subject: id });
    const devices = updateItemDto.device;
    if (devices && devices.length > 0) {
      const dList = devices.map((item) => ({
        creator: userId,
        updater: userId,
        device: item,
        subject: id,
      }));
      await this.subjectHasDeviceRep.insert(dList);
    }
    const steps = updateItemDto.step;
    if (steps && steps.length > 0) {
      const stepList = steps.map((item) => ({
        creator: userId,
        updater: userId,
        subject: id,
        ...item,
      }));
      await this.subjectStepRep.insert(stepList);
    }
    delete updateItemDto.device;
    delete updateItemDto.step;
    delete updateItemDto['pdf_name'];
    return this.subjectRep.update(id, updateItemDto);
  }
  /**
   * 批量删除科目,假删
   * @param id
   * @returns
   */
  async remove(ids: number[]) {
    return await this.subjectRep.update(ids, { delFlag: 1 });
  }
  /**
   * 修改科目状态
   * @param id
   * @returns
   */
  async changeSubjectStatus(id: number, status: number) {
    const res = await this.subjectRep.update(id, { status });
    if (res.affected == 0) {
      throw '修改失败';
    }
    return '修改成功';
  }
  async details(id: number) {
    return await this.subjectRep
      .createQueryBuilder('subject')
      .andWhere({ delFlag: 0, id })
      .leftJoinAndMapOne(
        'subject.pdf_name',
        Resource,
        'r',
        'r.diskname = subject.pdf',
      )
      .leftJoinAndMapMany(
        '',
        SubjectHasDevice,
        'shd',
        'shd.subject = subject.id',
      )
      .leftJoinAndMapMany('subject.device', Device, 'd', 'd.id= shd.device')
      .leftJoinAndMapMany(
        'subject.step',
        SubjectStep,
        'step',
        'step.subject=subject.id',
      )
      .orderBy('step.sort', 'ASC')
      .getOne();
  }
  async paging(pageInfo: PagingSubjectListDto) {
    // eslint-disable-next-line prefer-const
    let whereParam: any = {
      delFlag: 0,
    };
    if (pageInfo.classify) whereParam.classify = pageInfo.classify;
    if (pageInfo.train) whereParam.train = pageInfo.train;
    if (pageInfo.name) whereParam.name = Like(`%${pageInfo.name}%`);
    if (pageInfo.status) whereParam.status = pageInfo.status || 1;
    const res: any = await this.subjectRep
      .createQueryBuilder('subject')
      .andWhere(whereParam)
      .leftJoinAndMapMany(
        '',
        SubjectHasDevice,
        'shd',
        'shd.subject = subject.id',
      )
      .leftJoinAndMapMany('subject.devices', Device, 'd', 'd.id= shd.device')
      .leftJoinAndMapOne(
        'd.pos',
        DeviceNumberPosition,
        'pos',
        'd.position=pos.id',
      )
      .orderBy('subject.id', 'DESC')
      .skip((pageInfo.currentPage - 1) * pageInfo.pageSize)
      .take(pageInfo.pageSize)
      .getManyAndCount();
    return {
      data: res[0],
      total: res[1],
    };
  }
}

export class CreateSubjectItemDto extends CreateDto {
  @ApiProperty({ description: '科目名' })
  @IsNotEmpty({ message: '科目名不能为空' })
  name: string;

  @ApiProperty({ description: '科目说明', required: false })
  comment: string;
  @ApiProperty({
    description: '操作规程URL',
    required: false,
  })
  pdf: string;

  @ApiProperty({ description: '科目分类' })
  @IsNotEmpty({ message: '科目分类不能为空' })
  classify: number;

  @ApiProperty({ description: '训练类型' })
  @IsNotEmpty({ message: '训练类型不能为空' })
  train: number;

  @ApiProperty({ description: '科目状态,默认为0', required: false })
  status: number;

  @ApiProperty({
    description: '科目步骤们',
    default: [
      {
        sort: 1,
        duration: 1,
        comment: '',
        device: 1,
        part: 1,
        operation: 1,
      },
    ],
  })
  step?: {
    sort: number;
    duration: number;
    comment: string;
    device: number;
    part: string;
    operation: string;
  }[];

  @ApiProperty({
    description: '科目中包含的操作设备们',
    default: [1],
  })
  device?: number[];
}

export class UpdateSubjectItemDto extends CreateDto {
  @ApiProperty({ description: '科目名' })
  name: string;

  @ApiProperty({ description: '科目说明', required: false })
  comment: string;

  @ApiProperty({
    description: '操作规程URL',
    required: false,
  })
  pdf: string;

  @ApiProperty({ description: '科目分类' })
  classify: number;

  @ApiProperty({ description: '训练类型' })
  train: number;

  @ApiProperty({ description: '科目状态,默认为0', required: false })
  status: number;

  @ApiProperty({
    description: '科目步骤们',
    default: [
      {
        sort: 1,
        duration: 1,
        comment: '',
        device: 1,
        part: 1,
        operation: 1,
      },
    ],
  })
  step?: {
    sort: number;
    duration: number;
    comment: string;
    device: number;
    part: string;
    operation: string;
  }[];

  @ApiProperty({
    description: '科目中包含的操作设备们',
    default: [1],
  })
  device?: number[];
}

export class PagingSubjectListDto extends PaginationDTO {
  @ApiProperty({ description: '科目分类', required: false })
  classify: number;

  @ApiProperty({ description: '训练类型', required: false })
  train: number;

  @ApiProperty({ description: '科目名称模糊', required: false })
  name: string;

  @ApiProperty({ description: '科目状态', required: false, default: 1 })
  status: string;
}

export class ChangeSubjectStatusDto {
  @ApiProperty({ description: '科目ID', required: true })
  @IsNotEmpty({ message: '修改科目状态必须传入科目ID' })
  id: number;

  @ApiProperty({ description: '科目状态', required: true, default: 1 })
  @IsNotEmpty({ message: '修改科目状态必须传入状态' })
  status: number;
}
export class SubjectDetailsDto {
  @ApiProperty({ description: '科目ID', required: true })
  @IsNotEmpty({ message: '修改科目状态必须传入科目ID' })
  id: number;
}
