package com.ruoyi.logistics.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.datascope.annotation.DataScope;
import com.ruoyi.common.redis.service.RedisIdGenerator;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.logistics.constant.RedisCacheConstants;
import com.ruoyi.logistics.domain.BizAddressBook;
import com.ruoyi.logistics.domain.BizWaybillCostDetails;
import com.ruoyi.logistics.domain.dto.OrderStatisticsDto;
import com.ruoyi.logistics.domain.dto.RecentAddressDto;
import com.ruoyi.logistics.domain.dto.JDOrderDTO;
import com.ruoyi.logistics.enums.OrderStatusEnum;
import com.ruoyi.logistics.mapper.BizAddressBookMapper;
import com.ruoyi.logistics.mapper.BizWaybillCostDetailsMapper;
import com.ruoyi.logistics.service.LogisticsOrderService;
import com.ruoyi.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.logistics.mapper.BizWaybillOrderMapper;
import com.ruoyi.logistics.domain.BizWaybillOrder;
import com.ruoyi.logistics.domain.dto.DailyOrderStatisticsDto;
import com.ruoyi.logistics.service.IBizWaybillOrderService;

/**
 * 运单管理Service业务层处理
 * 
 * @author RuiJing
 * @date 2026-01-29
 */
@Slf4j
@Service
public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService 
{
    @Autowired
    private BizWaybillOrderMapper bizWaybillOrderMapper;
    @Autowired
    LogisticsOrderService logisticsOrderService;

    @Autowired
    private RedisIdGenerator redisIdGenerator;

    @Autowired
    private BizWaybillCostDetailsMapper bizWaybillCostDetailsMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private BizAddressBookMapper bizAddressBookMapper;

    /**
     * 查询运单管理
     * 
     * @param waybillId 运单管理主键
     * @return 运单管理
     */
    @Override
    public BizWaybillOrder selectBizWaybillOrderByWaybillId(Long waybillId)
    {

        return bizWaybillOrderMapper.selectBizWaybillOrderByWaybillId(waybillId);
    }

    /**
     * 查询运单管理列表
     * 
     * @param bizWaybillOrder 运单管理
     * @return 运单管理
     */
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<BizWaybillOrder> selectBizWaybillOrderList(BizWaybillOrder bizWaybillOrder)
    {
        return bizWaybillOrderMapper.selectBizWaybillOrderList(bizWaybillOrder);
    }

    /**
     * 新增运单管理
     * 
     * @param bizWaybillOrder 运单管理
     * @return 结果
     */
    @Override
    public int insertBizWaybillOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException, JsonProcessingException {

        LoginUser loginUser = SecurityUtils.getLoginUser();
        String orderId = redisIdGenerator.generateUniqueId("RJSD");
        bizWaybillOrder.setWaybillNo(orderId);
        bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_1.getCode());
        //前置校验
        JSONObject jsonObject= logisticsOrderService.precheckOrder(bizWaybillOrder);
        if(!jsonObject.getBooleanValue("success")){
            throw new ServiceException("下单前置校验未通过！ 原因:"+jsonObject.getString("msg"));
        }
        JSONObject orderObject= logisticsOrderService.createOrder(bizWaybillOrder);
        if(!orderObject.getBooleanValue("success")){
            throw new ServiceException("下单失败！ 原因:"+orderObject.getString("msg"));
        }
        if(2==bizWaybillOrder.getOrderType()){
            //顺丰物流返回的运单号
            JSONArray waybillNoArray=orderObject.getJSONArray("data");
            for (int i = 0; i < waybillNoArray.size(); i++) {
                JSONObject waybillNoJSONObject = waybillNoArray.getJSONObject(i);
                int waybillType = waybillNoJSONObject.getIntValue("waybillType");
                String  waybillNo = waybillNoJSONObject.getString("waybillNo");
                if(waybillType==1){
                    bizWaybillOrder.setExternalWaybillNo(waybillNo) ;
                }
            }
        }


        bizWaybillOrder.setPickupType(1);
        bizWaybillOrder.setCreateTime(DateUtils.getNowDate());
        bizWaybillOrder.setUserId(loginUser.getUserid());
        bizWaybillOrder.setDeptId(loginUser.getSysUser().getDeptId());
        
        // 保存寄件地址和收件地址到Redis作为用户最近使用地址
        saveRecentAddresses(bizWaybillOrder, loginUser.getUserid());
        
        return bizWaybillOrderMapper.insertBizWaybillOrder(bizWaybillOrder);
    }

    /**
     * 修改运单管理
     * 
     * @param bizWaybillOrder 运单管理
     * @return 结果
     */
    @Override
    public int updateBizWaybillOrder(BizWaybillOrder bizWaybillOrder){
        bizWaybillOrder.setUpdateTime(DateUtils.getNowDate());
        return  bizWaybillOrderMapper.updateBizWaybillOrder(bizWaybillOrder);
    }

    /**
     * 批量删除运单管理
     * 
     * @param waybillIds 需要删除的运单管理主键
     * @return 结果
     */
    @Override
    public int deleteBizWaybillOrderByWaybillIds(Long[] waybillIds)
    {
        return bizWaybillOrderMapper.deleteBizWaybillOrderByWaybillIds(waybillIds);
    }

    /**
     * 删除运单管理信息
     * 
     * @param waybillId 运单管理主键
     * @return 结果
     */
    @Override
    public int deleteBizWaybillOrderByWaybillId(Long waybillId)
    {
        return bizWaybillOrderMapper.deleteBizWaybillOrderByWaybillId(waybillId);
    }

    @Override
    public BizWaybillOrder selectBizWaybillOrderByQuery(BizWaybillOrder query) {
        return bizWaybillOrderMapper.selectBizWaybillOrderByQuery(query);
    }

    @Override
    public void updateBizWaybillOrderState(BizWaybillOrder bizWaybillOrder) {
         bizWaybillOrderMapper.updateBizWaybillOrderState(bizWaybillOrder);

    }

    @Override
    public int canceleBizWaybillOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
        JSONObject orderObject= logisticsOrderService.cancelOrder(bizWaybillOrder);
        if(!orderObject.getBooleanValue("success")){
            throw new ServiceException(orderObject.getString("msg"));
        }
        bizWaybillOrder.setOrderStatus(6);
        return bizWaybillOrderMapper.canceleBizWaybillOrder(bizWaybillOrder);

    }

    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public OrderStatisticsDto getTotalOrdersByOrderType(BizWaybillOrder bizWaybillOrder, BizWaybillCostDetails bizWaybillCostDetails) {
        OrderStatisticsDto orderStatisticsDto = bizWaybillOrderMapper.selectTotalOrdersByOrderType(bizWaybillOrder);
        BigDecimal totalAmount = bizWaybillCostDetailsMapper.selectBizWaybillCostDetailsSum(bizWaybillCostDetails);
        orderStatisticsDto.setTotalAmount(totalAmount);
        return orderStatisticsDto;
    }

    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<DailyOrderStatisticsDto> getLast7DaysOrderStatistics(BizWaybillOrder bizWaybillOrder) {
        // 获取最近7天的日期范围
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(14); // 包含今天在内的7天
        bizWaybillOrder.setStartDate(startDate);
        bizWaybillOrder.setEndDate(endDate);
        
        // 查询数据库中指定日期范围的所有数据
        List<DailyOrderStatisticsDto> recentData = bizWaybillOrderMapper.selectLast7DaysOrderStatisticsByDateRange(bizWaybillOrder);

        // 创建一个Map来存储查询结果，以日期为键
        Map<String, DailyOrderStatisticsDto> dataMap = new HashMap<>();
        for (DailyOrderStatisticsDto dto : recentData) {
            String dateStr = DateFormatUtils.format(dto.getStatisticsDate(), "yyyy-MM-dd"); // 假设日期格式为yyyy-MM-dd
            dataMap.put(dateStr, dto);
        }
        
        // 构建完整的7天数据，缺失的日期用0填充
        List<DailyOrderStatisticsDto> result = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            String dateStr = date.toString();
            if (dataMap.containsKey(dateStr)) {
                result.add(dataMap.get(dateStr));
            } else {
                // 如果当天没有数据，则创建一个全为0的记录
                DailyOrderStatisticsDto emptyDto = new DailyOrderStatisticsDto();
                emptyDto.setStatisticsDate(java.util.Date.from(date.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant()));
                emptyDto.setJdOrderCount(0L);
                emptyDto.setSfOrderCount(0L);
                emptyDto.setTotalOrderCount(0L);
                result.add(emptyDto);
            }
        }
        
        return result;
    }

    /**
     * 保存寄件地址和收件地址到Redis作为用户最近使用地址
     * @param userId 用户ID
     */
    private void saveRecentAddresses(BizWaybillOrder bizWaybillOrder, Long userId) {
        try {
            // 保存寄件地址
            saveRecentAddressToRedis(bizWaybillOrder.getSenderProvince(),
                    bizWaybillOrder.getSenderCity(),
                    bizWaybillOrder.getSenderCounty(),
                    bizWaybillOrder.getSenderAddress(),
                    bizWaybillOrder.getSenderName(),
                    bizWaybillOrder.getSenderPhone(),
                    "sender", userId);
            
            // 保存收件地址
            saveRecentAddressToRedis(bizWaybillOrder.getReceiverProvince(),
                    bizWaybillOrder.getReceiverCity(),
                    bizWaybillOrder.getReceiverCounty(),
                    bizWaybillOrder.getReceiverAddress(),
                    bizWaybillOrder.getReceiverName(),
                    bizWaybillOrder.getReceiverPhone(),
                    "receiver", userId);
        } catch (Exception e) {
            //记录日志但不影响主流程
            log.info("保存最近使用地址到Redis失败: ", e);
        }
    }

    /**
     * 保存单个地址到Redis
     * @param userId 用户ID
     */
    private void saveRecentAddressToRedis(String provinceName, String cityName, String countyName,
                                         String detailedAddress, String contactName, String contactPhone,
                                         String addressType, Long userId) {
        if (provinceName == null || cityName == null || contactName == null || contactPhone == null) {
            return; //基信息不完整，不保存
        }

        BizAddressBook bizAddressBook = new BizAddressBook();
        bizAddressBook.setUserId(userId);
        bizAddressBook.setContactName(contactName);
        bizAddressBook.setContactPhone(contactPhone);
        bizAddressBook.setProvinceName(provinceName);
        bizAddressBook.setCityName(cityName);
        bizAddressBook.setCountyName(countyName);
        bizAddressBook.setDetailedAddress(detailedAddress);

        List<BizAddressBook> bizAddressBooks = bizAddressBookMapper.selectBizAddressBookList(bizAddressBook);
        if (CollectionUtils.isEmpty(bizAddressBooks)) {
            bizAddressBookMapper.insertBizAddressBook(bizAddressBook);
        }
        
        //构造Redis key
        String redisKey = RedisCacheConstants.USER_RECENT_ADDRESS_CACHE_KEY + userId;
        
        // 创建地址对象
        RecentAddressDto addressDto = new RecentAddressDto();
        addressDto.setProvinceName(provinceName);
        addressDto.setCityName(cityName);
        addressDto.setCountyName(countyName);
        addressDto.setDetailedAddress(detailedAddress);
        addressDto.setContactName(contactName);
        addressDto.setContactPhone(contactPhone);

        // 获取当前列表
        List<RecentAddressDto> addressList = redisService.getCacheList(redisKey);
        if (addressList == null) {
            addressList = new ArrayList<>();
        }
        
        //移除相同的地址（如果已存在）
        addressList.removeIf(addr -> 
            addr.getProvinceName().equals(provinceName) &&
            addr.getCityName().equals(cityName) &&
            addr.getCountyName().equals(countyName) &&
            addr.getDetailedAddress().equals(detailedAddress) &&
            addr.getContactName().equals(contactName) &&
            addr.getContactPhone().equals(contactPhone)
        );
        
        //将新地址添加到列表开头
        addressList.add(0, addressDto);
        
        // 保持最多5个地址
        if (addressList.size() > 5) {
            addressList = addressList.subList(0, 5);
        }
        
        // 保存到Redis，设置过期时间30天
        redisService.deleteObject(redisKey);
        redisService.setCacheList(redisKey, addressList);
    }

    @Override
    public JSONObject queryOrderFeeInfo(Integer orderType, String waybillCode) {
        logisticsOrderService.queryOrderFeeInfoByWaybillCode(orderType, waybillCode);
        return null;
    }

    @Override
    public JSONObject queryWaybillPdf(BizWaybillOrder bizWaybillOrder) {
        JSONObject jsonObject = logisticsOrderService.queryWaybillPdf(bizWaybillOrder);
        if (jsonObject.getBoolean("success")) {
            if(1==bizWaybillOrder.getOrderType()) {
                bizWaybillOrder.setPdfUrl(jsonObject.getString("msg"));
                bizWaybillOrderMapper.updateBizWaybillOrder(bizWaybillOrder);
            }
        }
        return jsonObject;
    }

    /**
     * 批量下单
     *
     * @param orderList 订单列表
     * @param orderType 订单类型 1-京东，2-顺丰
     * @return 结果数组，每个元素表示对应订单的结果 [0:成功数，1:失败数]
     */
    @Override
    public int[] batchInsertBizWaybillOrder(List<JDOrderDTO> orderList, Integer orderType) {
        int successCount = 0;
        int failCount = 0;
        List<String> errorMessages = new ArrayList<>();

        LoginUser loginUser = SecurityUtils.getLoginUser();

        for (JDOrderDTO dto : orderList) {
            try {
                // 将 JDOrderDTO 转换为 BizWaybillOrder
                BizWaybillOrder bizWaybillOrder = convertToBizWaybillOrder(dto, orderType, loginUser);
                this.insertBizWaybillOrder(bizWaybillOrder);
                successCount++;
            } catch (Exception e) {
                log.error("批量下单异常！发件人:{}, 收件人:{}", 
                    dto.getSenderName(), dto.getReceiverName(), e);
                failCount++;
                errorMessages.add(String.format("订单 %s-%s 异常：%s", 
                    dto.getSenderName(), dto.getReceiverName(), e.getMessage()));
            }
        }

        log.info("批量下单完成！总数:{}, 成功:{}, 失败:{}", orderList.size(), successCount, failCount);
        
        return new int[]{successCount, failCount};
    }

    /**
     * 将 JDOrderDTO 转换为 BizWaybillOrder
     */
    private BizWaybillOrder convertToBizWaybillOrder(JDOrderDTO dto, Integer orderType, LoginUser loginUser) {
        BizWaybillOrder bizWaybillOrder = new BizWaybillOrder();
        
        // 设置订单类型
        bizWaybillOrder.setOrderType(orderType);
        
        // 复制基本信息
        bizWaybillOrder.setSenderName(dto.getSenderName());
        bizWaybillOrder.setSenderPhone(dto.getSenderPhone());
        bizWaybillOrder.setSenderProvince(dto.getSenderProvince());
        bizWaybillOrder.setSenderCity(dto.getSenderCity());
        bizWaybillOrder.setSenderCounty(dto.getSenderCounty());
        bizWaybillOrder.setSenderAddress(dto.getSenderAddress());
        
        bizWaybillOrder.setReceiverName(dto.getReceiverName());
        bizWaybillOrder.setReceiverPhone(dto.getReceiverPhone());
        bizWaybillOrder.setReceiverProvince(dto.getReceiverProvince());
        bizWaybillOrder.setReceiverCity(dto.getReceiverCity());
        bizWaybillOrder.setReceiverCounty(dto.getReceiverCounty());
        bizWaybillOrder.setReceiverAddress(dto.getReceiverAddress());
        
        // 货物信息
        bizWaybillOrder.setGoodsName(dto.getGoodsName());
        bizWaybillOrder.setGoodsWeight(dto.getGoodsWeight());
        bizWaybillOrder.setGoodsVolume(dto.getGoodsVolume());
        bizWaybillOrder.setGoodsQty(dto.getGoodsQty());
        
        // 取件时间
        bizWaybillOrder.setSendStartTime(dto.getSendStartTime());
        bizWaybillOrder.setSendEndTime(dto.getSendEndTime());
        
        // 产品信息和增值服务
        bizWaybillOrder.setProductCode(dto.getProductCode());
        bizWaybillOrder.setAddedService(dto.getAddedService());
        
        // 备注
        bizWaybillOrder.setRemark(dto.getRemark());
        
        return bizWaybillOrder;
    }
}
