package com.xxfc.platform.campsite.biz;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.campsite.dto.*;
import com.xxfc.platform.campsite.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xxfc.platform.campsite.entity.CampsiteShop;
import com.xxfc.platform.campsite.mapper.CampsiteShopMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 营地店铺表
 *
 * @author libin
 * @email 18178966185@163.com
 * @date 2019-06-17 10:28:48
 */
@Service
@Slf4j
public class CampsiteShopBiz extends BaseBiz<CampsiteShopMapper,CampsiteShop> {
     /**
     * 地球半径,单位 km
     */
     private static final double EARTH_RADIUS = 6378.137;

       @Autowired
       private CampsiteShopTagBiz campsiteShopTagBiz;

       @Autowired
       private CampsiteShopCarouselBiz campsiteShopCarouselBiz;

    /**
     * 根据店铺类型查找列表
     * @param type
     * @return
     */
    public PageDataVO<CampsiteShopPageVo> findCampsiteShopPageByType(Integer type,Integer pageNo,Integer pageSize) {
         //根据type类型查找店铺
        PageDataVO<CampsiteShopPageDTO> pageDataVO = PageDataVO.pageInfo(pageNo, pageSize, () -> mapper.findAllCampsiteShopsByType(type));
        List<CampsiteShopPageDTO> campsiteShopPageDTOS = pageDataVO.getData();

        PageDataVO<CampsiteShopPageVo> campsiteShopPageDataVO = new PageDataVO<>();
        campsiteShopPageDataVO.setTotalPage(pageDataVO.getTotalPage());
        campsiteShopPageDataVO.setTotalCount(pageDataVO.getTotalCount());
        campsiteShopPageDataVO.setPageSize(pageDataVO.getPageSize());
        campsiteShopPageDataVO.setPageNum(pageDataVO.getPageNum());
        if (CollectionUtils.isEmpty(campsiteShopPageDTOS)){
            return  campsiteShopPageDataVO;
        }
        if (log.isDebugEnabled()){
            log.debug("根据type=【{}】查询到的店铺数据：【{}】",type,campsiteShopPageDTOS);
        }
        List<CampsiteShopPageVo> campsiteShopPageVoList = new ArrayList<>();
        for (CampsiteShopPageDTO campsiteShopPageDTO : campsiteShopPageDTOS) {
            CampsiteShopPageVo campsiteShopPageVo = new CampsiteShopPageVo();
            BeanUtils.copyProperties(campsiteShopPageDTO,campsiteShopPageVo);
            campsiteShopPageVoList.add(campsiteShopPageVo);
        }
        campsiteShopPageVoList.sort(Comparator.comparing(CampsiteShopPageVo::getHot).reversed().thenComparing(CampsiteShopPageVo::getCrtTime).reversed());
        campsiteShopPageDataVO.setData(campsiteShopPageVoList);
        return campsiteShopPageDataVO;
    }

    /**
     * 根据店铺id查询店铺详情
     * @param id
     * @return
     */
    public CampsiteShopDetailVo findCampsiteShopDetailById(Integer id,Double longitude,Double latitude) {

        CampsiteShopDetailVo campsiteShopDetailVo = new CampsiteShopDetailVo();

        //从店铺表根据店铺id查询
          CampsiteShopDetailDTO  campsiteShopDetailDTO = mapper.findCampsiteShopDetailById(id);
          if (log.isDebugEnabled()){
              log.debug("根据店铺id=【{}】查询出店铺信息【{}】",id,campsiteShopDetailDTO);
          }
          BeanUtils.copyProperties(campsiteShopDetailDTO,campsiteShopDetailVo);
         //从轮播表根据店铺id查询
         List<CampsiteShopCarouselDetailDTO> campsiteShopCarouselDTOS  = campsiteShopCarouselBiz.findByCampsiteShopId(id);
         if (log.isDebugEnabled()){
             log.debug("根据店铺id=【{}】查询出店铺轮播图信息：【{}】",id,campsiteShopCarouselDTOS);
         }
         List<CampsiteShopCarouselDetailVo> campsiteShopCarouselDetailVos = new ArrayList<>();
         if (CollectionUtils.isNotEmpty(campsiteShopCarouselDTOS)) {
             campsiteShopCarouselDTOS.forEach(campsiteShopCarouselDetailDTO -> {
                 CampsiteShopCarouselDetailVo carouselDetailVo = new CampsiteShopCarouselDetailVo();
                 BeanUtils.copyProperties(campsiteShopCarouselDetailDTO, carouselDetailVo);
                 campsiteShopCarouselDetailVos.add(carouselDetailVo);
             });
         }
         campsiteShopDetailVo.setCampsiteShopCarouselDetailVos(campsiteShopCarouselDetailVos);
         //从店铺类型表根据店铺id查询 -->类型列表拼接
        List<CampsiteShopTagDTO> shopTagDTOS = campsiteShopTagBiz.findByCampsiteShopId(id);
        if (log.isDebugEnabled()){
             log.debug("根据店铺id=【{}】查询出店铺类型:【{}】",id,shopTagDTOS);
         }
         campsiteShopDetailVo.setTypeNames(shopTagDTOS==null?Collections.EMPTY_LIST:shopTagDTOS.stream().map(CampsiteShopTagDTO::getName).collect(Collectors.toList()));
        //根据经纬度算距离
         double distance = getDistance(campsiteShopDetailDTO.getLongitude(),campsiteShopDetailDTO.getLatitude(),longitude,latitude);
         if (log.isDebugEnabled()){
             log.debug("根据店铺经度=【{}】,纬度=【{}】和自己所在位置的经度=【{}】,纬度=【{}】计算出的距离：【{}km】",campsiteShopDetailDTO.getLongitude(),campsiteShopDetailDTO.getLatitude(),longitude,latitude,distance);
         }
         campsiteShopDetailVo.setDistance(String.format("%.1f",distance));
        return  campsiteShopDetailVo;
    }

    /**
     * 根据创建时间或营地名称来查找营地列表
     * @param campsiteShopAdminFindDTO
     * @return
     */
    public PageDataVO<CampsiteShopAdminPageVo> findCampsiteShopPage(CampsiteShopAdminFindDTO campsiteShopAdminFindDTO) {
        if (log.isDebugEnabled()){
            log.debug("查询条件：【{}】",campsiteShopAdminFindDTO);
        }

        //筛选时间处理
      /*  Long startTime = campsiteShopAdminFindDTO.getStartTime();
        Long endTime = campsiteShopAdminFindDTO.getEndTime();
        if (startTime==null || endTime ==null){
            Long processTime = startTime!=null?startTime:(endTime!=null?endTime:null);
            if (processTime!=null){
             campsiteShopAdminFindDTO.setStartTime(processStartTime(processTime));
             campsiteShopAdminFindDTO.setEndTime(processEndTime(processTime));
            }
        }else {
            campsiteShopAdminFindDTO.setStartTime(processStartTime(startTime));
            campsiteShopAdminFindDTO.setEndTime(processEndTime(endTime));
        }*/
        PageDataVO<CampsiteShopAdminPageDTO> campsiteShopAdminpageDTOPageDataVO = PageDataVO.pageInfo(campsiteShopAdminFindDTO.getPage(),campsiteShopAdminFindDTO.getLimit(),()->mapper.findAllCampsiteShops(campsiteShopAdminFindDTO));
        List<CampsiteShopAdminPageDTO> campsiteShopAdminPageDTOS = campsiteShopAdminpageDTOPageDataVO.getData();
        if (log.isDebugEnabled()){
            log.debug("查询结果：【{}】",campsiteShopAdminPageDTOS);
        }
        PageDataVO<CampsiteShopAdminPageVo> campsiteShopAdminPageDataVos = new PageDataVO<>();
        if (CollectionUtils.isEmpty(campsiteShopAdminPageDTOS)){
            return campsiteShopAdminPageDataVos;
        }
        //转换成营地ids
        List<Integer> campsiteShopIds = campsiteShopAdminPageDTOS.stream().map(CampsiteShopAdminPageDTO::getId).collect(Collectors.toList());
        //根据营地ids查询营地对应的标签  键营地id  值对应的标签列表
        Map<Integer,List<String>> shopTagsMap = campsiteShopTagBiz.findByCampsiteShopIds(campsiteShopIds);
        if (log.isDebugEnabled()){
            log.debug("营地id为:【{}】的类型【{}】",campsiteShopIds,shopTagsMap);
        }
        campsiteShopAdminPageDTOS = campsiteShopAdminPageDTOS.stream().peek(campsiteShopAdminPageDTO -> {
            if (Objects.nonNull(shopTagsMap)) {
                List<String> tagNames = shopTagsMap.get(campsiteShopAdminPageDTO.getId());
                campsiteShopAdminPageDTO.setStoreTypeName(tagNames == null ? new ArrayList<String>() : tagNames);
            }
        }).sorted(Comparator.comparing(CampsiteShopAdminPageDTO::getHot).reversed().thenComparing(CampsiteShopAdminPageDTO::getCrtTime).reversed()).collect(Collectors.toList());
        //组装数据
        campsiteShopAdminPageDataVos.setTotalPage(campsiteShopAdminpageDTOPageDataVO.getTotalPage());
        campsiteShopAdminPageDataVos.setTotalCount(campsiteShopAdminpageDTOPageDataVO.getTotalCount());
        campsiteShopAdminPageDataVos.setPageSize(campsiteShopAdminpageDTOPageDataVO.getPageSize());
        campsiteShopAdminPageDataVos.setPageNum(campsiteShopAdminpageDTOPageDataVO.getPageNum());
        campsiteShopAdminPageDataVos.setData(JSONObject.parseObject(JSONObject.toJSONString(campsiteShopAdminPageDTOS),new TypeReference<List<CampsiteShopAdminPageVo>>(){}));
        return campsiteShopAdminPageDataVos;
    }

    /**
     * 营地保存或更新
     * @param campsiteShopAdminDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public int saveCampsiteShop(CampsiteShopAdminDTO campsiteShopAdminDTO) {
        CampsiteShop campsiteShop = new CampsiteShop();
        campsiteShopAdminDTO.setName(campsiteShopAdminDTO.getName()==null?null:campsiteShopAdminDTO.getName().trim());
        BeanUtils.copyProperties(campsiteShopAdminDTO,campsiteShop);
        int effectRows = 0;
        if (Objects.nonNull(campsiteShopAdminDTO.getId())){
            if (log.isDebugEnabled()){
                log.debug("更新营地的信息：【{}】",campsiteShop);
            }
             //更新操作
            campsiteShop.setUpdTime(Instant.now().toEpochMilli());
           effectRows =  mapper.updateByPrimaryKeySelective(campsiteShop);
        }else {
            //保存操作
            //保存营地信息
            if (log.isDebugEnabled()){
                log.debug("保存营地的信息：【{}】",campsiteShop);
            }
            campsiteShop.setCrtTime(Instant.now().toEpochMilli());
             effectRows = mapper.insertSelective(campsiteShop);
        }
        //保存或更新 * 营地与 轮播图信息
        List<CampsiteShopCarouselDTO> carouselDTOS = campsiteShopAdminDTO.getCarouselDTOS();
        if (CollectionUtils.isNotEmpty(carouselDTOS)) {
            carouselDTOS.stream().peek(campsiteShopCarouselDTO -> campsiteShopCarouselDTO.setShopId(campsiteShop.getId())).count();
        }
        campsiteShopCarouselBiz.saveBatch(carouselDTOS,campsiteShop.getId());

        //保存或更新 * 营地与营地类型信息
        List<Integer> campsiteTagDTOS = campsiteShopAdminDTO.getCampsiteTagDTOS();
        campsiteShopTagBiz.saveBatch(campsiteTagDTOS,campsiteShop.getId());
        return effectRows;
    }

    /**
     * 编辑查询
     * @param id
     * @return
     */
    public CampsiteShopAdminVO findByCampsiteId(Integer id) {
        CampsiteShopAdminVO campsiteShopAdminVO = new CampsiteShopAdminVO();
        CampsiteShop campsiteShop = new CampsiteShop();
        campsiteShop.setId(id);
        CampsiteShop shop = mapper.selectOne(campsiteShop);
        BeanUtils.copyProperties(shop, campsiteShopAdminVO);

        //根据营地id查询轮播
        List<CampsiteShopCarouselDetailDTO> shopCarouselDetailDTOS = campsiteShopCarouselBiz.findByCampsiteShopId(id);
        List<CampsiteShopCarouselVo> campsiteShopCarouselVos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(shopCarouselDetailDTOS)) {
            shopCarouselDetailDTOS.forEach(campsiteShopCarouselDetailDTO -> {
                CampsiteShopCarouselVo campsiteShopCarouselVo = new CampsiteShopCarouselVo();
                BeanUtils.copyProperties(campsiteShopCarouselDetailDTO, campsiteShopCarouselVo);
                campsiteShopCarouselVos.add(campsiteShopCarouselVo);
            });
        }
        campsiteShopAdminVO.setCarouse(campsiteShopCarouselVos);
        //根据营地id查询营地类型
        List<CampsiteShopTagDTO> shopTagDTOS = campsiteShopTagBiz.findByCampsiteShopId(id);
        List<CampsiteTagListVo> shopTagVos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(shopTagDTOS)) {
            shopTagDTOS.forEach(campsiteShopTagDTO -> {
                CampsiteTagListVo campsiteTagListVo = new CampsiteTagListVo();
                BeanUtils.copyProperties(campsiteShopTagDTO, campsiteTagListVo);
                shopTagVos.add(campsiteTagListVo);
            });
            campsiteShopAdminVO.setCampsiteTagListVos(shopTagVos);
        }
        campsiteShopAdminVO.setCarouse(campsiteShopAdminVO.getCarouse()==null?new ArrayList<CampsiteShopCarouselVo>():campsiteShopAdminVO.getCarouse());
        campsiteShopAdminVO.setCampsiteTagListVos(campsiteShopAdminVO.getCampsiteTagListVos()==null?new ArrayList<CampsiteTagListVo>():campsiteShopAdminVO.getCampsiteTagListVos());
        return campsiteShopAdminVO;
    }
    /**
     * 逻辑删除
     * @param id
     * @return
     */
    public int updateCampsiteSatus(int id) {
        return mapper.updateCampsiteStatusById(id,1);
    }

    /**
     * 上下架
     * @param id
     * @param status
     * @return
     */
    public int updateCampsiteSaleStatus(Integer id, Integer status) {
        return mapper.updateCampsiteSaleStatusById(id,status);
    }

    /**
     * 检验营地名称是否存在
     * @param id
     * @param name
     * @return
     */
    public Boolean chekcCampsiteNameExist(Integer id, String name) {
          int  count = mapper.checkNameExist(id,name);
          if (count == 0) {
              return false;
          }
        return true;
    }

    /**
     * 处理开始时间
     * @param time
     * @return
     */
    private long processStartTime(Long time){
       return LocalDateTime.ofInstant(new Date(time).toInstant(), ZoneOffset.ofHours(+8))
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0)
                .toInstant(ZoneOffset.ofHours(+8))
                .toEpochMilli();
    }

    /**
     * 处理结束时间
     * @param time
     * @return
     */
    private long processEndTime(Long time){
      return   LocalDateTime.ofInstant(new Date(time).toInstant(), ZoneOffset.ofHours(+8))
              .withHour(23)
              .withMinute(59)
              .withSecond(59)
              .withNano(999)
              .toInstant(ZoneOffset.ofHours(+8))
              .toEpochMilli();
    }
    /**
     * 根据经纬度，计算两点间的距离
     *
     * @param longitude1 第一个点的经度
     * @param latitude1  第一个点的纬度
     * @param longitude2 第二个点的经度
     * @param latitude2  第二个点的纬度
     * @return 返回距离 单位千米
     */
    private static double getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        // 纬度
        double lat1 = Math.toRadians(latitude1);
        double lat2 = Math.toRadians(latitude2);
        // 经度
        double lng1 = Math.toRadians(longitude1);
        double lng2 = Math.toRadians(longitude2);
        // 纬度之差
        double a = lat1 - lat2;
        // 经度之差
        double b = lng1 - lng2;
        // 计算两点距离的公式
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
        // 弧长乘地球半径, 返回单位: 千米
        s =  s * EARTH_RADIUS;
        return s;
    }



}