package com.ltgk.port.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ltgk.common.annotation.DataScope;
import com.ltgk.common.annotation.Log;
import com.ltgk.common.annotation.RepeatSubmit;
import com.ltgk.common.constant.Constants;
import com.ltgk.common.core.controller.BaseController;
import com.ltgk.common.core.domain.AjaxResult;
import com.ltgk.common.core.domain.BaseEntity;
import com.ltgk.common.core.domain.entity.SysDept;
import com.ltgk.common.core.page.TableDataInfo;
import com.ltgk.common.enums.BusinessType;
import com.ltgk.common.utils.SecurityUtils;
import com.ltgk.common.utils.StringUtils;
import com.ltgk.common.utils.bean.BeanUtils;
import com.ltgk.common.utils.poi.ExcelUtil;
import com.ltgk.common.validation.groups.Add;
import com.ltgk.common.validation.groups.Detail;
import com.ltgk.common.validation.groups.Update;
import com.ltgk.port.domain.dto.DsPortDTO;
import com.ltgk.port.domain.dto.GetOutEnterPortListReq;
import com.ltgk.port.domain.entity.DsPort;
import com.ltgk.port.domain.vo.DsPortVO;
import com.ltgk.port.service.IDsPortService;
import com.ltgk.system.service.ISysDeptService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 渔港信息 前端控制器
 *
 * @author Qi ChengBin
 * @date 2024-12-09
 */
@Api(tags = "港口信息")
@RestController
@RequestMapping("/fishingPort/dsPort")
public class DsPortController extends BaseController {

    @Resource
    private IDsPortService dsPortService;
    @Resource
    private ISysDeptService deptService;

    /**
     * 分页查询港口信息列表
     *
     * @param dsPortDTO:
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @PostMapping("/page")
    @ApiOperation(value = "分页查询港口信息列表")
    public TableDataInfo page(@RequestBody DsPortDTO dsPortDTO) {
        LambdaQueryWrapper<DsPort> wrapper = getDsPortLambdaQueryWrapper(dsPortDTO);
        startPage(dsPortDTO.getPageNum(), dsPortDTO.getPageSize());
        wrapper.in(CollectionUtils.isNotEmpty(dsPortDTO.getPortIdList()), DsPort::getId, dsPortDTO.getPortIdList());
        List<DsPort> dsPortList = dsPortService.list(wrapper);
        return getDataTable(dsPortList);
    }

    /**
     * 导出渔港基础信息数据
     *
     * @param dsPortDTO:
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @Log(title = "港口信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ApiOperation(value = "导出渔港基础信息数据")
    public void export(HttpServletResponse response, DsPortDTO dsPortDTO) {
        LambdaQueryWrapper<DsPort> wrapper = getDsPortLambdaQueryWrapper(dsPortDTO);
        List<DsPort> dsPortList = dsPortService.list(wrapper);

        List<DsPortVO> dsPortVOList = dsPortList.stream()
                .map(item -> {
                    DsPortVO dsPortVO = new DsPortVO();
                    BeanUtils.copyProperties(item, dsPortVO);
                    return dsPortVO;
                })
                .collect(Collectors.toList());

        ExcelUtil<DsPortVO> util = new ExcelUtil<>(DsPortVO.class);
        util.exportExcel(response, dsPortVOList, "渔港基础信息数据");
    }

    /**
     * 获取港口信息详细信息
     *
     * @param dsPortDTO: 请求参数实体，获取ID
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @PostMapping(value = "/detail")
    @ApiOperation(value = "获取港口信息详细数据")
    public AjaxResult detail(@Validated(Detail.class) @RequestBody DsPortDTO dsPortDTO) {
        return success(dsPortService.getById(dsPortDTO.getId()));
    }

    /**
     * 新增港口信息信息
     *
     * @param dsPort: 渔港实体对象
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @RepeatSubmit(message = "请勿重复提交")
    @Log(title = "新增港口信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ApiOperation(value = "新增港口信息数据")
    public AjaxResult add(@Validated(Add.class) @RequestBody DsPort dsPort) {
        String userName = SecurityUtils.getLoginUser().getUser().getNickName();
        dsPort.setDelFlag(Constants.FLAG_FALSE)
                .setCreateBy(userName)
                .setCreateAt(new Date())
                .setUpdateBy(userName)
                .setUpdateAt(new Date());
        return toAjax(dsPortService.save(dsPort));
    }

    /**
     * 修改港口信息信息
     *
     * @param dsPort: 渔港实体对象
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @Log(title = "修改港口信息", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ApiOperation(value = "修改港口信息数据")
    public AjaxResult edit(@Validated(Update.class) @RequestBody DsPort dsPort) {
        String userName = SecurityUtils.getLoginUser().getUser().getNickName();
        dsPort.setUpdateBy(userName)
                .setUpdateAt(new Date());
        return toAjax(dsPortService.updateById(dsPort));
    }

    /**
     * 删除港口信息信息
     *
     * @param dsPortDTO: 请求参数实体，获取ID
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-09
     */
    @Log(title = "删除港口信息", businessType = BusinessType.DELETE)
    @PostMapping("/delete")
    @ApiOperation(value = "批量删除港口信息数据")
    public AjaxResult delete(@Validated(Detail.class) @RequestBody DsPortDTO dsPortDTO) {
        return toAjax(dsPortService.removeById(dsPortDTO.getId()));
    }

    /**
     * 渔港信息导入模板
     *
     * @param response:
     * @author Qi ChengBin
     * @date 2024/12/11 17:20
     */
    @Log(title = "渔港信息导入模板导出", businessType = BusinessType.EXPORT)
    @ApiOperation("渔港信息导入模板导出")
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response) {
        ExcelUtil<DsPortVO> util = new ExcelUtil<>(DsPortVO.class);
        util.importTemplateExcel(response, "渔港信息导入模板");
    }

    @RepeatSubmit(message = "请勿重复提交")
    @Log(title = "渔港信息导入", businessType = BusinessType.IMPORT)
    @ApiOperation("渔港信息导入")
    @PostMapping("/importData")
    public AjaxResult importData(@RequestBody MultipartFile file) throws Exception {
        String userName = SecurityUtils.getLoginUser().getUser().getNickName();
        // 校验是否为 Excel 格式
        ExcelUtil.checkExcelFile(file);
        ExcelUtil<DsPortVO> util = new ExcelUtil<>(DsPortVO.class);
        List<DsPortVO> dsPortVOList = util.importExcel(file.getInputStream());
        if (CollectionUtils.isEmpty(dsPortVOList) || dsPortVOList.stream().allMatch(Objects::isNull)) {
            return AjaxResult.error("导入数据为空或模板格式有误！");
        }

        // 根据Excel 中的数据查询部门的相关数据  TODO：之前港口信息中存储的单位ID 和 单位名称，此处先用部门信息，后期确定
        List<String> deptNameList = dsPortVOList.stream()
                .map(dsPortVO -> dsPortVO.getDeptName().replace(" ", ""))
                .collect(Collectors.toList());
        List<SysDept> sysDeptList = deptService.findDeptByDeptNameList(deptNameList);
        Map<String, String> sysDeptMap = sysDeptList.stream()
                .collect(Collectors.toMap(SysDept::getDeptName, dept -> String.valueOf(dept.getDeptId())));

        // 查询导入数据是否存在
        List<String> portNameList = dsPortVOList.stream()
                .map(dsPortVO -> dsPortVO.getPortName().replace(" ", ""))
                .collect(Collectors.toList());
        LambdaQueryWrapper<DsPort> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DsPort::getDelFlag, Constants.FLAG_FALSE)
                .in(DsPort::getPortName, portNameList);
        List<DsPort> dsPortList = dsPortService.list(wrapper);
        Map<String, DsPort> dsPortMap = dsPortList.stream()
                .collect(Collectors.toMap(DsPort::getPortName, dsPort -> dsPort));

        // 处理数据
        List<DsPort> dsPortAddList = new ArrayList<>();
        List<DsPort> dsPortUpdateList = new ArrayList<>();

        dsPortVOList.forEach(dsPortVO -> {
            DsPort dsPort = new DsPort();
            BeanUtils.copyProperties(dsPortVO, dsPort);
            // 组装数据
            dsPort.setDeptId(StringUtils.isNotBlank(dsPortVO.getDeptName()) ? sysDeptMap.get(dsPortVO.getDeptName()) : null);
            dsPort.setDelFlag(Constants.FLAG_FALSE);
            dsPort.setCreateBy(userName);
            dsPort.setUpdateBy(userName);
            dsPort.setCreateAt(new Date());
            dsPort.setUpdateAt(new Date());
            // 存在 则是修改
            if (dsPortMap.containsKey(dsPortVO.getPortName())) {
                dsPort.setId(dsPortMap.get(dsPortVO.getPortName()).getId());
                dsPortUpdateList.add(dsPort);
            } else {
                dsPortAddList.add(dsPort);
            }
        });

        //处理数据
        boolean update = true;
        boolean add = true;
        if (CollectionUtils.isNotEmpty(dsPortAddList)) {
            // 新增
            add = dsPortService.saveBatch(dsPortAddList);
        }
        if (CollectionUtils.isNotEmpty(dsPortUpdateList)) {
            // 修改
            update = dsPortService.updateBatchById(dsPortUpdateList);
        }
        return toAjax(update && add);
    }

    /**
     * 根据渔港数据传输对象转换成对应的查询 wrapper
     *
     * @param dsPortDTO: 渔港数据传输对象
     * @return com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ltgk.port.domain.entity.DsPort>
     * @author Qi ChengBin
     * @date 2024/12/25 16:54
     */
    private static LambdaQueryWrapper<DsPort> getDsPortLambdaQueryWrapper(DsPortDTO dsPortDTO) {
        DsPort dsPort = getDsPort(dsPortDTO);
        LambdaQueryWrapper<DsPort> wrapper = new LambdaQueryWrapper<>(dsPort);
        wrapper.orderByDesc(DsPort::getUpdateAt);
        return wrapper;
    }

    /**
     * 根据渔港数据传输对象转换成渔港实体对象
     *
     * @param dsPortDTO: 渔港数据传输对象
     * @return com.ltgk.port.domain.entity.DsPort
     * @author Qi ChengBin
     * @date 2024/12/25 16:56
     */
    private static DsPort getDsPort(DsPortDTO dsPortDTO) {
        dsPortDTO.queryCheck();
        DsPort dsPort = new DsPort();
        BeanUtils.copyProperties(dsPortDTO, dsPort);
        return dsPort;
    }

    /**
     * 业务板块 首页 渔港统计查询
     * -- 根据权限进行查询
     * -- 后台接口权限：后台暂无权限设置
     *
     * @param baseEntity:用于接收数据权限组装参数
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/3/21
     */
    @ApiOperation(value = "业务板块 首页 渔港统计查询 -- 根据权限进行查询")
    @PostMapping("/getBusinessIndexPortStatistics")
    @DataScope(deptAlias = "d", permission = "fishingPort:dsPort:getBusinessIndexPortStatistics")
    public AjaxResult getBusinessIndexPortStatistics(BaseEntity baseEntity) {
        return success(dsPortService.getBusinessIndexPortStatistics(baseEntity));
    }

    /**
     * 根据港口id 查询渔港的进港数、离港数、在港数
     * -- 数据均为当天00:00:00到当前时间的数据
     *
     * @param dsPortDTO:
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/3/21
     */
    @ApiOperation(value = "分港口统计查询")
    @PostMapping("/getPortStatisticsByPortId")
    public AjaxResult getPortStatisticsByPortId(@RequestBody DsPortDTO dsPortDTO) {
        return success(dsPortService.getPortStatisticsByPortId(dsPortDTO));
    }

    /**
     * 当日进出港列表
     * -- 00：00：00 到当前时间 的数据列表
     *
     * @param req:
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2025/3/21
     */
    @ApiOperation(value = "当日进出港列表")
    @PostMapping("/findOutEnterPortList")
    public TableDataInfo findOutEnterPortList(@RequestBody GetOutEnterPortListReq req) {
        return getDataTable(dsPortService.findOutEnterPortList(req));
    }
}
