import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { PageInfoEntity } from 'src/common/entities/page-info.entity';
import { Resource } from 'src/resource/entities/resource.entity';
import { DataSource, EntityManager, Repository } from 'typeorm';
import { UpdatePasswordDto } from '../dto/update-password.dto';
import { UserDto } from '../dto/user.dto';
import { Role } from '../entities/role.entity';
import { TeacherStudent } from '../entities/teacher-student.entity';
import { User } from '../entities/user.entity';

@Injectable()
export class UserService {
  constructor(
    private dataSource: DataSource,

    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}
  async create(userDto: UserDto) {
    const hasUser = await this.userRepository.findOneBy({
      username: userDto.username,
      delFlag: 0,
    });
    if (hasUser) throw '该用户名已存在';

    return this.userRepository.manager.transaction(async (entityManager) => {
      const { manageTeacher, ...user } = userDto;
      const { id } = await entityManager.save(User, user);
      await this.updateTeacherStudent(entityManager, id, manageTeacher, user);
    });
  }

  async update(id: string, userDto: UserDto) {
    return this.userRepository.manager.transaction(async (entityManager) => {
      const { manageTeacher, ...user } = userDto;
      await this.userRepository.update(id, user);
      await this.updateTeacherStudent(entityManager, id, manageTeacher, user);
    });
  }

  async updatePassword(updatePasswordDto: UpdatePasswordDto) {
    if (updatePasswordDto.password !== updatePasswordDto.confirmPassword)
      throw '两次新密码不一致';

    const user = await this.userRepository.findOne({
      where: { id: updatePasswordDto.updater },
      select: ['username', 'password'],
    });

    if (updatePasswordDto.oldPassword !== user.password) throw '旧密码输入错误';

    return this.userRepository.update(updatePasswordDto.updater, {
      password: updatePasswordDto.password,
      updater: updatePasswordDto.updater,
    });
  }

  async resetPassword(id: string, updater: string) {
    return this.userRepository.update(id, { password: '123456', updater });
  }

  async updateTeacherStudent(
    entityManager: EntityManager,
    student: string,
    manageTeacher: [],
    user,
  ) {
    if (user.roleId !== 3) return;

    await entityManager.delete(TeacherStudent, { student });

    if (!manageTeacher?.length) return;
    const ts = manageTeacher.map((teacher) => ({
      teacher,
      student,
      creator: user.creator || user.updater,
      updater: user.updater,
    }));
    await entityManager.insert(TeacherStudent, ts);
  }

  async removes(ids: string[]) {
    return this.userRepository.update(ids, { delFlag: 1 });
  }

  async findAll(pageInfo: PageInfoEntity, query) {
    console.log(query);

    const [list, total] = await this.userRepository
      .createQueryBuilder('user')
      .leftJoinAndMapOne(
        'user.photoResource',
        Resource,
        'resource',
        'resource.del_flag=0 and user.photo=resource.id',
      )
      .leftJoinAndMapMany(
        'user.manageTeacher',
        TeacherStudent,
        'ts',
        'user.id=ts.student',
      )
      .select([
        'user.id',
        'user.username',
        'user.name',
        'user.photo',
        'user.orgId',
        'user.orgIds',
        'user.roleId',
        'user.sex',
        'user.birthday',
        'user.idcard',
        'user.identity',
        'user.phone',
        'user.email',
        'user.createTime',
        'resource.id',
        'resource.diskname',
        'ts.id',
        'ts.teacher',
      ])
      .where(
        [
          'user.del_flag=0',
          'user.del_flag=0',
          query.likeName && `user.name like '%${query.likeName}%'`,
          query.org && `user.org_id='${query.org}'`,
          query.role && `user.role_id='${query.role}'`,
        ]
          .filter(Boolean)
          .join(' and '),
      )
      .orderBy('user.createTime', 'DESC')
      .skip(pageInfo.start)
      .take(pageInfo.size)
      .getManyAndCount();

    return { list, total };
  }

  findAllTeacher() {
    return this.userRepository
      .createQueryBuilder('user')
      .innerJoin(
        Role,
        'role',
        [
          'user.del_flag = 0',
          'role.del_flag = 0',
          'role.base = 2',
          'user.role_id = role.id',
        ].join(' and '),
      )
      .select(['user.id', 'user.name'])
      .getMany();
  }

  findSomeUserByRole(role: number) {
    return this.userRepository
      .createQueryBuilder('user')
      .innerJoin(
        Role,
        'role',
        [
          'user.del_flag = 0',
          'role.del_flag = 0',
          'role.base = ' + role,
          'user.role_id = role.id',
        ].join(' and '),
      )
      .select(['user.id', 'user.name'])
      .getMany();
  }

  findStudentByOrgId(orgId: number) {
    return this.userRepository
      .createQueryBuilder('user')
      .innerJoin(
        Role,
        'role',
        [
          'user.del_flag = 0',
          'role.del_flag = 0',
          'role.base = 3',
          'user.role_id = role.id',
        ].join(' and '),
      )
      .select(['user.id', 'user.name'])
      .where('user.org_id=:orgId', { orgId })
      .getMany();
  }

  findStudentByTeacher(teacherId: string) {
    return this.userRepository
      .createQueryBuilder('user')
      .innerJoin(TeacherStudent, 'ts', 'ts.student=user.id')
      .select(['user.id', 'user.name'])
      .where('ts.teacher=:teacherId', { teacherId })
      .getMany();
  }

  async batchCreate(userList: [any], token) {
    if (Array.isArray(userList)) {
      const errList = [];
      const sucList = [];
      const allTeacher = [];
      for (const item of userList) {
        try {
          console.log(item.manageTeacher);
          item.creator = token.userId;
          item.updater = token.userId;
          await this.userRepository.save(item);
          item.manageTeacher &&
            allTeacher.push(
              ...item.manageTeacher.map((tac) => ({
                teacher: tac,
                student: item.id,
                creator: token.userId,
                updater: token.userId,
              })),
            );
          sucList.push(item);
        } catch (error) {
          console.log(error);
          item.errMsg = '用户名重复';
          errList.push(item);
        }
      }
      await this.dataSource.getRepository(TeacherStudent).save(allTeacher);
      return {
        errList,
        sucList,
      };
    }
  }
}
