package com.shanghaichengdi.ghjgitem.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.shanghaichengdi.ghjgitem.enums.SupervisionAreaCode;
import com.shanghaichengdi.ghjgitem.exception.EnumException;
import com.shanghaichengdi.ghjgitem.mapper.CommonMapper;
import com.shanghaichengdi.ghjgitem.service.CommonService;
import com.shanghaichengdi.ghjgitem.util.PrintLogUtils;
import com.shanghaichengdi.ghjgitem.vo.*;
import com.shanghaichengdi.ghjgitem.vo.request.*;
import com.shanghaigeography.Util.DateUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

@Service
@Slf4j
public class CommonServiceImpl implements CommonService {

    @Resource
    CommonMapper mapper;

    @Value("${interface.esService}")
    String esService;

    @Override
    public List<BoatAISVo> selectAisRealTimeXYList(BoatAisRealTimeReq param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectAisRealTimeXYList(param);
    }


    @Override
    public List<BoatAISVo> selectAisRealTimePointList(List mmsiList) {
        return mapper.selectAisRealTimePointList(mmsiList);

    }

    @Override
    public String selectRecordOrDocNumber(SupervisionOrDocNumberReq param) {
        // 港航行业监管告知书编码规则为：区代码+年份+五位流水号。
        String areaCode = SupervisionAreaCode.getByCode(param.getAreaCode()).getCode();
        Integer year = LocalDate.now().getYear();
        String codeInOracle = null;
        StringBuilder supervisionOrDocNumber = null;
        String rules = areaCode + year;
        if (!Objects.isNull(param.getStationCode())) {
            rules = rules + param.getStationCode();
        }
        if ("inform".equals(param.getType())) {
            codeInOracle = mapper.getLastInformNo(rules);
        } else if ("record".equals(param.getType())) {
            codeInOracle = mapper.getLastRecordNo(rules);
        } else {
            throw new RuntimeException("类型输入有误");
        }
        if (Objects.isNull(codeInOracle)) {
            codeInOracle = rules;
            // 根据实际规则，除最后一位之外都补0
            for (int i = 0; i < 11 - rules.length() - 1; i++) {
                codeInOracle = codeInOracle + "0";
            }
            codeInOracle = codeInOracle + "1";
            return codeInOracle;
        }
        Integer next = Integer.parseInt(codeInOracle.substring(rules.length())) + 1;
        supervisionOrDocNumber = new StringBuilder(rules);
        // 根据实际规则，除最后一位之外都补0
        for (int i = 0; i < 11 - rules.length() - String.valueOf(next).length(); i++) {
            supervisionOrDocNumber.append("0");
        }
        supervisionOrDocNumber.append(next);
        return supervisionOrDocNumber.toString();
    }

    @Override
    public List<CCbCargoDeclareRecVo> selectCargoDeclareInfo(ReportSubInfoReq param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectCargoDeclareInfo(param);
    }

    @Override
    public List<CCbOnShipCrewRecVo> selectShipCrewInfo(ReportSubInfoReq param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectShipCrewInfo(param);
    }

    @Override
    public List<VwCertInfoSelfAllVo> selectCertInfoList(PageVo param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectInfoList();
    }

    @Override
    public List<ShipDataVo> selectBoatInfoList(ShipDataRequest param) {
        // 批量查询判断
        String mmsi = param.getMmsi();
        if (mmsi != null && mmsi.split(",").length > 1){
            if(mmsi.split(",").length > 100){
                throw new EnumException("mmsi批量查询不得超过100条");
            }
            List<ShipDataVo> list = new ArrayList<>();
            List<String> mmsiList = Arrays.asList(mmsi.split(","));
            for(int i=0; i<mmsiList.size();i++){
                mmsiList.set(i, "'" + mmsiList.get(i) + "'");
                System.out.println(mmsiList.get(i));
            }
            param.setMmsiList(mmsiList);
            param.setMmsi("");
        }

        String shipNameCn = param.getShipNameCn();
        if (shipNameCn != null && shipNameCn.split(",").length > 1){
            if(shipNameCn.split(",").length > 100){
                throw new EnumException("shipNameCn批量查询不得超过100条");
            }
            List<ShipDataVo> list = new ArrayList<>();
            List<String> shipNameCnList = Arrays.asList(shipNameCn.split(","));
            for(int i=0; i<shipNameCnList.size();i++){
                shipNameCnList.set(i, "'" + shipNameCnList.get(i) + "'");
                System.out.println(shipNameCnList.get(i));
            }
            param.setShipNameCnList(shipNameCnList);
            param.setShipNameCn("");
        }
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectBoatInfoList(param);
    }

    @Override
    public List<BoatReportInfoVo> selectBoatReportInfoList(ReportInfoRequest param)
            throws ParseException {
        String startTime = param.getDateFrom() + " 00:00:00";
        String endTime = param.getDateTo() + " 23:59:59";
//        String partition = "SHIP_REPORT_" + DateUtils.dateToString(
//                DateUtils.stringToDate(param.getDateFrom(), DateUtils.DATE_FORMAT_10),
//                DateUtils.DATE_FORMAT_11);

        List<String> datesBetween = PollutantBoatWaterReq.getDatesBetween(
                startTime,
                endTime);

        List<String> tableNameList = new ArrayList<>();
        String partitionPrefix = "SHIP_REPORT_";
        datesBetween.forEach(
                x -> tableNameList.add("GHJG_BASICS.c_cb_ship_eep_report_rec " + "partition(" +
                        partitionPrefix + x + ")" + " t"));
        log.info("查询的表名为:{}", JSONObject.toJSONString(tableNameList));


        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectBoatReportInfoList(
                param.getReportId(),
                "",
                param.getDistrict(),
                param.getShipId(),
                startTime,
                endTime,
                tableNameList,
                param.getReportNo());
    }

    @Override
    public List<BoatContactVo> selectBoatContactByMmsi(ShipDataRequest param) throws Exception{
        String[] mmsis = param.getMmsi().split(",");
        if (mmsis != null && mmsis.length > 0){
            if(mmsis.length > 500){
                throw new EnumException("mmsi批量查询不得超过500条");
            }
            List<String> mmsiList = Arrays.asList(mmsis);
            for(int i=0; i<mmsiList.size();i++){
                mmsiList.set(i, "'" + mmsiList.get(i) + "'");
            }
            param.setMmsiList(mmsiList);
            param.setMmsi("");
        }

        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        List<ShipDataVo> shipDataVoList = mapper.selectBoatContactInfoByMmsi(param);
        log.info("匹配到船舶基础信息：{}",shipDataVoList.toString());

        List<BoatContactVo> baotContactList =new ArrayList<>();
        for(ShipDataVo shipDataVo : shipDataVoList){
            BoatContactVo boatContactVo = new BoatContactVo();
            ReportInfoRequest reportReq = new ReportInfoRequest();
            reportReq.setShipId(shipDataVo.getShipId());
            reportReq.setPageIndex(1);
            reportReq.setPageSize(1);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.set(Calendar.HOUR_OF_DAY, -48);
            reportReq.setDateFrom(DateUtils.dateToString(calendar.getTime(), DateUtils.DATE_FORMAT_10));
            reportReq.setDateTo(DateUtils.dateToString(new Date(), DateUtils.DATE_FORMAT_10));
            List<BoatReportInfoVo> reportVoList = selectBoatReportInfoList(reportReq);

            boatContactVo.setMmsi(shipDataVo.getMmsi());
            boatContactVo.setShipId(shipDataVo.getShipId());
            if(!reportVoList.isEmpty()){
                boatContactVo.setContact(reportVoList.get(0).getBidName());
                boatContactVo.setPhone(reportVoList.get(0).getMobilePhone());
            }else{
                boatContactVo.setContact(shipDataVo.getOwnerLegalPerson());
                boatContactVo.setPhone(shipDataVo.getOwnerContactPhone());
            }

            baotContactList.add(boatContactVo);
        }

        return baotContactList;
    }

    @Override
    public List<ShipDataVo> obscureSelectBoatInfoList(ShipDataRequest param) {
        param.setPageIndex(1);
        param.setPageSize(1);
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.obscureSelectBoatInfoList(param);
    }

    @Override
    public CountVo getRangeCount(ShipRangeReq param) {
        return mapper.selectCountByRange(param);
    }

    @Override
    public List<ShipDataVo> getRangeDetail(ShipRangeReq param) {
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectBoatInfoByRange(param);
    }

    @Override
    public List<ShipDataVo> getMmsiDetail(ShipMmsiReq param) throws ParseException {
        List<String> reportTablePartition = getReportTablePartition();
        List<String> tableNameList = new ArrayList<>();
        String partitionPrefix = "SHIP_REPORT_";
        reportTablePartition.forEach(
                x -> tableNameList.add("GHJG_BASICS.c_cb_ship_eep_report_rec " + "partition(" +
                        partitionPrefix + x + ")" + " t"));
        log.info("查询的表名为:{}", JSONObject.toJSONString(tableNameList));
        param.setTableNameList(tableNameList);
        param.setPageSize(1);
        param.setPageIndex(1);
        PageHelper.startPage(param.getPageIndex(), param.getPageSize());
        return mapper.selectBoatInfoByMmsi(param);
    }

    private static List<String> getReportTablePartition() throws ParseException {
        Date appearTime = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(appearTime);
        calendar.add(Calendar.HOUR_OF_DAY, -24);
        Date startDate = calendar.getTime();
        List<String> dates = new ArrayList<>();
        dates.add(DateUtils.dateToString(startDate, DateUtils.DATE_FORMAT_11));
        dates.add(DateUtils.dateToString(appearTime, DateUtils.DATE_FORMAT_11));
        return dates;
    }

    @Override
    public List<BoatPathVo> selectBoatPathList(BoatPathReq param) {
        try {
            String mmsi = param.getMmsi();
            String startTime = param.getStartTime();
            String endTime = param.getEndTime();
            LocalDate startDate = LocalDate.parse(
                    DateUtils.dateToString(DateUtils.stringToDate(startTime, DateUtils.DATE_FORMAT_10),
                            DateUtils.DATE_FORMAT_10));
            LocalDate endDate = LocalDate.parse(
                    DateUtils.dateToString(DateUtils.stringToDate(endTime, DateUtils.DATE_FORMAT_10),
                            DateUtils.DATE_FORMAT_10));
            LocalDate now = LocalDate.now();
            long daysDiff = ChronoUnit.DAYS.between(startDate, now);
            log.info("查询轨迹相差天数为======>{}", daysDiff);
            if (daysDiff >= 30) {
                // 走融合后的历史轨迹
                log.info("走融合后的历史轨迹");
                return mapper.selectBoatPathFromMvwHistory(mmsi, startTime, endTime);
            } else {
                // 走ES的历史轨迹
                log.info("走ES的历史轨迹");
                return getBoatPathFromEs(mmsi, startTime, endTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
            PrintLogUtils.printErrorLogInfo(e, "selectBoatPathList异常：");
            return null;
        }
    }

    private List<BoatPathVo> getBoatPathFromEs(String mmsi, String startTime, String endTime) throws Exception {
        try {
            List<BoatPathVo> resultList = new ArrayList<>();
            Objects.requireNonNull(mmsi, "mmsi can not be null!");
            Objects.requireNonNull(startTime, "startTime can not be null!");
            Objects.requireNonNull(endTime, "endTime can not be null!");
            JSONObject boatPathRequest = new JSONObject();
            boatPathRequest.put("deviceId", mmsi);
            boatPathRequest.put("startTime", startTime);
            boatPathRequest.put("endTime", endTime);
            HttpRequest post = HttpUtil.createPost(esService + "ais/get_info");
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json;charset=utf-8");
            post.addHeaders(headers);
            log.info("开始查询时间:{}", DateUtils.dateToString(new Date(), DateUtils.DATE_FORMAT_19));
            String body = post.body(JSONObject.toJSONString(boatPathRequest)).setReadTimeout(3600000)
                    .execute()
                    .body();
            log.info("结束查询时间:{}", DateUtils.dateToString(new Date(), DateUtils.DATE_FORMAT_19));
            JSONObject jsonObject = JSONObject.parseObject(body);
            String code = jsonObject.get("code").toString();
            if (code.equals("200") && jsonObject.get("data") != null) {
                JSONObject data = (JSONObject) jsonObject.get("data");
                if (data.get("Rows") != null) {
                    JSONObject rows = (JSONObject) data.get("Rows");
                    if (rows.get("list") != null) {
                        JSONArray list = (JSONArray) rows.get("list");
                        for (int i = 0; i < list.size(); i++) {
                            JSONObject row = (JSONObject) list.get(i);
                            // 格式化航向，保留两位小数
                            BigDecimal directionBd = new BigDecimal(Double.toString(row.getDouble("direction")));
                            directionBd = directionBd.setScale(2, RoundingMode.HALF_UP); // 保留两位小数
                            double direction = directionBd.doubleValue();
                            // 格式化航速，保留两位小数
                            BigDecimal velocityBd = new BigDecimal(Double.toString(row.getDouble("velocity")));
                            velocityBd = velocityBd.setScale(2, RoundingMode.HALF_UP); // 保留两位小数
                            double velocity = velocityBd.doubleValue();

                            // 格式化经度，保留两位小数
                            BigDecimal longitudeBd = new BigDecimal(Double.toString(row.getDouble("longitude")));
                            longitudeBd = longitudeBd.setScale(8, RoundingMode.HALF_UP); // 保留8位小数
                            double longitude = longitudeBd.doubleValue();

                            // 格式化纬度，保留两位小数
                            BigDecimal latitudeBd = new BigDecimal(Double.toString(row.getDouble("latitude")));
                            latitudeBd = latitudeBd.setScale(8, RoundingMode.HALF_UP); // 保留8位小数
                            double latitude = latitudeBd.doubleValue();

                            // 格式化纬度，保留两位小数
                            BigDecimal mapxBd = new BigDecimal(Double.toString(row.getDouble("mapx")));
                            mapxBd = mapxBd.setScale(8, RoundingMode.HALF_UP); // 保留8位小数
                            double mapx = mapxBd.doubleValue();

                            // 格式化纬度，保留两位小数
                            BigDecimal mapyBd = new BigDecimal(Double.toString(row.getDouble("mapy")));
                            mapyBd = mapyBd.setScale(8, RoundingMode.HALF_UP); // 保留8位小数
                            double mapy = mapyBd.doubleValue();

                            BoatPathVo boatPathVo = new BoatPathVo();
                            boatPathVo.setMmsi(row.getString("deviceid"));
                            boatPathVo.setDirection(direction);
                            boatPathVo.setVelocity(velocity);
                            boatPathVo.setLongitude(longitude);
                            boatPathVo.setLatitude(latitude);
                            boatPathVo.setTime(row.getString("gpstime"));
                            boatPathVo.setMapX(String.valueOf(mapx));
                            boatPathVo.setMapY(String.valueOf(mapy));
                            resultList.add(boatPathVo);
                        }
                    }
                }
            }
            return resultList;
        } catch (Exception e) {
            e.printStackTrace();
            PrintLogUtils.printErrorLogInfo(e, "getBoatPathFromEs异常：");
            return null;
        }
    }

    @Override
    public ShipInfoForShipLockVo selectBoatInfoByShipId(String shipId) {
        return mapper.selectBoatInfoByShipId(shipId);
    }

    @Override
    public CargoInfoForShipLockVo selectCargoDeclareInfoByShipId(String shipId) {
        String startPartition3 = DateUtils.dateToString(new Date(), "yyyyMMdd");
        String startPartition2 = DateUtils.dateToString(DateUtils.dayAddNum(new Date(), -1), "yyyyMMdd");
        String startPartition1 = DateUtils.dateToString(DateUtils.dayAddNum(new Date(), -1), "yyyyMMdd");
        String partitionPrefix = "SHIP_REPORT_";
        ArrayList<String> list = new ArrayList<>();
        list.add(partitionPrefix + startPartition1);
        list.add(partitionPrefix + startPartition2);
        list.add(partitionPrefix + startPartition3);
        List<CargoInfoForShipLockVo> cargoInfoForShipLockVo = mapper.selectCargoDeclareInfoByShipId(shipId, list);
        if (cargoInfoForShipLockVo.isEmpty()) {
            return new CargoInfoForShipLockVo();
        } else {
            cargoInfoForShipLockVo.sort((o1, o2) -> o2.getLastUpdateDate().compareTo(o1.getLastUpdateDate()));
            cargoInfoForShipLockVo.get(0).setLastUpdateDate(null);
            return  cargoInfoForShipLockVo.get(0);
        }
    }

    @Override
    public boolean checkInportByMmsiAndShipName(String mmsi, String shipName){
        boolean flag = false;
        int count = mapper.getPdShipCountByMmsiAndShipName(mmsi,shipName);
        if(count > 0) {
          flag = true;
        }
        return flag;
    }

    @Override
    public boolean checkInportByShipId(String shipId){
        boolean flag = false;
        int count = mapper.getPdShipCountByShipId(shipId);
        if(count > 0) {
            flag = true;
        }
        return flag;
    }

    @Override
    public List<String> getPortDrawPicture(PortDrawReq portDrawReq) {
        PageHelper.startPage(portDrawReq.getPageIndex(), portDrawReq.getPageSize());
        List<String> list = mapper.selectPdPortDrawPicture(portDrawReq);
        List<String> pictures = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }else {
//            list.forEach(x -> x = "http://10.83.68.109:8080/ghjgWebServiceTest/supervise/" + x);
            for (String s : list) {
                pictures.add("http://10.83.68.109:8080/ghjgWebServiceTest/supervise/" + s.replaceAll("\\\\","/"));
            }
        }
        return pictures;
    }


}
