package com.jsowell.pile.service.impl;

import cn.hutool.core.util.PageUtil;
import com.google.common.collect.Lists;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.entity.SysDept;
import com.jsowell.common.core.domain.entity.SysUser;
import com.jsowell.common.core.domain.vo.AuthorizedDeptVO;
import com.jsowell.common.core.page.PageResponse;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.DistanceUtils;
import com.jsowell.common.util.SecurityUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.ip.AddressUtils;
import com.jsowell.pile.domain.PileBasicInfo;
import com.jsowell.pile.domain.PileStationInfo;
import com.jsowell.pile.domain.ThirdPartyPlatformConfig;
import com.jsowell.pile.domain.ThirdpartyParkingConfig;
import com.jsowell.pile.dto.FastCreateStationDTO;
import com.jsowell.pile.dto.QueryStationDTO;
import com.jsowell.pile.dto.lutongyunting.BindParkingPlatformDTO;
import com.jsowell.pile.mapper.PileStationInfoMapper;
import com.jsowell.pile.service.*;
import com.jsowell.pile.vo.base.MerchantInfoVO;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.base.StationInfoVO;
import com.jsowell.pile.vo.uniapp.CurrentTimePriceDetails;
import com.jsowell.pile.vo.web.PileStationVO;
import com.jsowell.system.service.SysDeptService;
import com.jsowell.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 充电站信息Service业务层处理
 *
 * @author jsowell
 * @date 2022-08-30
 */
@Slf4j
@Service
public class PileStationInfoServiceImpl implements IPileStationInfoService {
	@Autowired
	private PileStationInfoMapper pileStationInfoMapper;

	@Autowired
	private IPileConnectorInfoService pileConnectorInfoService;

	@Autowired
	private IPileBillingTemplateService pileBillingTemplateService;

	@Autowired
	private IPileMerchantInfoService pileMerchantInfoService;

	@Autowired
	private SysDeptService sysDeptService;

	@Autowired
	private IPileBasicInfoService pileBasicInfoService;

	@Autowired
	private RedisCache redisCache;

	@Autowired
	private SysUserService userService;

	@Autowired
	private IThirdPartyParkingConfigService parkingConfigService;

	@Autowired
	private IOrderBasicInfoService orderBasicInfoService;


	/**
	 * 查询充电站信息
	 *
	 * @param id 充电站信息主键
	 * @return 充电站信息
	 */
	@Override
	public PileStationInfo selectPileStationInfoById(Long id) {
		// 加缓存
		String redisKey = CacheConstants.SELECT_PILE_STATION_INFO_BY_ID + id;
		PileStationInfo pileStationInfo = redisCache.getCacheObject(redisKey);
		if (pileStationInfo == null) {
			// 查数据库
			pileStationInfo = pileStationInfoMapper.selectPileStationInfoById(id);
			redisCache.setCacheObject(redisKey, pileStationInfo, 15, TimeUnit.MINUTES);
		}
		return pileStationInfo;
	}

	/**
	 * 查询站点基本资料
	 * 加缓存
	 * @param stationId
	 * @return
	 */
	@Override
	public PileStationVO getStationInfo(String stationId) {
		PileStationVO vo = new PileStationVO();
		PileStationInfo pileStationInfo = selectPileStationInfoById(Long.parseLong(stationId));
		// 查计费模板
		CurrentTimePriceDetails currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetails(stationId);
		if (currentTimePriceDetails != null) {
			String electricityPrice = currentTimePriceDetails.getElectricityPrice();
			electricityPrice = StringUtils.isBlank(electricityPrice) ? "0" : electricityPrice;

			String servicePrice = currentTimePriceDetails.getServicePrice();
			servicePrice = StringUtils.isBlank(servicePrice) ? "0" : servicePrice;

			vo.setElectricityPrice(new BigDecimal(electricityPrice));
			vo.setServicePrice(new BigDecimal(servicePrice));

			if (StringUtils.isNotBlank(String.valueOf(currentTimePriceDetails.getFreeTime()))) {
				vo.setFreeTime(currentTimePriceDetails.getFreeTime());
			}
			if (StringUtils.isNotBlank(String.valueOf(currentTimePriceDetails.getOccupyFee()))) {
				vo.setOccupyFee(currentTimePriceDetails.getOccupyFee());
			}
		}

		if (pileStationInfo != null) {
			vo.setMerchantId(pileStationInfo.getMerchantId().toString());
			vo.setStationName(pileStationInfo.getStationName());
			vo.setId(pileStationInfo.getId().toString());
			vo.setAreaCode(pileStationInfo.getAreaCode());
			vo.setAddress(pileStationInfo.getAddress());
			if (StringUtils.isNotBlank(pileStationInfo.getParkingId())) {
				vo.setParkingId(pileStationInfo.getParkingId());
			}
			if (StringUtils.isNotBlank(pileStationInfo.getQrcodePrefix())) {
				vo.setQrcodePrefix(pileStationInfo.getQrcodePrefix());
			}
			if (StringUtils.isNotBlank(pileStationInfo.getParkingNumber())) {
				vo.setParkingNumber(pileStationInfo.getParkingNumber());
			}
			if (StringUtils.isNotBlank(pileStationInfo.getParkFeeDescribe())) {
				vo.setParkFeeDescribe(pileStationInfo.getParkFeeDescribe());
			}

			vo.setMerchantAdminName(pileStationInfo.getStationAdminName());
			vo.setStationStatus(Integer.parseInt(pileStationInfo.getStationStatus()));
			vo.setStationType(pileStationInfo.getStationType());
			vo.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, pileStationInfo.getCreateTime()));
			vo.setStationTel(pileStationInfo.getStationTel());
			vo.setMatchCars(pileStationInfo.getMatchCars());
			if (StringUtils.isNotBlank(pileStationInfo.getMatchCars())) {
				vo.setSelectMatchCars(Lists.newArrayList(pileStationInfo.getMatchCars().split(",")));
			}
			vo.setStationLat(pileStationInfo.getStationLat());
			vo.setStationLng(pileStationInfo.getStationLng());
			vo.setCountryCode(pileStationInfo.getCountryCode());
			vo.setConstruction(pileStationInfo.getConstruction());
			vo.setBusinessHours(pileStationInfo.getBusinessHours());
			// vo.setOrganizationCode(pileStationInfo.getor);
			vo.setPublicFlag(pileStationInfo.getPublicFlag());
			vo.setOpenFlag(pileStationInfo.getOpenFlag());
			vo.setOpenAllDay(pileStationInfo.getOpenAllDay());
			vo.setDeptId(pileStationInfo.getDeptId());
			if (StringUtils.isNotBlank(pileStationInfo.getPictures())) {
				vo.setPictures(pileStationInfo.getPictures());
				vo.setPictureList(Lists.newArrayList(pileStationInfo.getPictures().split(",")));
			}
		}
		return vo;
	}

	@Override
	public PileStationVO getStationInfoByPileSn(String pileSn) {
		// 通过pileSn查询充电桩（缓存方法）
		PileInfoVO pileInfoVO = pileBasicInfoService.selectPileInfoBySn(pileSn);
		if (pileInfoVO == null) {
			return null;
		}
		// 通过stationId查询充电站信息（缓存方法）
		PileStationVO stationInfo = getStationInfo(pileInfoVO.getStationId());
		return stationInfo;
	}

	@Override
	public List<PileStationInfo> getStationInfosByThirdParty() {
		// PageUtils.startPage(pageNum, pageSize);
		return pileStationInfoMapper.getStationInfoForLianLian();
	}

	@Override
	public List<PileStationInfo> getStationInfosByAmap() {
		return pileStationInfoMapper.getStationInfoForAmap();
	}

	@Override
	public List<String> queryByStationDeptIds(List<String> stationIds) {
		return pileStationInfoMapper.queryByStationDeptIds(stationIds);
	}

	/**
	 * 查询充电站信息列表
	 *
	 * @param pileStationInfo 充电站信息
	 * @return 充电站信息
	 */
	@Override
	public List<PileStationInfo> selectPileStationInfoList(PileStationInfo pileStationInfo) {
		return pileStationInfoMapper.selectPileStationInfoList(pileStationInfo);
	}

	/**
	 * 通过运营商id查询站点信息
	 *
	 * @param merchantId 运营商id
	 * @return 站点信息列表
	 */
    @Override
    public List<PileStationInfo> selectStationListByMerchantId(Long merchantId) {
        return pileStationInfoMapper.selectStationListByMerchantId(merchantId);
    }

    /**
	 * 新增充电站信息
	 *
	 * @param pileStationInfo 充电站信息
	 * @return 结果
	 */
	@Override

	public int insertPileStationInfo(PileStationInfo pileStationInfo) {
		pileStationInfo.setCreateTime(DateUtils.getNowDate());
		pileStationInfo.setCreateBy(SecurityUtils.getUsername());
		return pileStationInfoMapper.insertPileStationInfo(pileStationInfo);
	}

	/**
	 * 快速建站
	 * @param dto
	 * @return
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public int fastCreateStation(FastCreateStationDTO dto) {
		MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(dto.getMerchantId());
		if (merchantInfo == null) {
			return 0;
		}

		// 创建站点对应部门
		SysDept dept = sysDeptService.createStationDept(Long.valueOf(merchantInfo.getDeptId()), dto.getStationName(), dto.getStationAdminName(), dto.getStationTel());

		PileStationInfo pileStationInfo = new PileStationInfo();
		pileStationInfo.setDeptId(String.valueOf(dept.getDeptId()));
		// 前端输入信息
		pileStationInfo.setMerchantId(Long.valueOf(dto.getMerchantId()));
		pileStationInfo.setStationName(StringUtils.trim(dto.getStationName()));
		pileStationInfo.setAddress(StringUtils.trim(dto.getAddress()));
		pileStationInfo.setAreaCode(StringUtils.trim(dto.getAreaCode()));
		pileStationInfo.setCapacity(BigDecimal.ZERO); // 容量
		pileStationInfo.setStationTel(StringUtils.trim(dto.getStationTel()));
		pileStationInfo.setStationAdminName(StringUtils.trim(dto.getStationAdminName()));
		// 获取经纬度
		Map<String, String> longitudeAndLatitude = AddressUtils.getLongitudeAndLatitude(dto.getAreaCode(), dto.getAddress());
		if (longitudeAndLatitude != null) {
			pileStationInfo.setStationLng(longitudeAndLatitude.get("lng"));
			pileStationInfo.setStationLat(longitudeAndLatitude.get("lat"));
		}
		pileStationInfo.setCreateBy(SecurityUtils.getUsername());
		int i = pileStationInfoMapper.insertPileStationInfo(pileStationInfo);
		return i;
	}

	/**
	 * 修改充电站信息
	 *
	 * @param pileStationInfo 充电站信息
	 * @return 结果
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public int updatePileStationInfo(PileStationInfo pileStationInfo) {
		// 清缓存
		String redisKey = CacheConstants.SELECT_PILE_STATION_INFO_BY_ID + pileStationInfo.getId();
		redisCache.deleteObject(redisKey);

		String templateRedisKey = CacheConstants.QUERY_STATION_BILLING_TEMPLATE_LIST + pileStationInfo.getId();
		redisCache.deleteObject(templateRedisKey);

		// 先查询一下当前数据库的充电站数据
		PileStationInfo queryStationInfo = selectPileStationInfoById(pileStationInfo.getId());
		String oldMerchantId = String.valueOf(queryStationInfo.getMerchantId());
		String newMerchantId = String.valueOf(pileStationInfo.getMerchantId());
		// 对比一下运营商有没有变化
		if (!StringUtils.equals(oldMerchantId, newMerchantId)) {
			// 新旧运营商不一致，执行站点更换运营商逻辑
			stationUpdateMerchant(pileStationInfo, newMerchantId);
		} else {
			// 查询部门
			SysDept sysDept = sysDeptService.selectDeptById(Long.parseLong(pileStationInfo.getDeptId()));
			// 同步组织中的名称，联系人，电话
			if (sysDept != null) {
				sysDept.setDeptName(pileStationInfo.getStationName());
				sysDept.setLeader(pileStationInfo.getStationAdminName());
				sysDept.setPhone(pileStationInfo.getStationTel());
				sysDept.setUpdateTime(DateUtils.getNowDate());
				sysDeptService.updateDept(sysDept);
			}
		}

		pileStationInfo.setUpdateBy(SecurityUtils.getUsername());
		pileStationInfo.setUpdateTime(DateUtils.getNowDate());
		int i = pileStationInfoMapper.updatePileStationInfo(pileStationInfo);

		// 再次清缓存
		redisCache.deleteObject(redisKey);
		return i;
	}

	/**
	 * 充电站更换运营商逻辑
	 */
	private void stationUpdateMerchant(PileStationInfo pileStationInfo, String newMerchantId) {
		/*
		修改充电桩所属运营商
		 */
		List<PileBasicInfo> pileInfoList = pileBasicInfoService.getPileListByStationId(String.valueOf(pileStationInfo.getId()));
		if (CollectionUtils.isNotEmpty(pileInfoList)) {
			List<Long> pileIdList = pileInfoList.stream().map(PileBasicInfo::getId).collect(Collectors.toList());
			// 修改桩基本信息
			pileBasicInfoService.updatePileMerchantBatch(pileIdList, newMerchantId);
		}

		/*
		 修改组织部门
		 */
		MerchantInfoVO merchantInfo = pileMerchantInfoService.getMerchantInfo(newMerchantId);
		if (merchantInfo != null) {
			// 创建一个新的站点对应部门
			SysDept dept = sysDeptService.createStationDept(Long.valueOf(merchantInfo.getDeptId()),
					pileStationInfo.getStationName(), pileStationInfo.getStationAdminName(), pileStationInfo.getStationTel());
			Long newDeptId = dept.getDeptId();

			// 修改账号归属部门
			SysUser user = new SysUser();
			user.setDeptId(Long.valueOf(pileStationInfo.getDeptId()));
			List<SysUser> userList = userService.selectUserList(user);
			if (CollectionUtils.isNotEmpty(userList)) {
				for (SysUser sysUser : userList) {
					sysUser.setDeptId(newDeptId);
					userService.updateUser(sysUser);
				}
			}

			// 逻辑删除老的部门
			sysDeptService.deleteDeptById(Long.parseLong(pileStationInfo.getDeptId()));

			// 设置新部门id
			pileStationInfo.setDeptId(String.valueOf(newDeptId));
		}

		/**
		 * 修改订单中的 merchantId
		 */
		orderBasicInfoService.updateMerchantByStationId(pileStationInfo.getId(), newMerchantId);

	}

	/**
	 * 批量删除充电站信息
	 *
	 * @param ids 需要删除的充电站信息主键
	 * @return 结果
	 */
	@Override
	public int deletePileStationInfoByIds(Long[] ids) {
		return pileStationInfoMapper.deletePileStationInfoByIds(ids);
	}

	/**
	 * 充电站列表信息
	 * @param dto 前台参数
	 * @return 充电站对象集合
	 */
	@Override
	// @DataScope(deptAlias = "t3")
	public List<PileStationVO> queryStationInfos(QueryStationDTO dto) {
		AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap();
		if (authorizedMap == null) {
			// 为空表示没有权限，返回空数组
			return Lists.newArrayList();
		}
		dto.setStationDeptIds(authorizedMap.getStationDeptIds());
		dto.setMerchantDeptIds(authorizedMap.getMerchantDeptIds());
		List<PileStationVO> list = pileStationInfoMapper.queryStationInfos(dto);
		return list;
	}

	/**
	 * uniApp查询充电站信息并通过经纬度排序
	 *
	 * @param dto 前台参数
	 * @return 充电站对象集合
	 */
	@Override
	public PageResponse uniAppQueryStationInfoList(QueryStationDTO dto) {
		long pageNum = dto.getPageNum() == 0 ? 1L : dto.getPageNum();
		long pageSize = dto.getPageSize() == 0 ? 10L : dto.getPageSize();

		// 小程序站点列表页只展示对外开放的站点
		dto.setPublicFlag(Constants.ONE);
		// 根据前台参数分页
		List<PileStationVO> list = pileStationInfoMapper.queryStationInfos(dto);

		List<StationInfoVO> stationVOList = Lists.newArrayList();
		StationInfoVO stationVO = null;
		String stationLng = dto.getStationLng();
		String stationLat = dto.getStationLat();
		double distance = 0d;
		for (PileStationVO pileStationVO : list) {
			stationVO = new StationInfoVO();
			if (StringUtils.isNotEmpty(stationLng) && StringUtils.isNotEmpty(stationLat)) {
				try{
					// 计算当前经纬度和站点之间的距离
					distance = DistanceUtils.getDistance(Double.parseDouble(stationLng), Double.parseDouble(stationLat),
							Double.parseDouble(pileStationVO.getStationLng()), Double.parseDouble(pileStationVO.getStationLat()));
					// 保留两位小数
					stationVO.setDistance(String.format("%.2f", distance));
				}catch (Exception e){
					stationVO.setDistance("0.00");
				}

			}
			stationVO.setStationId(pileStationVO.getId());
			stationVO.setStationName(pileStationVO.getStationName());
			stationVO.setStationAddress(pileStationVO.getAddress());
			stationVO.setStationLat(pileStationVO.getStationLat());
			stationVO.setStationLng(pileStationVO.getStationLng());
			if (StringUtils.isNotBlank(pileStationVO.getParkFeeDescribe())) {
				stationVO.setParkFeeDescribe(pileStationVO.getParkFeeDescribe());
			}

			// 站点图片
			if (StringUtils.isNotBlank(pileStationVO.getPictures())) {
				stationVO.setStationImgList(Lists.newArrayList(pileStationVO.getPictures().split(",")));
			}

			Map<String, Integer> map = pileConnectorInfoService.getPileTypeNum(Long.parseLong(pileStationVO.getId()));

			Integer fastFree = map.get("fastFree");
			Integer slowFree = map.get("slowFree");

			stationVO.setFastTotal(map.get("fastTotal"));
			stationVO.setFastFree(fastFree);
			stationVO.setSlowTotal(map.get("slowTotal"));
			stationVO.setSlowFree(map.get("slowFree"));
			stationVO.setTotalFree(fastFree + slowFree);

			// 查询当前时段电费
			CurrentTimePriceDetails currentTimePriceDetails = pileBillingTemplateService.getCurrentTimePriceDetails(stationVO.getStationId());
			if (currentTimePriceDetails != null) {
				stationVO.setElectricityPrice(currentTimePriceDetails.getElectricityPrice());
				stationVO.setServicePrice(currentTimePriceDetails.getServicePrice());
				stationVO.setTotalPrice(currentTimePriceDetails.getTotalPrice());
				stationVO.setFreeTime(currentTimePriceDetails.getFreeTime());
				stationVO.setOccupyFee(currentTimePriceDetails.getOccupyFee());
			}
			stationVOList.add(stationVO);
		}

		if (distance != 0.00) {
			// 对集合按照距离排序，距离小的在前
			stationVOList.sort((o1, o2) -> {
				Double a = Double.valueOf(o1.getDistance());
				Double b = Double.valueOf(o2.getDistance());
				return a.compareTo(b);
			});
		}
		List<StationInfoVO> collect = stationVOList.stream()
				.skip((pageNum - 1) * pageSize)
				.limit(pageSize)
				.collect(Collectors.toList());

		int total = stationVOList.size();
		int pages = PageUtil.totalPage(total, dto.getPageSize());
		// 返回结果集
		return PageResponse.builder()
				.pageNum(Integer.parseInt(String.valueOf(pageNum)))
				.pageSize(Integer.parseInt(String.valueOf(pageSize)))
				.list(collect)
				.pages(pages)
				.total(total)
				.build();
	}

	/**
	 * 根据站点id查询运营商配置的汇付会员id
	 * @param stationId
	 * @return
	 */
	@Override
	public String selectAdapayMemberId(String stationId) {
		return null;
	}

	@Override
	public int updateAmapFlag(String stationId, String amapFlag) {
		return pileStationInfoMapper.updateAmapFlag(stationId, amapFlag);
	}

	/**
	 * 通过站点部门id查询站点id
	 * @param deptId
	 * @return
	 */
    @Override
    public List<String> getIdsByDeptId(String deptId) {
        return pileStationInfoMapper.getIdsByDeptId(deptId);
    }

	/**
	 * 绑定停车系统平台
	 * @param dto
	 */
    @Override
    public int bindParkingPlatform(BindParkingPlatformDTO dto) {
		String parkingId = dto.getParkingId();
		String stationId = dto.getStationId();
		// 先根据停车系统平台查询一下是否有数据
		ThirdpartyParkingConfig basicInfo = parkingConfigService.selectByPrimaryKey(Integer.parseInt(parkingId));
		if (basicInfo == null) {
			throw new BusinessException(ReturnCodeEnum.CODE_QUERY_PARKING_INFO_IS_NULL);
		}
		// 先删除缓存
		String redisKey = CacheConstants.SELECT_PILE_STATION_INFO_BY_ID + stationId;
		redisCache.deleteObject(redisKey);
		// 再将站点信息表中绑定上parkingId
        return pileStationInfoMapper.updateParkingPlatform(parkingId, stationId);
    }

	/**
	 * 查询充电站下拉列表
	 * @param dto
	 * @return
	 */
	@Override
	public List<PileStationVO> getStationSelectList(QueryStationDTO dto) {
		AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap();
		if (authorizedMap == null) {
			// 为空表示没有权限，返回空数组
			return Lists.newArrayList();
		}
		dto.setStationDeptIds(authorizedMap.getStationDeptIds());
		dto.setMerchantDeptIds(authorizedMap.getMerchantDeptIds());

		return pileStationInfoMapper.getStationSelectList(dto);
	}

}

