package shop.alien.storeplatform.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.geo.Point;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.StoreInfoDto;
import shop.alien.entity.store.vo.StoreBusinessInfoVo;
import shop.alien.entity.store.vo.StoreMainInfoVo;
import shop.alien.entity.store.vo.StoreMenuVo;
import shop.alien.mapper.*;
import shop.alien.storeplatform.config.GaoDeMapUtil;
import shop.alien.storeplatform.service.NearMeService;
import shop.alien.storeplatform.service.StorePlatformInfoService;
import shop.alien.util.common.DistanceUtil;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional
public class StorePlatformInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo> implements StorePlatformInfoService {

    private final LifeUserOrderMapper lifeUserOrderMapper;

    private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;

    private final LifeCouponMapper lifeCouponMapper;

    private final StoreDictionaryMapper storeDictionaryMapper;

    private final StoreInfoMapper storeInfoMapper;

    private final EssentialCityCodeMapper essentialCityCodeMapper;

    private final NearMeService nearMeService;

    private final StoreBusinessInfoMapper storeBusinessInfoMapper;

    private final StoreImgMapper storeImgMapper;

    private final StoreMenuMapper storeMenuMapper;

    private final StoreLabelMapper storeLabelMapper;

    private final StoreUserMapper storeUserMapper;

    private final GaoDeMapUtil gaoDeMapUtil;

    private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;

    @Override
    public int saveOrUpdateStoreInfo(StoreInfoDto storeInfodto) {
        if (storeInfodto.getId() != null) {
            // 校验当前店铺存在未完成的订单及正在销售的商品
            verificationStoreInfoStatus(storeInfodto);

            // 1. 处理经营板块及经营种类
            Integer businessSection = storeInfodto.getBusinessSection();
            StoreDictionary businessSectionDict = null;
            List<String> businessTypeNames = new ArrayList<>();

            // 查询经营板块（非空判断，避免后续空指针）
            if (Objects.nonNull(businessSection)) {
                businessSectionDict = storeDictionaryMapper.selectOne(
                        new LambdaQueryWrapper<StoreDictionary>()
                                .eq(StoreDictionary::getDictId, businessSection)
                                .eq(StoreDictionary::getTypeName, "business_section")
                );
                // 若经营板块不存在，可根据业务抛出异常或默认处理
                if (Objects.isNull(businessSectionDict)) {
                    throw new IllegalArgumentException("经营板块不存在：" + businessSection);
                }
            }

            // 批量查询经营种类（替代循环查询，解决N+1问题）
            List<String> businessTypes = storeInfodto.getBusinessTypes();
            if (Objects.nonNull(businessSectionDict) && !CollectionUtils.isEmpty(businessTypes)) {
                // 一次查询所有符合条件的经营种类
                List<StoreDictionary> typeDicts = storeDictionaryMapper.selectList(
                        new LambdaQueryWrapper<StoreDictionary>()
                                .in(StoreDictionary::getDictId, businessTypes) // 批量匹配id
                                .eq(StoreDictionary::getParentId, businessSectionDict.getId())
                );
                // 转为Map<dictId, StoreDictionary>，方便快速获取
                Map<String, StoreDictionary> typeDictMap = typeDicts.stream()
                        .collect(Collectors.toMap(
                                dict -> dict.getDictId().toString(), // 假设dictId是字符串类型，若为数字需转换
                                Function.identity(),
                                (existing, replacement) -> existing // 处理重复id（理论上不会有）
                        ));
                // 提取经营种类名称
                for (String typeId : businessTypes) {
                    StoreDictionary dict = typeDictMap.get(typeId);
                    if (Objects.nonNull(dict)) {
                        businessTypeNames.add(dict.getDictDetail());
                    } else {
                        // 可选：记录无效的经营种类id，便于排查
                        log.warn("无效的经营种类id：" + typeId + "（所属板块：" + businessSectionDict.getDictDetail() + "）");
                    }
                }
            }

            // 2. 构建StoreInfo对象
            StoreInfo storeInfo = new StoreInfo();
            BeanUtils.copyProperties(storeInfodto, storeInfo);

            // 3. 处理经纬度
            String longitude = storeInfodto.getStorePositionLongitude();
            String latitude = storeInfodto.getStorePositionLatitude();
            if (StringUtils.isEmpty(longitude) || StringUtils.isEmpty(latitude)) {
                // 经纬度为空时，复用原数据
                StoreInfo oldStore = storeInfoMapper.selectById(storeInfodto.getId());
                if (Objects.nonNull(oldStore)) {
                    storeInfo.setStorePosition(oldStore.getStorePosition());
                }
            } else {
                // 拼接经纬度
                storeInfo.setStorePosition(longitude + "," + latitude);
            }

            // 4. 设置门店状态、经营板块及类型
            storeInfo.setStoreStatus(storeInfodto.getStoreStatus());
            // 经营板块（非空时才设置）
            if (Objects.nonNull(businessSection)) {
                storeInfo.setBusinessSection(businessSection);
            }
            // 经营板块名称（非空时才设置）
            if (Objects.nonNull(businessSectionDict)) {
                storeInfo.setBusinessSectionName(businessSectionDict.getDictDetail());
            }
            // 经营种类及名称（非空时拼接）
            if (!CollectionUtils.isEmpty(businessTypes) && !CollectionUtils.isEmpty(businessTypeNames)) {
                storeInfo.setBusinessTypes(String.join(",", businessTypes));
                storeInfo.setBusinessTypesName(String.join(",", businessTypeNames));
            }

            // 5. 处理行政区域信息（抽取为方法，减少重复） 不存在单独查的情况
            if (!Objects.isNull(storeInfo.getAdministrativeRegionProvinceAdcode())) {

                storeInfo.setAdministrativeRegionProvinceName(
                        getAreaName(storeInfo.getAdministrativeRegionProvinceAdcode())
                );
                storeInfo.setAdministrativeRegionCityName(
                        getAreaName(storeInfo.getAdministrativeRegionCityAdcode())
                );
                storeInfo.setAdministrativeRegionDistrictName(
                        getAreaName(storeInfo.getAdministrativeRegionDistrictAdcode())
                );
            }

            // 6. 执行更新
            int updateNum = storeInfoMapper.updateById(storeInfo);

            // 7. 更新地理位置信息（处理经纬度解析异常）
            if (!StringUtils.isEmpty(longitude) && !StringUtils.isEmpty(latitude)) {
                try {
                    double lon = Double.parseDouble(longitude);
                    double lat = Double.parseDouble(latitude);
                    nearMeService.inGeolocation(new Point(lon, lat), storeInfo.getId().toString(), Boolean.TRUE);
                } catch (NumberFormatException e) {
                    log.error("经纬度解析失败：longitude=" + longitude + ", latitude=" + latitude);
                    // 可选：根据业务是否抛出异常，或忽略
                    // throw new IllegalArgumentException("经纬度格式错误", e);
                }
            }
            return updateNum;
        } else {
            StoreInfo storeInfo = new StoreInfo();
            BeanUtils.copyProperties(storeInfodto, storeInfo);
            int num = storeInfoMapper.insert(storeInfo);
            return num;
        }
    }

    void verificationStoreInfoStatus(StoreInfoDto storeInfo) {
        //营业状态 0:正常营业, 1:暂停营业, 2:筹建中, 99:永久关门
        if (storeInfo.getBusinessStatus() == 99) {
            //判断店铺有未完成的订单
            List<LifeUserOrder> lifeUserOrders = lifeUserOrderMapper.selectList(new LambdaQueryWrapper<LifeUserOrder>().in(LifeUserOrder::getStatus, 0, 3).eq(LifeUserOrder::getStoreId, storeInfo.getId()).eq(LifeUserOrder::getDeleteFlag, 0));
            if (!CollectionUtils.isEmpty(lifeUserOrders)) {
                throw new RuntimeException("店铺有未完成的订单");
            }
            //判断店铺有正在售卖的商品
            List<LifeGroupBuyMain> lifeGroupBuyMainList = lifeGroupBuyMainMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getStoreId, storeInfo.getId()).eq(LifeGroupBuyMain::getStatus, 5).eq(LifeGroupBuyMain::getDeleteFlag, 0));
            List<LifeCoupon> lifeCoupons = lifeCouponMapper.selectList(new LambdaQueryWrapper<LifeCoupon>().in(LifeCoupon::getStatus, 0, 1).and(qw -> qw.gt(LifeCoupon::getStockQty, 0).or().gt(LifeCoupon::getSingleQty, 0)).eq(LifeCoupon::getStoreId, storeInfo.getId()).eq(LifeCoupon::getType, 1).eq(LifeCoupon::getDeleteFlag, 0));
            if (!CollectionUtils.isEmpty(lifeCoupons) || !CollectionUtils.isEmpty(lifeGroupBuyMainList)) {
                throw new RuntimeException("店铺有正在销售的商品");
            }
        }
    }

    // 抽取：根据区域编码查询区域名称（通用方法）
    private String getAreaName(String areaCode) {
        if (StringUtils.isEmpty(areaCode)) {
            return ""; // 或返回null，根据业务定义
        }
        EssentialCityCode cityCode = essentialCityCodeMapper.selectOne(
                new LambdaQueryWrapper<EssentialCityCode>().eq(EssentialCityCode::getAreaCode, areaCode)
        );
        return Objects.nonNull(cityCode) ? cityCode.getAreaName() : "";
    }

    @Override
    public List<StoreBusinessInfo> getStoreInfoBusinessHours(Integer id) {
        //营业时间
        List<StoreBusinessInfo> storeBusinessInfoList = storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().eq(StoreBusinessInfo::getStoreId, id));
        return storeBusinessInfoList;
    }

    /**
     * 门店详情
     *
     * @return StoreMainInfoVo
     */
    @Override
    public StoreMainInfoVo getDetail(Integer id) {

        StoreInfo storeInfo = storeInfoMapper.selectById(id);
        if(storeInfo == null){
            return null;
        }
        StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);

        //判断门店是否到期
        if (ObjectUtils.isNotEmpty(storeMainInfoVo.getExpirationTime())) {
            if (new Date().after(storeMainInfoVo.getExpirationTime())) {
                storeMainInfoVo.setExpirationFlag(0);
            }else {
                storeMainInfoVo.setExpirationFlag(1);
            }
        }else {
            storeMainInfoVo.setExpirationFlag(1);
        }

        //存入门店地址、
        storeMainInfoVo.setStoreAddress(storeInfo.getStoreAddress());
        //入口图
        LambdaQueryWrapper<StoreImg> inletsUrlQueryWrapper = new LambdaQueryWrapper<>();
        inletsUrlQueryWrapper.eq(StoreImg::getImgType, 1);
        inletsUrlQueryWrapper.eq(StoreImg::getStoreId, id);
        List<StoreImg> inletsUrlList = storeImgMapper.selectList(inletsUrlQueryWrapper);
        storeMainInfoVo.setInletsUrl(inletsUrlList.stream().sorted(Comparator.comparing(StoreImg::getImgSort)).map(StoreImg::getImgUrl).collect(Collectors.toList()));
        //相册
        LambdaQueryWrapper<StoreImg> albumUrlQueryWrapper = new LambdaQueryWrapper<>();
        albumUrlQueryWrapper.eq(StoreImg::getImgType, 2);
        albumUrlQueryWrapper.eq(StoreImg::getStoreId, id);
        List<StoreImg> albumUrlList = storeImgMapper.selectList(albumUrlQueryWrapper);
        storeMainInfoVo.setAlbumUrl(albumUrlList.stream().sorted(Comparator.comparing(StoreImg::getImgSort)).map(StoreImg::getImgUrl).collect(Collectors.toList()));
        //推荐菜
        storeMainInfoVo.setRecommendUrl(storeMenuMapper.getStoreMenuList(id, 1).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));
        //菜单
        storeMainInfoVo.setMenuUrl(storeMenuMapper.getStoreMenuList(id, 0).stream().sorted(Comparator.comparing(StoreMenuVo::getImgSort)).collect(Collectors.toList()));
        //门店标签
        storeMainInfoVo.setStoreLabel(storeLabelMapper.selectOne(new LambdaQueryWrapper<StoreLabel>().eq(StoreLabel::getStoreId, id)));
        //营业时间
        //storeMainInfoVo.setStoreBusinessInfo(storeBusinessInfoMapper.selectList(new LambdaQueryWrapper<StoreBusinessInfo>().eq(StoreBusinessInfo::getStoreId, id)));

        //营业时间（通过 getStoreInfoBusinessHours 方法获取，包含节假日信息）
        List<StoreBusinessInfoVo> storeBusinessInfoVos = this.getStoreInfoBusinessHoursNew(id);
        // 设置包含节假日信息的营业时间列表
        storeMainInfoVo.setStoreBusinessInfoVos(storeBusinessInfoVos);

        //门店头像
        LambdaQueryWrapper<StoreImg> eq = new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 10).eq(StoreImg::getStoreId, id);
        StoreImg storeImg = storeImgMapper.selectOne(eq);
        storeMainInfoVo.setHeadImgUrl(storeImg != null ? storeImg.getImgUrl() : "");
        List<StoreUser> storeUsers = storeUserMapper.selectList(new LambdaQueryWrapper<StoreUser>().eq(StoreUser::getStoreId, storeInfo.getId()));
        for (StoreUser storeUser : storeUsers) {
            storeMainInfoVo.setLogoutFlagUser(storeUser.getLogoutFlag());
        }
        // 计算店铺到最近地铁站的距离
        JSONObject nearbySubway = gaoDeMapUtil.getNearbySubway(storeMainInfoVo.getStorePosition().split(",")[0], storeMainInfoVo.getStorePosition().split(",")[1]);
        // 地铁名
        String subWayName = nearbySubway.getString("name");
        storeMainInfoVo.setSubwayName(subWayName);
        // 地铁站经纬度
        String subWayJing = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[0];
        String subWayWei = nearbySubway.getString("location") == null ? null : nearbySubway.getString("location").split(",")[1];
        if ((subWayJing != null && !subWayJing.isEmpty()) && (subWayWei != null && !subWayWei.isEmpty())) {
            double storeJing = Double.parseDouble(storeMainInfoVo.getStorePosition().split(",")[0]);
            double storeWei = Double.parseDouble(storeMainInfoVo.getStorePosition().split(",")[1]);
            double storeDistance2 = DistanceUtil.haversineCalculateDistance(Double.parseDouble(subWayJing), Double.parseDouble(subWayWei), storeJing, storeWei);
            storeMainInfoVo.setDistance2(storeDistance2);
        } else {
            storeMainInfoVo.setDistance2(0);
        }
        return storeMainInfoVo;
    }


    public List<StoreBusinessInfoVo> getStoreInfoBusinessHoursNew(Integer id) {
        // 查询营业时间（包含正常时间和特殊时间）
        List<StoreBusinessInfo> storeBusinessInfoList = storeBusinessInfoMapper.selectList(
                new LambdaQueryWrapper<StoreBusinessInfo>()
                        .eq(StoreBusinessInfo::getStoreId, id)
                        .eq(StoreBusinessInfo::getDeleteFlag, 0)
                        .orderByAsc(StoreBusinessInfo::getBusinessType) // 先按类型排序：1-正常时间，2-特殊时间
                        .orderByAsc(StoreBusinessInfo::getBusinessDate) // 再按日期排序
        );

        // 转换为 VO 并关联节假日信息
        // store_business_info 的 essential_id 关联 essential_holiday_comparison 的 id
        List<StoreBusinessInfoVo> resultList = new ArrayList<>();
        for (StoreBusinessInfo businessInfo : storeBusinessInfoList) {
            StoreBusinessInfoVo vo = new StoreBusinessInfoVo();
            // 复制基本信息
            BeanUtils.copyProperties(businessInfo, vo);

            // 如果有关联的节假日ID（essential_id），查询 essential_holiday_comparison 表的节假日信息
            if (businessInfo.getEssentialId() != null && !businessInfo.getEssentialId().trim().isEmpty()) {
                Integer essentialId = null;
                try {
                    essentialId = Integer.parseInt(businessInfo.getEssentialId().trim());
                    EssentialHolidayComparison holiday = essentialHolidayComparisonMapper.selectById(essentialId);
                    if (holiday != null) {
                        vo.setHolidayInfo(holiday);
                    } else {
                        log.warn("门店营业时间关联的节假日信息不存在，storeId=" + id + ", essentialId=" + essentialId);
                    }
                } catch (NumberFormatException e) {
                    log.warn("门店营业时间关联的节假日ID格式错误，storeId=" + id + ", essentialId=" + businessInfo.getEssentialId());
                } catch (Exception e) {
                    log.error("查询节假日信息失败，storeId=" + id + ", essentialId=" + businessInfo.getEssentialId(), e);
                }
            }

            resultList.add(vo);
        }

        return resultList;
    }

}
