/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package cn.ysk.cashier.service.impl.shopimpl;

import cn.ysk.cashier.dto.shop.TbShopPermissionDto;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.exception.EntityExistException;
import cn.ysk.cashier.pojo.shop.TbPlussShopStaff;
import cn.ysk.cashier.service.TbShopStaffPermissionService;
import cn.ysk.cashier.system.domain.Dept;
import cn.ysk.cashier.system.domain.Job;
import cn.ysk.cashier.system.domain.Role;
import cn.ysk.cashier.system.domain.User;
import cn.ysk.cashier.system.repository.UserRepository;
import cn.ysk.cashier.system.service.UserService;
import cn.ysk.cashier.system.service.dto.RoleSmallDto;
import cn.ysk.cashier.system.service.dto.UserDto;
import cn.ysk.cashier.utils.*;
import lombok.RequiredArgsConstructor;
import cn.ysk.cashier.repository.shop.TbPlussShopStaffRepository;
import cn.ysk.cashier.service.shop.TbPlussShopStaffService;
import cn.ysk.cashier.dto.shop.TbPlussShopStaffDto;
import cn.ysk.cashier.dto.shop.TbPlussShopStaffQueryCriteria;
import cn.ysk.cashier.mapper.shop.TbPlussShopStaffMapper;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.io.IOException;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author lyf
* @date 2024-03-01
**/
@Service
@RequiredArgsConstructor
public class TbPlussShopStaffServiceImpl implements TbPlussShopStaffService {

    private final TbPlussShopStaffRepository tbPlussShopStaffRepository;
    private final TbPlussShopStaffMapper tbPlussShopStaffMapper;

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final UserService userService;

    private final TbShopStaffPermissionService shopStaffPermissionService;

    // 正则表达式：(\u4e00-\u9fa5) 表示匹配一个中文字符，.* 表示匹配零个或多个任意字符
    private final Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]");

    @Override
    public Map<String,Object> queryAll(TbPlussShopStaffQueryCriteria criteria, Pageable pageable){
        Page<TbPlussShopStaff> page = tbPlussShopStaffRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(tbPlussShopStaffMapper::toDto));
    }

    @Override
    public List<TbPlussShopStaffDto> queryAll(TbPlussShopStaffQueryCriteria criteria){
        return tbPlussShopStaffMapper.toDto(tbPlussShopStaffRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public TbPlussShopStaffDto findById(Integer id) {
        TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffRepository.findById(id).orElseGet(TbPlussShopStaff::new);
        ValidationUtil.isNull(tbPlussShopStaff.getId(),"TbPlussShopStaff","id",id);
        TbPlussShopStaffDto dto = tbPlussShopStaffMapper.toDto(tbPlussShopStaff);
        UserDto userDto = userService.findByName(tbPlussShopStaff.getShopId()+"@"+tbPlussShopStaff.getAccount());
//        dto.setUser(userDto);
        if(!CollectionUtils.isEmpty(userDto.getRoles())){
            dto.setRoleId(userDto.getRoles().stream().findFirst().get().getId());
        }
        dto.setPhone(userDto.getPhone());
        dto.setPassword("");//不返回密码

        List<TbShopPermissionDto> permissionList = shopStaffPermissionService.getStaffPermissionList(userDto.getId().intValue());
        dto.setPermissions(permissionList);
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TbPlussShopStaffDto create(TbPlussShopStaff resources) {
        if (!PhoneUtil.validator(resources.getPhone())){
            throw new BadRequestException("手机号格式有误");
        }
        if (userRepository.findByUsername(resources.getShopId()+"@"+resources.getAccount()) != null) {
            throw new BadRequestException("员工账号已存在");
        }

        if (pattern.matcher(resources.getCode()).find()) {
            throw new BadRequestException("员工编号不能包含中文");
        }

        if (resources.getRoleId()==null) {
            throw new BadRequestException("请选择角色");
        }

        if (resources.getMaxDiscountAmount().compareTo(new BigDecimal(100000000L)) > 0) {
            throw new BadRequestException("最大优惠金额过大");
        }
        resources.setCreatedAt(Instant.now().toEpochMilli());

        //添加收银系统后台账号
        User user = new User();
        if (StringUtils.isBlank(resources.getPassword())) {
            resources.setPassword(MD5Utils.md5("123456"));
            user.setPassword(passwordEncoder.encode("123456"));
        }else {
            user.setPassword(passwordEncoder.encode(resources.getPassword()));
            resources.setPassword(MD5Utils.md5(resources.getPassword()));
        }
        user.setUsername(resources.getShopId() + "@" +resources.getAccount());
        user.setNickName(resources.getName());
        user.setPhone(resources.getPhone());
        user.setEnabled(true);

        Dept dept = new Dept();
        dept.setId(18L);
        user.setDept(dept);

        Set<Role> roles = new HashSet<>();
        Role role = new Role();
        role.setId(resources.getRoleId());
        roles.add(role);
        user.setRoles(roles);

        Set<Job> jobs = new HashSet<>();
        Job job = new Job();
        job.setId(10L);
        jobs.add(job);
        user.setJobs(jobs);
        userRepository.save(user);

        TbPlussShopStaffDto dto = tbPlussShopStaffMapper.toDto(tbPlussShopStaffRepository.save(resources));

        shopStaffPermissionService.updateStaffPermission(user.getId().intValue(),
                Integer.valueOf(resources.getShopId()), resources.getId(), resources.getPermissions());
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(TbPlussShopStaff resources) {
        if (StringUtils.isBlank(resources.getPassword())) {
            resources.setPassword(null);
        }

        if (pattern.matcher(resources.getCode()).find()) {
            throw new BadRequestException("员工编号不能包含中文");
        }
        TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffRepository.findById(resources.getId()).orElseGet(TbPlussShopStaff::new);
        User sysUser = userRepository.findByUsername(resources.getShopId()+"@"+tbPlussShopStaff.getAccount());
        if(!tbPlussShopStaff.getAccount().equals(resources.getAccount())){
            if (userRepository.findByUsername(resources.getShopId()+"@"+resources.getAccount()) != null) {
                throw new BadRequestException("员工账号不可重复");
            }
        }
        resources.setUpdatedAt(System.currentTimeMillis());
        ValidationUtil.isNull( tbPlussShopStaff.getId(),"TbPlussShopStaff","id",resources.getId());
        tbPlussShopStaff.copy(resources);
        if (StringUtils.isNotBlank(resources.getPassword())) {
            tbPlussShopStaff.setPassword(MD5Utils.md5(resources.getPassword()));
        }
        tbPlussShopStaffRepository.save(tbPlussShopStaff);
        //修改 sysUser账号
        Set<Role> roles = new HashSet<>();
        Role role = new Role();
        role.setId(resources.getRoleId());
        roles.add(role);
        sysUser.setUsername(resources.getShopId()+"@"+resources.getAccount());
        sysUser.setRoles(roles);
        sysUser.setNickName(resources.getName());
        if (StringUtils.isNotBlank(resources.getPassword())) {
            sysUser.setPassword(passwordEncoder.encode(resources.getPassword()));
        }
        sysUser.setPhone(resources.getPhone());
        userRepository.save(sysUser);

        shopStaffPermissionService.updateStaffPermission(sysUser.getId().intValue(),
                Integer.valueOf(resources.getShopId()), resources.getId(), resources.getPermissions());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(TbPlussShopStaff resources) {
        TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffRepository.findById(resources.getId()).orElseGet(TbPlussShopStaff::new);
        tbPlussShopStaff.setUpdatedAt(Instant.now().toEpochMilli());
        tbPlussShopStaff.setStatus(resources.getStatus());
        tbPlussShopStaffRepository.save(tbPlussShopStaff);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        Set<Long> sysUserIds=new HashSet<>();
        for (Integer id : ids) {
            TbPlussShopStaff tbPlussShopStaff = tbPlussShopStaffRepository.findById(id).get();
            User sysUser = userRepository.findByUsername(tbPlussShopStaff.getShopId()+"@"+tbPlussShopStaff.getAccount());
            tbPlussShopStaffRepository.deleteById(id);
            sysUserIds.add(sysUser.getId());
        }
        userService.delete(sysUserIds);
    }

    @Override
    public void download(List<TbPlussShopStaffDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TbPlussShopStaffDto tbPlussShopStaff : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("员工编号", tbPlussShopStaff.getCode());
            map.put("员工名称", tbPlussShopStaff.getName());
            map.put("登录账号", tbPlussShopStaff.getAccount());
            map.put("密码", tbPlussShopStaff.getPassword());
            map.put("最大优惠金额", tbPlussShopStaff.getMaxDiscountAmount());
            map.put("1启用0不启用", tbPlussShopStaff.getStatus());
            map.put("登录端", tbPlussShopStaff.getEmployee());
            map.put("shopId", tbPlussShopStaff.getShopId());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
