package cn.iocoder.yudao.module.employee.controller.admin.info;


import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoPageReqVO;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoRespVO;
import cn.iocoder.yudao.module.employee.controller.admin.info.vo.EmployeeInfoSaveReqVO;
import cn.iocoder.yudao.module.employee.convert.info.EmployeeConvert;
import cn.iocoder.yudao.module.employee.dal.dataobject.info.EmployeeInfoDO;
import cn.iocoder.yudao.module.employee.service.info.EmployeeInfoService;
import cn.iocoder.yudao.module.relations.api.contract.RelationsContractApi;
import cn.iocoder.yudao.module.relations.api.contract.dto.RelationsContractDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;

@Tag(name = "管理后台 - 员工信息")
@RestController
@RequestMapping("/personnel/employee")
@Validated
public class EmployeeInfoController {

    @Resource
    private EmployeeInfoService infoService;
    @Resource
    private DeptService deptService;

    @Resource
    private PostService postService;

    @Resource
    private RelationsContractApi relationsContractApi;

    @PostMapping("/create")
    @Operation(summary = "创建员工信息")
    @PreAuthorize("@ss.hasPermission('employee:info:create')")
    public CommonResult<Long> createInfo(@Valid @RequestBody EmployeeInfoSaveReqVO createReqVO) {
        return success(infoService.createInfo(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新员工信息")
    @PreAuthorize("@ss.hasPermission('employee:info:update')")
    public CommonResult<Boolean> updateInfo(@Valid @RequestBody EmployeeInfoSaveReqVO updateReqVO) {
        infoService.updateInfo(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除员工信息")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('employee:info:delete')")
    public CommonResult<Boolean> deleteInfo(@RequestParam("id") Long id) {
        infoService.deleteInfo(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得员工信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('employee:info:query')")
    public CommonResult<EmployeeInfoRespVO> getInfo(@RequestParam("id") Long id) {

        EmployeeInfoDO info = infoService.getInfo(id);
        EmployeeInfoRespVO employeeInfoRespVO = BeanUtils.toBean(info, EmployeeInfoRespVO.class);

        // 如果部门ID不为空，则尝试获取部门详细信息
        Long deptId = employeeInfoRespVO.getDeptId();
        if (deptId != null) {
            DeptDO dept = deptService.getDept(deptId);
            // 如果成功获取到部门信息，则设置部门名称到员工信息中
            if (dept != null) {
                employeeInfoRespVO.setDeptName(dept.getName());
            }
        }

        // 如果职位ID不为空，则尝试获取职位详细信息
        Long postId = employeeInfoRespVO.getPostId();
        if (postId != null) {
            PostDO post = postService.getPost(postId);
            // 如果成功获取到职位信息，则设置职位名称到员工信息中
            if (post != null) {
                employeeInfoRespVO.setPosition(post.getName());
            }
        }

        // 根据员工ID查询员工当前的合同信息
        RelationsContractDTO lastContract = relationsContractApi.getLastContract(employeeInfoRespVO.getId());
        // 如果员工的合同信息存在，则更新员工信息中的合同起始和结束日期
        if (lastContract != null) {
            employeeInfoRespVO.setContractStartDate(lastContract.getContractStartDate());
            employeeInfoRespVO.setContractEndDate(lastContract.getContractEndDate());
        }

        return success(employeeInfoRespVO);
    }

    @GetMapping("/getLoginEmployee")
    @Operation(summary = "获得当前登录的员工信息")
    // @PreAuthorize("@ss.hasPermission('employee:info:query')")
    public CommonResult<EmployeeInfoRespVO> getLoginEmployee() {
        // 获取当前登录员工的信息
        EmployeeInfoDO info = infoService.getLoginEmployee();

        // 如果部门ID不为空，则尝试获取部门详细信息
        Long deptId = info.getDeptId();
        if (deptId != null) {
            DeptDO dept = deptService.getDept(deptId);
            // 如果成功获取到部门信息，则设置部门名称到员工信息中
            if (dept != null) {
                info.setDeptName(dept.getName());
            }
        }

        // 如果职位ID不为空，则尝试获取职位详细信息
        Long postId = info.getPostId();
        if (postId != null) {
            PostDO post = postService.getPost(postId);
            // 如果成功获取到职位信息，则设置职位名称到员工信息中
            if (post != null) {
                info.setPosition(post.getName());
            }
        }

        // 将员工信息对象转换为响应视图对象，并返回成功响应
        return success(BeanUtils.toBean(info, EmployeeInfoRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得员工信息分页")
    @PreAuthorize("@ss.hasPermission('employee:info:query')")
    public CommonResult<PageResult<EmployeeInfoRespVO>> getInfoPage(@Valid EmployeeInfoPageReqVO pageReqVO) {
        PageResult<EmployeeInfoDO> pageResult = infoService.getInfoPage(pageReqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(new PageResult<>(pageResult.getTotal()));
        }
        // 拼接数据
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(pageResult.getList(), EmployeeInfoDO::getDeptId));
        // 避免空指针报错
        Map<Long, PostDO> postMap = new HashMap<>();
        return success(new PageResult<>(EmployeeConvert.INSTANCE.convertList(pageResult.getList(), deptMap, postMap),
                pageResult.getTotal()));
    }


    @GetMapping("/listForSelectEmployee")
    @Operation(summary = "获得可选择的员工信息列表，用于选择业务人或审批人等")
    @Parameter(name = "auth", description = "是否有权限，0无 1有", required = true)
    @Parameter(name = "name", description = "员工姓名", required = false)
    @Parameter(name = "deptId", description = "部门ID", required = false)
    @Parameter(name = "phone", description = "员工手机号", required = false)
    // @PreAuthorize("@ss.hasPermission('employee:info:listForSelectEmployee')")
    public CommonResult<List<EmployeeInfoRespVO>> getInfoListForSelectEmployee(@RequestParam(value = "auth", required = false) String auth,
                                                                               @RequestParam(value = "name", required = false) String name,
                                                                               @RequestParam(value = "deptId", required = false) Long deptId,
                                                                               @RequestParam(value = "phone", required = false) String phone) {
        // 查询员工信息列表
        List<EmployeeInfoDO> listResult = infoService.getInfoListForSelectEmployee(auth, name, deptId, phone);
        // 如果查询结果为空，则返回一个空列表
        if (CollUtil.isEmpty(listResult)) {
            return success(new ArrayList<>());
        }
        // 将查询结果中的部门ID映射为部门信息
        Map<Long, DeptDO> deptMap = deptService.getDeptMap(
                convertList(listResult, EmployeeInfoDO::getDeptId));

        // 获取所有员工的岗位ID列表
        List<Long> postIdList = listResult.stream().map(EmployeeInfoDO::getPostId).collect(Collectors.toList());
        // 根据岗位ID列表查询岗位信息
        List<PostDO> postList = postService.getPostList(postIdList);
        // 将岗位ID与岗位信息映射
        Map<Long, PostDO> postMap = CollectionUtils.convertMap(postList, PostDO::getId);

        // 将员工信息、部门信息和岗位信息合并转换为前端所需的格式，并返回
        return success(EmployeeConvert.INSTANCE.convertList(listResult, deptMap, postMap));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出员工信息 Excel")
    @PreAuthorize("@ss.hasPermission('employee:info:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportInfoExcel(@Valid EmployeeInfoPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<EmployeeInfoDO> list = infoService.getInfoPage(pageReqVO).getList();
        List<EmployeeInfoRespVO> respVOList = BeanUtils.toBean(list, EmployeeInfoRespVO.class);
        if (respVOList != null && respVOList.size() > 0) {
            respVOList.forEach(respVO -> {
                // 如果部门ID不为空，则尝试获取部门详细信息
                Long deptId = respVO.getDeptId();
                if (deptId != null) {
                    DeptDO dept = deptService.getDept(deptId);
                    // 如果成功获取到部门信息，则设置部门名称到员工信息中
                    if (dept != null) {
                        respVO.setDeptName(dept.getName());
                    }
                }
                // 如果职位ID不为空，则尝试获取职位详细信息
                Long postId = respVO.getPostId();
                if (postId != null) {
                    PostDO post = postService.getPost(postId);
                    // 如果成功获取到职位信息，则设置职位名称到员工信息中
                    if (post != null) {
                        respVO.setPosition(post.getName());
                    }
                }
            });
        }
        // 导出 Excel
        ExcelUtils.write(response, "员工信息.xls", "数据", EmployeeInfoRespVO.class,
                respVOList);
    }

}