package com.izouma.jiashanxia.service;

import cn.hutool.core.util.ObjectUtil;
import com.izouma.jiashanxia.domain.Company;
import com.izouma.jiashanxia.domain.User;
import com.izouma.jiashanxia.dto.CompanyDTO;
import com.izouma.jiashanxia.dto.PageQuery;
import com.izouma.jiashanxia.enums.AuthorityName;
import com.izouma.jiashanxia.exception.BusinessException;
import com.izouma.jiashanxia.repo.CompanyRepo;
import com.izouma.jiashanxia.repo.UserPackageRepo;
import com.izouma.jiashanxia.repo.UserRepo;
import com.izouma.jiashanxia.security.Authority;
import com.izouma.jiashanxia.utils.JpaUtils;
import com.izouma.jiashanxia.utils.ObjUtils;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class CompanyService {

    private CompanyRepo     companyRepo;
    private UserRepo        userRepo;
    private UserPackageRepo userPackageRepo;

    public Page<CompanyDTO> all(PageQuery pageQuery, User user) {
        pageQuery.setSort("createdAt,desc");
        Set<Authority> authorities = user.getAuthorities();
        if (!authorities.contains(Authority.get(AuthorityName.ROLE_ADMIN)) && authorities.contains(Authority.get(AuthorityName.ROLE_CREATOR))) {
            Map<String, Object> query = pageQuery.getQuery();
            query.put("userId", user.getId());
            return companyRepo.findAll(JpaUtils.toSpecification(pageQuery, Company.class), JpaUtils.toPageRequest(pageQuery))
                    .map(company -> {
                        CompanyDTO dto = new CompanyDTO(company);
                        dto.setNickname(user.getNickname());
                        return dto;
                    });
        }
        Map<Long, User> userMap = userRepo.findAllByTeamFounderTrueAndDelFalse()
                .stream()
                .collect(Collectors.toMap(User::getId, user1 -> user1));
        return companyRepo.findAll(JpaUtils.toSpecification(pageQuery, Company.class), JpaUtils.toPageRequest(pageQuery))
                .map(company -> {
                    User user1 = userMap.get(company.getUserId());
                    CompanyDTO dto = new CompanyDTO(company);
                    if (ObjectUtil.isNotEmpty(user1)) {
                        dto.setNickname(user1.getNickname());
                    }
                    return dto;
                });
    }

    /*
    添加员工
    */
    public void addUser(Long userId, Long companyId) {
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
        user.setCompanyId(companyId);
        userRepo.save(user);
    }

    /*
    删除员工
     */
    public void removeUser(Long userId, Long companyId) {
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
        if (companyId.equals(user.getCompanyId())) {
            user.setCompanyId(null);
            userRepo.save(user);
        }
    }

    /*
    员工列表
     */
    public List<User> employee(Long userId) {
        Company company = companyRepo.findByUserId(userId);
        if (ObjectUtil.isEmpty(company)) {
            return null;
        }
        return userRepo.findAllByCompanyIdAndDelFalse(company.getId());
    }

    /*
    新建企业
     */
    public Company save(Company record) {
        // 团队权限
        Authority creator = Authority.get(AuthorityName.ROLE_CREATOR);
        // 修改
        if (record.getId() != null) {
            Company orig = companyRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
            // 现在的员工列表
            List<Long> employee = record.getEmployee();
            // 原来的员工列表
            List<User> users = userRepo.findAllByCompanyIdAndDelFalse(record.getId());
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));
            Set<Long> oldEmployee = new HashSet<>(userMap.keySet());
            // 如果旧员工被移除
            oldEmployee.removeAll(employee);
            if (ObjectUtil.isNotEmpty(oldEmployee)) {
                oldEmployee.forEach(yee -> {
                    User user = userMap.get(yee);
                    user.setCompanyId(null);
                    userRepo.save(user);
                });
            }
            // 新员工加入团队
            employee.removeAll(userMap.keySet());
            if (ObjectUtil.isNotEmpty(employee)) {
                userRepo.updateCompanyId(record.getId(), employee);
            }
            // 更换团队管理人
            if (!record.getUserId().equals(orig.getUserId())) {
                userRepo.findById(orig.getUserId()).ifPresent(user1 -> {
                    user1.setTeamFounder(false);
                    Set<Authority> authorities1 = user1.getAuthorities();
                    authorities1.remove(creator);
                    userRepo.save(user1);
                });
                // 新团队管理人增加权限
                this.teamFounder(record.getUserId(), creator, record.getId());
                // 套餐转到新管理员上
                userPackageRepo.updateUserId(orig.getUserId(), record.getUserId());
            }
            ObjUtils.merge(orig, record);
            return companyRepo.save(orig);
        }

        // 增加
        record.setAmount(BigDecimal.ZERO);
        Company save = companyRepo.save(record);
        // 管理员加权限
        this.teamFounder(save.getUserId(), creator, save.getId());
        // 员工加入企业
        userRepo.updateCompanyId(save.getId(), record.getEmployee());
        return save;
    }

    /*
    修改团队权限
     */
    public void teamFounder(Long userId, Authority creator, Long companyId) {
        // 新团队管理人增加权限
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
        Set<Authority> authorities = user.getAuthorities();
        if (!authorities.contains(creator) || !user.getTeamFounder()) {
            authorities.add(creator);
            user.setTeamFounder(true);
            user.setCompanyId(companyId);
            userRepo.save(user);
        }
    }

    /*
    删除企业
     */
    public void del(Long id) {
        companyRepo.findById(id).ifPresent(company -> {
            userRepo.findById(company.getUserId()).ifPresent(user -> {
                user.setCompanyId(null);
                user.setTeamFounder(null);
                Set<Authority> authorities = user.getAuthorities();
                authorities.remove(Authority.get(AuthorityName.ROLE_CREATOR));
                userRepo.save(user);
            });
            userRepo.deleteCompanyId(id);
        });
        companyRepo.softDelete(id);
    }

}
