package com.cool.store.service.impl;

import com.cool.store.dao.*;
import com.cool.store.dto.FranchiseReportDTO;
import com.cool.store.entity.BigRegionDO;
import com.cool.store.entity.FranchiseFeeDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.enums.FranchiseBrandEnum;
import com.cool.store.enums.JoinModeEnum;
import com.cool.store.enums.StoreTypeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.mapper.FranchiseFeeMapper;
import com.cool.store.request.FranchiseReportRequest;
import com.cool.store.response.FranchiseReportResponse;
import com.cool.store.response.ShopReportResponse;
import com.cool.store.service.FranchiseReportService;
import com.cool.store.utils.poi.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import groovy.util.logging.Log4j;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: WangShuo
 * @Date: 2025/05/13/15:22
 * @Version 1.0
 * @注释:
 */
@Slf4j
@Service
public class FranchiseReportServiceImpl implements FranchiseReportService {
    @Resource
    private EnterpriseUserDAO enterpriseUserDAO;
    @Resource
    private BigRegionDAO bigRegionDAO;
    @Resource
    private ShopInfoDAO shopInfoDAO;
    @Resource
    private FranchiseFeeMapper franchiseFeeMapper;
    @Resource
    private RegionDao regionDao;

    @Override
    public List<FranchiseReportResponse> zxjpOpenShopReport(FranchiseReportRequest request) {
        if (StringUtils.isBlank(request.getBuildStartTime()) || StringUtils.isBlank(request.getBuildEndTime())) {
            throw new ServiceException(ErrorCodeEnum.TIME_NULL_FALSE);
        }
        //集团查大区
        List<Long> regionIdByGroupName = bigRegionDAO.getRegionIdByGroupName(request.getJoinGroupName());
        if (CollectionUtils.isNotEmpty(regionIdByGroupName)) {
            if (CollectionUtils.isEmpty(request.getRegionIds())) {
                request.setRegionIds(regionIdByGroupName);
            } else {
                request.getRegionIds().retainAll(regionIdByGroupName);
                if (CollectionUtils.isEmpty(request.getRegionIds())) {
                    throw new ServiceException(ErrorCodeEnum.REGION_INTERSECTION_IS_NULL);
                }
            }
        }
        List<FranchiseReportDTO> shopFranchiseReportList = shopInfoDAO.getShopFranchiseReportList(request);
        if (CollectionUtils.isEmpty(shopFranchiseReportList)) {
            log.info("查询门店数据为空");
            return null;
        }
        List<Long> shopIds = shopFranchiseReportList.stream().map(FranchiseReportDTO::getShopId).collect(Collectors.toList());
        Set<Long> regionSet = shopFranchiseReportList.stream().map(FranchiseReportDTO::getRegionId).collect(Collectors.toSet());
        //加盟费账单
        List<FranchiseFeeDO> franchiseFeeList = franchiseFeeMapper.getFranchiseFeeByShopIds(shopIds);
        Map<Long, FranchiseFeeDO> franchiseFeeMap = franchiseFeeList.stream().collect(Collectors.toMap(FranchiseFeeDO::getShopId, franchiseFeeDO -> franchiseFeeDO));
        List<BigRegionDO> bigRegionDOList = bigRegionDAO.getByRegionIdList(new ArrayList<>(regionSet));
        Map<Long, BigRegionDO> bigRegionDOMap = bigRegionDOList.stream().collect(Collectors.toMap(BigRegionDO::getRegionId, bigRegionDO -> bigRegionDO));
        Map<Long, FranchiseReportResponse> responseByRegionIdMap = new HashMap<>();
        Map<String, FranchiseReportResponse> responseByJoinGroupNameMap = new HashMap<>();
        for (FranchiseReportDTO shopFranchiseReportDTO : shopFranchiseReportList) {
            BigRegionDO bigRegionDO = bigRegionDOMap.get(shopFranchiseReportDTO.getRegionId());
            if (bigRegionDO == null) {
                continue;
            }
            FranchiseReportResponse response = new FranchiseReportResponse();
            //查集团维度
            if (CollectionUtils.isEmpty(request.getJoinGroupName()) && CollectionUtils.isEmpty(request.getRegionIds())) {
                response = responseByJoinGroupNameMap.getOrDefault(bigRegionDO.getGroupName(), new FranchiseReportResponse());
                response.setJoinGroupName(bigRegionDO.getGroupName());
                if (CollectionUtils.isEmpty(response.getRegionIds())) {
                    response.setRegionIds(new ArrayList<>());
                }
                response.getRegionIds().add(shopFranchiseReportDTO.getRegionId());
            } else {
                //查大区维度
                response = responseByRegionIdMap.getOrDefault(shopFranchiseReportDTO.getRegionId(), new FranchiseReportResponse());
            }

            if (CollectionUtils.isNotEmpty(request.getJoinGroupName()) || CollectionUtils.isNotEmpty(request.getRegionIds())) {
                response.setRegionId(shopFranchiseReportDTO.getRegionId());
                response.setRegionName(bigRegionDO.getRegionName());
                String groupName = bigRegionDO.getGroupName();
                if (StringUtils.isBlank(groupName)) {
                    continue;
                }
                response.setJoinGroupName(groupName);
            }
            if (StoreTypeEnum.NO_SHOW_STORE.getCode().equals(shopFranchiseReportDTO.getStoreType())) {
                response.setNoShowStoreNum(response.getNoShowStoreNum() + 1);
            } else if (StoreTypeEnum.ORDINARY_STORE.getCode().equals(shopFranchiseReportDTO.getStoreType())) {
                response.setNormalStoreNum(response.getNormalStoreNum() + 1);
            } else if (StoreTypeEnum.RESTAURANT_STORE.getCode().equals(shopFranchiseReportDTO.getStoreType())) {
                response.setRestaurantStoreNum(response.getRestaurantStoreNum() + 1);
            }
            response.setStoreNum(response.getStoreNum() + 1);
            FranchiseFeeDO franchiseFeeDO = franchiseFeeMap.get(shopFranchiseReportDTO.getShopId());
            if (franchiseFeeDO != null) {
                response.setFranchiseFeeTotal(response.getFranchiseFeeTotal().add(new BigDecimal(franchiseFeeDO.getYearFranchiseFee())));
                response.setLoanMarginTotal(response.getLoanMarginTotal().add(new BigDecimal(franchiseFeeDO.getLoanMargin())));
                response.setFirstYearManagementFeeTotal(response.getFirstYearManagementFeeTotal().add(new BigDecimal(franchiseFeeDO.getFirstYearManageFee())));
                response.setFirstYearBrandingFeeTotal(response.getFirstYearBrandingFeeTotal().add(new BigDecimal(franchiseFeeDO.getFirstYearFee())));
                response.setPerformanceBondTotal(response.getPerformanceBondTotal().add(new BigDecimal(franchiseFeeDO.getPerformanceBond())));
                response.setManagementBrandingDesignFeeTotal(response.getManagementBrandingDesignFeeTotal()
                        .add(new BigDecimal(franchiseFeeDO.getFirstYearManageFee()))
                        .add(new BigDecimal(franchiseFeeDO.getFirstYearFee()))
                        .add(new BigDecimal(franchiseFeeDO.getPerformanceBond())));
            }
            if (CollectionUtils.isEmpty(request.getJoinGroupName()) && CollectionUtils.isEmpty(request.getRegionIds())) {
                responseByJoinGroupNameMap.put(bigRegionDO.getGroupName(), response);
            } else {
                responseByRegionIdMap.put(shopFranchiseReportDTO.getRegionId(), response);
            }
        }
        FranchiseReportRequest yesterdayRequest = new FranchiseReportRequest();
        yesterdayRequest.setRegionIds(request.getRegionIds());
        yesterdayRequest.setStoreTypes(request.getStoreTypes());
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //昨日 00:00:00
        LocalDateTime yesterdayStartDate = now.minusDays(1).atStartOfDay();
        String yesterdayStartTime = yesterdayStartDate.format(formatter);
        //昨日 23:59:59
        LocalDateTime yesterdayEndDate = now.minusDays(1).atTime(23, 59, 59);
        String yesterdayEndTime = yesterdayEndDate.format(formatter);
        yesterdayRequest.setBuildStartTime(yesterdayStartTime);
        yesterdayRequest.setBuildEndTime(yesterdayEndTime);
        List<FranchiseReportDTO> yesterdayShopFranchiseReportList = shopInfoDAO.getShopFranchiseReportList(yesterdayRequest);
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Map<Long, List<FranchiseReportDTO>> yesterdayMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(yesterdayShopFranchiseReportList)) {
            yesterdayMap = yesterdayShopFranchiseReportList.stream().collect(Collectors.groupingBy(FranchiseReportDTO::getRegionId));
        }
        //查集团维度
        if (CollectionUtils.isEmpty(request.getJoinGroupName()) && CollectionUtils.isEmpty(request.getRegionIds())) {
            for (FranchiseReportResponse responseByJoinGroupName : responseByJoinGroupNameMap.values()) {
                Set<Long> regionIds = new HashSet<>(responseByJoinGroupName.getRegionIds());
                for (Long regionId : regionIds) {
                    BigRegionDO bigRegionDO = bigRegionDOMap.get(regionId);
                    List<FranchiseReportDTO> yesterdayList = yesterdayMap.getOrDefault(bigRegionDO.getRegionId(), new ArrayList<>());
                    responseByJoinGroupName.setYesterdayDate(yesterdayStartDate.format(formatter1));
                    responseByJoinGroupName.setYesterdayStoreNum(responseByJoinGroupName.getYesterdayStoreNum() + (CollectionUtils.isEmpty(yesterdayList) ? 0 : yesterdayList.size()));
                }
            }
        } else {
            //大区维度
            for (Long regionId : responseByRegionIdMap.keySet()) {
                FranchiseReportResponse response = responseByRegionIdMap.get(regionId);
                if (Objects.isNull(response)) {
                    continue;
                }
                List<FranchiseReportDTO> yesterdayList = yesterdayMap.get(regionId);
                response.setYesterdayDate(yesterdayStartDate.format(formatter1));
                response.setYesterdayStoreNum(CollectionUtils.isEmpty(yesterdayList) ? 0 : yesterdayList.size());
                responseByRegionIdMap.put(regionId, response);
            }
        }


        List<FranchiseReportResponse> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(request.getJoinGroupName()) && CollectionUtils.isEmpty(request.getRegionIds())) {
            list.addAll(responseByJoinGroupNameMap.values());
        } else {
            list.addAll(responseByRegionIdMap.values());
        }
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return Collections.emptyList();
        }
        sortByName(list);
        return list;
    }

    @Override
    public PageInfo<ShopReportResponse> zxjpOpenShopReportPage(FranchiseReportRequest request) {
        if (StringUtils.isBlank(request.getBuildStartTime()) || StringUtils.isBlank(request.getBuildEndTime())) {
            throw new ServiceException(ErrorCodeEnum.TIME_NULL_FALSE);
        }
        //集团查大区
        List<Long> regionIdByGroupName = bigRegionDAO.getRegionIdByGroupName(request.getJoinGroupName());
        if (CollectionUtils.isNotEmpty(regionIdByGroupName)) {
            if (CollectionUtils.isEmpty(request.getRegionIds())) {
                request.setRegionIds(regionIdByGroupName);
            } else {
                request.getRegionIds().retainAll(regionIdByGroupName);
                if (CollectionUtils.isEmpty(request.getRegionIds())) {
                    throw new ServiceException(ErrorCodeEnum.REGION_INTERSECTION_IS_NULL);
                }
            }
        }
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<FranchiseReportDTO> shopFranchiseReportList = shopInfoDAO.getShopFranchiseReportList(request);
        if (CollectionUtils.isEmpty(shopFranchiseReportList)) {
            log.info("查询门店数据为空");
            return null;
        }
        PageInfo franchiseReportDTOPageInfo = new PageInfo<>(shopFranchiseReportList);
        List<Long> shopIds = shopFranchiseReportList.stream().map(FranchiseReportDTO::getShopId).collect(Collectors.toList());
        Set<Long> regionSet = shopFranchiseReportList.stream().map(FranchiseReportDTO::getRegionId).collect(Collectors.toSet());
        Set<String> investmentManagerUsers = shopFranchiseReportList.stream().map(FranchiseReportDTO::getInvestmentManager).collect(Collectors.toSet());
        Map<String, String> userNameMap = enterpriseUserDAO.getUserNameMap(new ArrayList<>(investmentManagerUsers));
        //加盟费账单
        List<FranchiseFeeDO> franchiseFeeList = franchiseFeeMapper.getFranchiseFeeByShopIds(shopIds);
        Map<Long, FranchiseFeeDO> franchiseFeeMap = franchiseFeeList.stream().collect(Collectors.toMap(FranchiseFeeDO::getShopId, franchiseFeeDO -> franchiseFeeDO));
        List<BigRegionDO> bigRegionDOList = bigRegionDAO.getByRegionIdList(new ArrayList<>(regionSet));
        Map<Long, BigRegionDO> bigRegionDOMap = bigRegionDOList.stream().collect(Collectors.toMap(BigRegionDO::getRegionId, bigRegionDO -> bigRegionDO));
        Map<Long, String> regionNameMap = regionDao.getRegionNameMap(new ArrayList<>(regionSet));
        List<ShopReportResponse> list = new ArrayList<>();
        for (FranchiseReportDTO shopFranchiseReportDTO : shopFranchiseReportList) {
            BigRegionDO bigRegionDO = bigRegionDOMap.getOrDefault(shopFranchiseReportDTO.getRegionId(), new BigRegionDO());
            String regionName = regionNameMap.getOrDefault(shopFranchiseReportDTO.getRegionId(), "");
            ShopReportResponse response = new ShopReportResponse();
            response.setRegionId(shopFranchiseReportDTO.getRegionId());
            response.setRegionName(regionName);
            String groupName = bigRegionDO.getGroupName();
            if (StringUtils.isBlank(groupName)) {
                response.setJoinGroupName("-");
            } else {
                response.setJoinGroupName(groupName);
            }
            response.setBuildTime(shopFranchiseReportDTO.getActualCompleteTime());
            response.setShopCode(shopFranchiseReportDTO.getShopCode());
            response.setShopName(shopFranchiseReportDTO.getShopName());
            response.setStoreType(StoreTypeEnum.getMessage(shopFranchiseReportDTO.getStoreType()));
            response.setJoinMode(JoinModeEnum.getByCode(shopFranchiseReportDTO.getJoinMode()));
            response.setFranchiseBrand(FranchiseBrandEnum.getDescByCode(shopFranchiseReportDTO.getFranchiseBrand()));
            response.setInvestmentManagerName(userNameMap.getOrDefault(shopFranchiseReportDTO.getInvestmentManager(), ""));
            FranchiseFeeDO franchiseFeeDO = franchiseFeeMap.get(shopFranchiseReportDTO.getShopId());
            if (franchiseFeeDO != null) {
                response.setFranchiseFee(response.getFranchiseFee().add(new BigDecimal(franchiseFeeDO.getYearFranchiseFee())));
                response.setLoanMargin(response.getLoanMargin().add(new BigDecimal(franchiseFeeDO.getLoanMargin())));
                response.setFirstYearManagementFee(response.getFirstYearManagementFee().add(new BigDecimal(franchiseFeeDO.getFirstYearManageFee())));
                response.setFirstYearBrandingFee(response.getFirstYearBrandingFee().add(new BigDecimal(franchiseFeeDO.getFirstYearFee())));
                response.setPerformanceBond(response.getPerformanceBond().add(new BigDecimal(franchiseFeeDO.getPerformanceBond())));
                response.setManagementBrandingDesignFeeTotal(response.getManagementBrandingDesignFeeTotal()
                        .add(new BigDecimal(franchiseFeeDO.getFirstYearManageFee()))
                        .add(new BigDecimal(franchiseFeeDO.getFirstYearFee()))
                        .add(new BigDecimal(franchiseFeeDO.getPerformanceBond())));
                response.setTotal(response.getTotal()
                        .add(response.getManagementBrandingDesignFeeTotal())
                        .add(response.getLoanMargin())
                        .add(response.getFranchiseFee()));
            }
            list.add(response);
        }
        if (CollectionUtils.isEmpty(list)) {
            log.info("数据为空");
            return null;
        }
        franchiseReportDTOPageInfo.setList(list);
        return franchiseReportDTOPageInfo;
    }

    public static void sortByName(List<FranchiseReportResponse> list) {
        list.sort(Comparator.comparingInt(f -> extractNumberFromName(f.getJoinGroupName())));
    }

    private static int extractNumberFromName(String name) {
        try {

            if (name.contains("第一加盟集团")) {
                return 1;
            }
            if (name.contains("第二加盟集团")) {
                return 2;
            }
            if (name.contains("第三加盟集团")) {
                return 3;
            }
            if (name.contains("第四加盟集团")) {
                return 4;
            }
            if (name.contains("第五加盟集团")) {
                return 5;
            }
            if (name.contains("第六加盟集团")) {
                return 6;
            }
            if (name.contains("第七加盟集团")) {
                return 7;
            }
            if (name.contains("第八加盟集团")) {
                return 8;
            }
            return Integer.MAX_VALUE;
        } catch (Exception e) {
            return Integer.MAX_VALUE;
        }
    }
}
