package com.ltgk.boat.service.impl;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ltgk.boat.domain.dto.GetBoatCredentialOverDueListReq;
import com.ltgk.boat.domain.dto.GetBoatEnterOutReq;
import com.ltgk.boat.domain.dto.GetBoatGoSeaReq;
import com.ltgk.boat.domain.dto.GetBoatInsuranceOverDueListReq;
import com.ltgk.boat.domain.entity.DsBoatData;
import com.ltgk.boat.domain.entity.DsBoatInsurance;
import com.ltgk.boat.domain.vo.*;
import com.ltgk.boat.mapper.DsBoatDataMapper;
import com.ltgk.boat.mapper.DsBoatInsuranceMapper;
import com.ltgk.boat.mapper.DsEnterOutPortMapper;
import com.ltgk.boat.service.BoatStatisticsService;
import com.ltgk.common.core.domain.AjaxResult;
import com.ltgk.common.enums.EnterOutPortType;
import com.ltgk.common.utils.DateUtils;
import com.ltgk.port.mapper.DsPortMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.github.pagehelper.page.PageMethod.startPage;

/**
 * @Author: wan kun
 * @Description: 大屏一张图 渔船统计
 * @Date: 2025/2/5 9:25
 * @Version: 1.0
 */
@Slf4j
@Service
public class BoatStatisticsServiceImpl implements BoatStatisticsService {
    @Autowired
    private DsBoatDataMapper dsBoatDataMapper;
    @Autowired
    private DsPortMapper dsPortMapper;
    @Autowired
    private DsEnterOutPortMapper dsEnterOutPortMapper;
    @Autowired
    private DsBoatInsuranceMapper dsBoatInsuranceMapper;
    private Random random = new Random();

    @Override
    public AjaxResult getBoatStatistics() {
        BoatStatisticsVo boatStatisticsVo = new BoatStatisticsVo();
        // 在册船只 -- 所有
        boatStatisticsVo.setBoatCount(dsBoatDataMapper.selectBoatCount(null));
        // 在册船只 -- 本地
        boatStatisticsVo.setLocalBoatCount(dsBoatDataMapper.selectBoatCount(0));
        // 在册船只 -- 外地
        boatStatisticsVo.setForeignBoatCount(dsBoatDataMapper.selectBoatCount(1));
        // 证书信息
        boatStatisticsVo.setBoatCredentialOverDue(dsBoatDataMapper.getBoatCredentialOverDueCount(DateUtils.getNowDate()));
        // 保险信息
        boatStatisticsVo.setBoatInsuranceOverDue(dsBoatInsuranceMapper.selectCount(DateUtils.getNowDate()));
        // AIS感知船
        boatStatisticsVo.setBoatAisCount(dsBoatDataMapper.getOnlineCount(DateUtils.getAgoTime(2, TimeUnit.HOURS)));
        // 泊位总数量
        boatStatisticsVo.setBerthCount(dsPortMapper.getBerthCount(null));
//        // 已用泊位数量
        boatStatisticsVo.setUseBerthCount(Long.valueOf(random.nextInt(50))); // 暂时写死，后期需要修改
        boatStatisticsVo.setAvailableBerthCount(boatStatisticsVo.getBerthCount() - boatStatisticsVo.getUseBerthCount());
        // 每个港口的泊位统计
        boatStatisticsVo.setPortBerthList(dsBoatDataMapper.getPortBerthList());
        return AjaxResult.success(boatStatisticsVo);
    }

    @Override
    public List<BoatGoSeaVo> getBoatGoSea(GetBoatGoSeaReq getBoatGoSeaReq) {
        // 出海作业趋势
        return dsEnterOutPortMapper.selectBoatGoSea(getBoatGoSeaReq);
    }

    @Override
    public List<BoatInsuranceOverDueVo> getBoatInsuranceOverDueList(GetBoatInsuranceOverDueListReq getBoatInsuranceOverDueListReq) {
        startPage(getBoatInsuranceOverDueListReq.getPageNum(), getBoatInsuranceOverDueListReq.getPageSize());
        getBoatInsuranceOverDueListReq.setDate(DateUtils.getNowDate());
        return dsBoatInsuranceMapper.getBoatInsuranceOverDueList(getBoatInsuranceOverDueListReq);
    }

    @Override
    public List<BoatCredentialOverDueVo> getBoatCredentialOverDueList(GetBoatCredentialOverDueListReq getBoatCredentialOverDueListReq) {
        startPage(getBoatCredentialOverDueListReq.getPageNum(), getBoatCredentialOverDueListReq.getPageSize());
        getBoatCredentialOverDueListReq.setDate(DateUtils.getNowDate());
        return dsBoatDataMapper.getBoatCredentialOverDueList(getBoatCredentialOverDueListReq);
    }

    @Override
    public List<GetBoatEnterOutVo> getBoatEnterOut(GetBoatEnterOutReq getBoatEnterOutReq) {
        startPage(getBoatEnterOutReq.getPageNum(), getBoatEnterOutReq.getPageSize());
        String type = null;
        if (ObjectUtils.isNotEmpty(getBoatEnterOutReq.getType())) {
            type = EnterOutPortType.getEnterOutPortType(getBoatEnterOutReq.getType()).getType();
        }
        return dsBoatDataMapper.getBoatEnterOut(getBoatEnterOutReq, type);
    }

    /**
     * 渔船证书统计
     *
     * @return com.ltgk.common.core.domain.AjaxResult
     * @author Qi ChengBin
     * @date 2025/3/25
     */
    @Override
    public BoatCertificateAndInsuranceStatisticsVO getBoatCertificateAndInsuranceStatistics() {
        // 所有渔船证书列表集合
        List<CertificateValidityVO> certificateValidityVOList = dsBoatDataMapper.getCertificateValidityList();
        // 所有渔船保险证书集合
        List<DsBoatInsurance> dsBoatInsuranceList = dsBoatInsuranceMapper.selectList(null);
        // 所有渔船集合
        List<DsBoatData> dsBoatDataList = dsBoatDataMapper.selectList(null);

        // 证书正常的 boatId 列表
        Set<String> certificateNormalBoatIdSet = certificateValidityVOList.stream().filter(certificateValidityVO ->
                // 捕捞许可证
                (ObjectUtils.isEmpty(certificateValidityVO.getFishingValidity()) || certificateValidityVO.getFishingValidity().after(DateUtils.getNowDate()))
                        // 渔船校验
                        &&
                        (ObjectUtils.isEmpty(certificateValidityVO.getExamineValidity()) || certificateValidityVO.getExamineValidity().after(DateUtils.getNowDate()))
                        // 船名登记
                        &&
                        (ObjectUtils.isEmpty(certificateValidityVO.getNameValidity()) || certificateValidityVO.getNameValidity().after(DateUtils.getNowDate()))
                        // 国籍所有权登记
                        &&
                        (ObjectUtils.isEmpty(certificateValidityVO.getNationalityValidity()) || certificateValidityVO.getNationalityValidity().after(DateUtils.getNowDate()))
                        // 渔业船网工具
                        &&
                        (ObjectUtils.isEmpty(certificateValidityVO.getNetValidity()) || certificateValidityVO.getNetValidity().after(DateUtils.getNowDate()))
        ).map(CertificateValidityVO::getBoatId).collect(Collectors.toSet());

        // 保险证书正常的 boatId 列表
        Set<String> insuranceNormalBoatIdSet = dsBoatInsuranceList.stream().filter(dsBoatInsurance ->
                // 保险证书
                ObjectUtils.isEmpty(dsBoatInsurance.getInsuranceEndTime()) || dsBoatInsurance.getInsuranceEndTime().after(DateUtils.getNowDate())
        ).map(DsBoatInsurance::getBoatId).collect(Collectors.toSet());

        // 渔船正常数量
        long boatNormalNum = dsBoatDataList.stream().filter(dsBoatData ->
                // 渔船证书 正常
                certificateNormalBoatIdSet.contains(dsBoatData.getBoatId())
                        // 渔船 保险证书 正常
                        && insuranceNormalBoatIdSet.contains(dsBoatData.getBoatId())
        ).count();

        // 渔船证书过期的 boatId 列表
        Set<String> certificateOverdueBoatIdSet = certificateValidityVOList.stream().filter(certificateValidityVO ->
                // 捕捞许可证
                (ObjectUtils.isNotEmpty(certificateValidityVO.getFishingValidity()) && certificateValidityVO.getFishingValidity().before(DateUtils.getNowDate()))
                        // 渔船校验
                        ||
                        (ObjectUtils.isNotEmpty(certificateValidityVO.getExamineValidity()) && certificateValidityVO.getExamineValidity().before(DateUtils.getNowDate()))
                        // 船名登记
                        ||
                        (ObjectUtils.isNotEmpty(certificateValidityVO.getNameValidity()) && certificateValidityVO.getNameValidity().before(DateUtils.getNowDate()))
                        // 国籍所有权登记
                        ||
                        (ObjectUtils.isNotEmpty(certificateValidityVO.getNationalityValidity()) && certificateValidityVO.getNationalityValidity().before(DateUtils.getNowDate()))
                        // 渔业船网工具
                        ||
                        (ObjectUtils.isNotEmpty(certificateValidityVO.getNetValidity()) && certificateValidityVO.getNetValidity().before(DateUtils.getNowDate()))
        ).map(CertificateValidityVO::getBoatId).collect(Collectors.toSet());
        // 渔船证书过期数量
        long boatCertificateOverdueNum = dsBoatDataList.stream().filter(dsBoatData ->
                // 渔船证书过期
                certificateOverdueBoatIdSet.contains(dsBoatData.getBoatId())
        ).count();

        // 渔船保险过期的 boatId 列表
        Set<String> insuranceOverdueBoatIdSet = dsBoatInsuranceList.stream().filter(dsBoatInsurance ->
                // 保险证书
                ObjectUtils.isNotEmpty(dsBoatInsurance.getInsuranceEndTime()) && dsBoatInsurance.getInsuranceEndTime().before(DateUtils.getNowDate())
        ).map(DsBoatInsurance::getBoatId).collect(Collectors.toSet());
        // 渔船保险过期数量
        long boatInsuranceOverdueNum = dsBoatDataList.stream().filter(dsBoatData ->
                // 渔船证书过期
                insuranceOverdueBoatIdSet.contains(dsBoatData.getBoatId())
        ).count();

        // 没有证书信息渔船数量
        long noCertificateNum = dsBoatDataList.stream().filter(dsBoatData ->
                certificateValidityVOList.stream().noneMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
        ).count();
        // 没有保险信息渔船数量
        long noInsuranceNum = dsBoatDataList.stream().filter(dsBoatData ->
                dsBoatInsuranceList.stream().noneMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
        ).count();

        // 只有证书 没有保险
        long onlyCertificateNoInsuranceNum = certificateValidityVOList.stream().filter(certificateValidityVO ->
                dsBoatInsuranceList.stream().noneMatch(obj -> obj.getBoatId().equals(certificateValidityVO.getBoatId()))
        ).count();
        // 只有保险 没有证书
        long onlyInsuranceNoCertificateNum = dsBoatInsuranceList.stream().filter(certificateValidityVO ->
                certificateValidityVOList.stream().noneMatch(obj -> obj.getBoatId().equals(certificateValidityVO.getBoatId()))
        ).count();

        // 均没有渔船数量
        long allNoNum = dsBoatDataList.stream().filter(dsBoatData ->
                dsBoatInsuranceList.stream().noneMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
                        // 渔船 保险证书 正常
                        && certificateValidityVOList.stream().noneMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
        ).count();

        // 有证书又有保险的渔船的数量
        long allHaveNum = dsBoatDataList.stream().filter(dsBoatData ->
                dsBoatInsuranceList.stream().anyMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
                        // 渔船 保险证书 正常
                        && certificateValidityVOList.stream().anyMatch(obj -> obj.getBoatId().equals(dsBoatData.getBoatId()))
        ).count();

        // 渔船数量
        int boatNum = dsBoatDataList.size();

        log.info("渔船证书和保险:\n正常数量: {}\n 证书过期数量:{}\n 保险过期数量:{}\n 没有证书信息渔船数量:{}\n 没有保险信息渔船数量:{}\n 只有证书 没有保险:{}\n 只有保险 没有证书:{}\n 均没有渔船数量:{}\n 有证书又有保险：{}\n 渔船数量:{}"
                , boatNormalNum, boatCertificateOverdueNum, boatInsuranceOverdueNum, noCertificateNum, noInsuranceNum, onlyCertificateNoInsuranceNum, onlyInsuranceNoCertificateNum, allNoNum, allHaveNum, boatNum);


        return new BoatCertificateAndInsuranceStatisticsVO()
                .setBoatNormal(boatNormalNum)
                .setBoatNormalPercentage(Math.round((double) boatNormalNum / (double) boatNum * 10000.00) / 10000.00 * 100.00)
                .setBoatCredentialOverDue(boatCertificateOverdueNum)
                .setBoatCredentialOverDuePercentage(Math.round((double) boatCertificateOverdueNum / (double) boatNum * 10000.00) / 10000.00 * 100.00)
                .setBoatInsuranceOverDue(boatInsuranceOverdueNum)
                .setBoatInsuranceOverDuePercentage(Math.round((double) boatInsuranceOverdueNum / (double) boatNum * 10000.00) / 10000.00 * 100.00)
                ;
    }
}
