package com.ltgk.boat.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ltgk.boat.domain.dto.*;
import com.ltgk.boat.domain.entity.DsBoatData;
import com.ltgk.boat.domain.entity.DsEnterOutPort;
import com.ltgk.boat.domain.vo.AutomaticIdentificationVO;
import com.ltgk.boat.domain.vo.EnterOutPortStatisticsVO;
import com.ltgk.boat.service.DsBoatDataService;
import com.ltgk.boat.service.IDsEnterOutPortService;
import com.ltgk.common.annotation.Log;
import com.ltgk.common.annotation.RepeatSubmit;
import com.ltgk.common.core.controller.BaseController;
import com.ltgk.common.core.domain.AjaxResult;
import com.ltgk.common.core.page.TableDataInfo;
import com.ltgk.common.enums.BusinessType;
import com.ltgk.common.enums.EnterOutPortType;
import com.ltgk.common.utils.StringUtils;
import com.ltgk.common.utils.bean.BeanUtils;
import com.ltgk.common.utils.poi.ExcelUtil;
import com.ltgk.system.domain.vo.BoatNavigateStatus;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 渔船进出港记录（数据来自船位动态监控） 前端控制器
 *
 * @author Qi ChengBin
 * @date 2024-12-19
 */
@Api(tags = "渔船进出港记录（数据来自船位动态监控）")
@RestController
@RequestMapping("/fishingPort/dsEnterOutPort")
@Validated
public class DsEnterOutPortController extends BaseController {

    @Resource
    private IDsEnterOutPortService dsEnterOutPortService;
    @Resource
    private DsBoatDataService dsBoatDataService;

    /**
     * 分页查询渔船进出港记录（数据来自船位动态监控）列表
     *
     * @param dsEnterOutPortDTO: 渔船进出港记录数据传输对象
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2024-12-19
     */
    @PostMapping("/page")
    @ApiOperation(value = "分页查询渔船进出港记录（数据来自船位动态监控）列表")
    public TableDataInfo page(@RequestBody DsEnterOutPortDTO dsEnterOutPortDTO) {
        DsEnterOutPort dsEnterOutPort = getDsEnterOutPort(dsEnterOutPortDTO);
        // 开始时间、结束时间 对应 进出港时间
        String startTime = dsEnterOutPortDTO.getStartTime();
        String endTime = dsEnterOutPortDTO.getEndTime();

        boolean beNotTimeBlank = StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime);

        LambdaQueryWrapper<DsEnterOutPort> wrapper = new LambdaQueryWrapper<>(dsEnterOutPort);
        wrapper.between(beNotTimeBlank, DsEnterOutPort::getEnterOutTime, startTime, endTime)
                .eq(DsEnterOutPort::getIsLocal, dsEnterOutPortDTO.getIsLocal())
                .isNotNull(Objects.nonNull(dsEnterOutPortDTO.getBeHaveBoatName()) && 1 == dsEnterOutPortDTO.getBeHaveBoatName(), DsEnterOutPort::getBoatName)
                .orderByDesc(DsEnterOutPort::getEnterOutTime);
        startPage(dsEnterOutPortDTO.getPageNum(), dsEnterOutPortDTO.getPageSize());
        List<DsEnterOutPort> dsEnterOutPortList = dsEnterOutPortService.list(wrapper);

        if (CollectionUtils.isNotEmpty(dsEnterOutPortList)) {
            List<String> boatIdList = dsEnterOutPortList.stream().map(DsEnterOutPort::getBoatId).collect(Collectors.toList());
            List<DsBoatData> dsBoatDataList = dsBoatDataService.lambdaQuery()
                    .in(DsBoatData::getBoatId, boatIdList)
                    .list();
            Map<String, DsBoatData> dsBoatDataMap = dsBoatDataList.stream().collect(Collectors.toMap(DsBoatData::getBoatId, data -> data));
            dsEnterOutPortList.forEach(enterOutPort -> {
                if (dsBoatDataMap.containsKey(enterOutPort.getBoatId())) {
                    DsBoatData dsBoatData = dsBoatDataMap.get(enterOutPort.getBoatId());
                    enterOutPort.setHolderName(dsBoatData.getHolderName());
                    enterOutPort.setHolderPhone(dsBoatData.getHolderPhone());
                }
            });
        }

        return getDataTable(dsEnterOutPortList);
    }

    /**
     * 不分页查询渔港进出港记录列表
     *
     * @param dsEnterOutPortDTO: 渔船进出港记录信息数据传输对象
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024/12/20 17:15
     */
    @PostMapping("/list")
    @ApiOperation(value = "不分页查询渔船进出港记录（数据来自船位动态监控）列表")
    public AjaxResult list(@RequestBody DsEnterOutPortDTO dsEnterOutPortDTO) {
        DsEnterOutPort dsEnterOutPort = getDsEnterOutPort(dsEnterOutPortDTO);
        LambdaQueryWrapper<DsEnterOutPort> wrapper = new LambdaQueryWrapper<>(dsEnterOutPort);
        wrapper.orderByDesc(DsEnterOutPort::getEnterOutTime);
        return AjaxResult.success(dsEnterOutPortService.list(wrapper));
    }

    /**
     * 导出渔船进出港记录（数据来自船位动态监控）列表
     *
     * @param dsEnterOutPortDTO:
     * @author Qi ChengBin
     * @date 2024-12-19
     */
    @Log(title = "渔船进出港记录（数据来自船位动态监控）", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ApiOperation(value = "导出渔船进出港记录（数据来自船位动态监控）数据")
    public void export(HttpServletResponse response, DsEnterOutPortDTO dsEnterOutPortDTO) {
        DsEnterOutPort dsEnterOutPort = getDsEnterOutPort(dsEnterOutPortDTO);
        // 开始时间、结束时间 对应 进出港时间
        String startTime = dsEnterOutPortDTO.getStartTime();
        String endTime = dsEnterOutPortDTO.getEndTime();

        LambdaQueryWrapper<DsEnterOutPort> wrapper = new LambdaQueryWrapper<>(dsEnterOutPort);
        wrapper.ge(StringUtils.isNotBlank(startTime), DsEnterOutPort::getEnterOutTime, startTime)
                .le(StringUtils.isNotBlank(endTime), DsEnterOutPort::getEnterOutTime, endTime)
                .orderByDesc(DsEnterOutPort::getEnterOutTime);
        List<DsEnterOutPort> dsEnterOutPortList = dsEnterOutPortService.list(wrapper);
        ExcelUtil<DsEnterOutPort> util = new ExcelUtil<>(DsEnterOutPort.class);
        util.exportExcel(response, dsEnterOutPortList, "渔船进出港记录（数据来自船位动态监控）数据");
    }

    /**
     * 获取渔船进出港记录（数据来自船位动态监控）详细信息
     *
     * @param dsEnterOutPortDTO:
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-19
     */
    @PostMapping(value = "/detail")
    @ApiOperation(value = "获取渔船进出港记录（数据来自船位动态监控）详细数据")
    public AjaxResult detail(@RequestBody DsEnterOutPortDTO dsEnterOutPortDTO) {
        return success(dsEnterOutPortService.getById(dsEnterOutPortDTO.getId()));
    }

    /**
     * 新增渔船进出港记录（数据来自船位动态监控）信息
     *
     * @param dsEnterOutPort:
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-19
     */
    @RepeatSubmit(message = "请勿重复提交")
    @Log(title = "新增渔船进出港记录（数据来自船位动态监控）", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ApiOperation(value = "新增渔船进出港记录（数据来自船位动态监控）数据")
    public AjaxResult add(@RequestBody DsEnterOutPort dsEnterOutPort) {
        dsEnterOutPort.setCreateAt(new Date());
        return toAjax(dsEnterOutPortService.save(dsEnterOutPort));
    }

    /**
     * 删除渔船进出港记录（数据来自船位动态监控）信息
     *
     * @param dsEnterOutPortDTO: 渔船进出港记录信息数据传输对象
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2024-12-19
     */
    @Log(title = "删除渔船进出港记录（数据来自船位动态监控）", businessType = BusinessType.DELETE)
    @PostMapping("/delete")
    @ApiOperation(value = "批量删除渔船进出港记录（数据来自船位动态监控）数据")
    public AjaxResult delete(@RequestBody DsEnterOutPortDTO dsEnterOutPortDTO) {
        return toAjax(dsEnterOutPortService.removeById(dsEnterOutPortDTO.getId()));
    }

    /**
     * 获取当日出海渔船分页列表
     *
     * @param dsEnterOutPortDTO:
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2024/12/20 17:35
     */
    @Log(title = "获取当日出海渔船分页列表", businessType = BusinessType.DELETE)
    @PostMapping("/outPortPage")
    @ApiOperation(value = "获取当日出海渔船分页列表")
    public TableDataInfo outPortPage(@RequestBody DsEnterOutPortDTO dsEnterOutPortDTO) {
        DsEnterOutPort dsEnterOutPort = getDsEnterOutPort(dsEnterOutPortDTO);
        // 获取当前时间的开始时间
        Date beginOfDay = DateUtil.beginOfDay(new Date());
        LambdaQueryWrapper<DsEnterOutPort> wrapper = new LambdaQueryWrapper<>(dsEnterOutPort);
        wrapper.ge(DsEnterOutPort::getEnterOutTime, beginOfDay)
                // 番禺使用中文，此处暂时使用中文查询，
                .eq(DsEnterOutPort::getEntryDir, EnterOutPortType.OUT_PORT.getCode());
        startPage(dsEnterOutPortDTO.getPageNum(), dsEnterOutPortDTO.getPageSize());
        List<DsEnterOutPort> resList = dsEnterOutPortService.list(wrapper);
        resList.stream()
                .filter(Objects::nonNull)
                .forEach(item -> item.setTerminalCode(item.getDeviceCode()));
        return getDataTable(resList);
    }

    /**
     * 根据渔船进出港数据传输对象转换成渔船进出港数据实体
     *
     * @param dsEnterOutPortDTO: 渔船进出港数据传输对象
     * @return com.ltgk.boat.domain.entity.DsEnterOutPort
     * @author Qi ChengBin
     * @date 2024/12/20 16:51
     */
    private static DsEnterOutPort getDsEnterOutPort(DsEnterOutPortDTO dsEnterOutPortDTO) {
        dsEnterOutPortDTO.queryCheck();
        DsEnterOutPort dsEnterOutPort = new DsEnterOutPort();
        BeanUtils.copyProperties(dsEnterOutPortDTO, dsEnterOutPort);
        return dsEnterOutPort;
    }

    /**
     * 获取待泊区渔船
     *
     * @return {@link List<BoatNavigateStatus>}
     * @throws JsonProcessingException
     */
    @Log(title = "获取待泊区渔船", businessType = BusinessType.DELETE)
    @PostMapping("/getWaitingArea")
    @ApiOperation(value = "获取待泊区渔船")
    public AjaxResult getWaitingArea(@RequestBody GetAreaBoatListReq getAreaBoatListReq) throws JsonProcessingException {
        if (StringUtils.isBlank(getAreaBoatListReq.getMainAreaId())) {
            return success();
        }
        return success(dsEnterOutPortService.getWaitingArea(getAreaBoatListReq));
    }

    /**
     * 获取指定区域的渔船列表
     *
     * @return {@link List<BoatNavigateStatus>}
     * @throws JsonProcessingException
     */
    @Log(title = "获取指定区域的渔船列表", businessType = BusinessType.DELETE)
    @PostMapping("/getRegionBoat")
    @ApiOperation(value = "获取指定区域的渔船列表")
    public AjaxResult getRegionBoat(@Valid @RequestBody GetRegionBoatReq getRegionBoatReq) throws JsonProcessingException {
        return success(dsEnterOutPortService.getRegionBoat(getRegionBoatReq));
    }

    @Log(title = "获取指定区域的渔船回放", businessType = BusinessType.DELETE)
    @PostMapping("/getRegionBoatPlayback")
    @ApiOperation(value = "获取指定区域的渔船回放")
    public AjaxResult getRegionBoatPlayback(@Valid @RequestBody GetRegionBoatPlaybackReq getRegionBoatPlaybackReq) throws JsonProcessingException {
        return success(dsEnterOutPortService.getRegionBoatPlayback(getRegionBoatPlaybackReq));
    }

    /**
     * 自动识别记录：包括AIS/北斗 设备解析和视频识别算法
     *
     * @param req： 自动识别记录请求参数
     * @return java.util.List<?>
     * @author Qi ChengBin
     * @date 2025/3/4
     */
    @PostMapping("/findAutomaticIdentificationList")
    @ApiOperation(value = "查询自动识别列表数据")
    public TableDataInfo findAutomaticIdentificationList(@RequestBody AutomaticIdentificationReq req) {
        return getDataTable(dsEnterOutPortService.findAutomaticIdentificationList(req));
    }

    /**
     * 导出自动识别记录：包括 AIS/北斗 设备解析和视觉识别算法结果
     *
     * @param response：
     * @param req：
     * @author Qi ChengBin
     * @date 2025/3/4
     */
    @PostMapping("/exportAutomaticIdentification")
    @ApiOperation(value = "导出自动识别记录")
    public void exportAutomaticIdentification(HttpServletResponse response, AutomaticIdentificationReq req) {
        req.setPageNum(1);
        req.setPageSize(999999);
        List<AutomaticIdentificationVO> automaticIdentificationList = dsEnterOutPortService.findAutomaticIdentificationList(req);

        ExcelUtil<AutomaticIdentificationVO> util = new ExcelUtil<>(AutomaticIdentificationVO.class);
        util.exportExcel(response, automaticIdentificationList, "导出自动识别记录数据");
    }

    /**
     * 渔船统计管理 - 进出港统计分析
     * -- 接口权限：后台暂未设置权限
     *
     * @param dto: 渔船统计管理 - 进出港统计分析 请求参数
     * @return {@link EnterOutPortStatisticsVO}
     * @author Qi ChengBin
     * @date 2025/3/24
     */
    @PostMapping("/getEnterOutPortStatistics")
    @ApiOperation(value = "渔船统计管理 - 进出港统计分析")
    public AjaxResult getEnterOutPortStatistics(@Validated @RequestBody EnterOutPortStatisticsDTO dto) {
        return success(dsEnterOutPortService.getEnterOutPortStatistics(dto));
    }

    /**
     * 查询未报告渔船管理 - 查询所有未报备的渔船，包括不在系统中管理的渔船（根据长海项目需求）
     *
     * @param req：未报告渔船管理请求参数
     * @return com.ltgk.common.core.page.TableDataInfo
     * @author Qi ChengBin
     * @date 2025/4/11
     */
    @PostMapping("/findNotReportBoatList")
    @ApiOperation(value = "未报告渔船管理")
    public TableDataInfo findNotReportBoatList(@RequestBody NotReportBoatReq req) {
        req.queryCheck();
        return getDataTable(dsEnterOutPortService.findNotReportBoatList(req));
    }
}
