package org.dromara.erp.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.erp.domain.ErpOrder;
import org.dromara.erp.domain.query.ErpOrderQuery;
import org.dromara.erp.domain.vo.ErpOrderVo;
import org.dromara.erp.mapper.ErpOrderMapper;
import org.dromara.erp.service.IErpOrderService;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单 Service 业务层处理
 * @Author: Antigravity
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ErpOrderServiceImpl implements IErpOrderService {

    private final ErpOrderMapper baseMapper;
    private final org.dromara.erp.mapper.ErpOrderDetailMapper erpOrderDetailMapper;
    private final org.dromara.erp.mapper.ErpSaleOrderMasterMapper erpSaleOrderMasterMapper;
    private final LockTemplate lockTemplate;

    @Override
    public TableDataInfo<ErpOrderVo> queryPageList(ErpOrderQuery query, PageQuery pageQuery) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ErpOrderVo> result = baseMapper.selectOrderVoPage(pageQuery.build(), query);

        List<ErpOrderVo> list = result.getRecords();
        if (ObjectUtil.isNotEmpty(list)) {
            fillOrderDetails(list);
        }
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<ErpOrderVo> queryPageListByClientId(ErpOrderQuery query, PageQuery pageQuery) {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ErpOrderVo> result = baseMapper.selectOrderVoPageByClientId(pageQuery.build(), query);

        List<ErpOrderVo> list = result.getRecords();
        if (ObjectUtil.isNotEmpty(list)) {
            fillOrderDetails(list);
        }
        return TableDataInfo.build(result);
    }

    @Override
    public List<ErpOrderVo> queryList(ErpOrderQuery query) {
        List<ErpOrderVo> list = baseMapper.selectOrderVoList(query);
        if (ObjectUtil.isNotEmpty(list)) {
            fillOrderDetails(list);
        }
        return list;
    }

    private LambdaQueryWrapper<ErpOrder> buildQueryWrapper(ErpOrderQuery query) {
        LambdaQueryWrapper<ErpOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(ObjectUtil.isNotEmpty(query.getCode()), ErpOrder::getCode, query.getCode());
        lqw.eq(ObjectUtil.isNotEmpty(query.getPlacer()), ErpOrder::getPlacer, query.getPlacer());
        lqw.eq(ObjectUtil.isNotEmpty(query.getIsConfirmed()), ErpOrder::getIsConfirmed, query.getIsConfirmed());
        lqw.eq(ObjectUtil.isNotEmpty(query.getDocCode()), ErpOrder::getDocCode, query.getDocCode());
        lqw.orderByDesc(ErpOrder::getCreateTime);
        return lqw;
    }

    private void fillOrderDetails(List<ErpOrderVo> list) {
        List<String> orderIds = list.stream().map(ErpOrderVo::getRowId).toList();
        LambdaQueryWrapper<org.dromara.erp.domain.ErpOrderDetail> detailLqw = Wrappers.lambdaQuery();
        detailLqw.in(org.dromara.erp.domain.ErpOrderDetail::getOrderId, orderIds);
        List<org.dromara.erp.domain.vo.ErpOrderDetailVo> allDetails = erpOrderDetailMapper.selectVoList(detailLqw);

        for (ErpOrderVo vo : list) {
            List<org.dromara.erp.domain.vo.ErpOrderDetailVo> details = allDetails.stream()
                    .filter(d -> vo.getRowId().equals(d.getOrderId()))
                    .toList();
            vo.setDetails(details);
            vo.setTotalCount(details.stream().mapToInt(d -> d.getCount() == null ? 0 : d.getCount()).sum());
        }
    }

    @Override
    public ErpOrderVo queryById(String rowId) {
        ErpOrderVo vo = baseMapper.selectOrderVoById(rowId);
        if (vo != null) {
            LambdaQueryWrapper<org.dromara.erp.domain.ErpOrderDetail> detailLqw = Wrappers.lambdaQuery();
            detailLqw.eq(org.dromara.erp.domain.ErpOrderDetail::getOrderId, rowId);
            List<org.dromara.erp.domain.vo.ErpOrderDetailVo> details = erpOrderDetailMapper.selectVoList(detailLqw);
            vo.setDetails(details);
            vo.setTotalCount(details.stream().mapToInt(d -> d.getCount() == null ? 0 : d.getCount()).sum());
        }
        return vo;
    }

    @Override
    public Map<Integer, Long> countByStatus() {
        List<Map<String, Object>> list = baseMapper.countOrderStatus();
        Map<Integer, Long> result = new java.util.LinkedHashMap<>();
        for (Map<String, Object> row : list) {
            Integer key = ((Number) row.get("statusKey")).intValue();
            Long value = ((Number) row.get("statusCount")).longValue();
            result.put(key, value);
        }
        return result;
    }

    private String generateOrderCode() {
        String dateStr = DateUtil.format(new Date(), "yyMMdd");
        String redisKey = CacheConstants.ERP_ORDER_CODE_KEY + dateStr;
        String lockKey = CacheConstants.ERP_ORDER_CODE_LOCK_KEY + dateStr;

        try {
            if (!RedisUtils.isExistsObject(redisKey)) {
                LockInfo lockInfo = lockTemplate.lock(lockKey, 5000L, 3000L, RedissonLockExecutor.class);
                if (lockInfo == null) {
                    log.warn("订单号恢复锁获取超时，降级使用雪花ID");
                    return "WD" + IdUtil.getSnowflakeNextIdStr();
                }
                try {
                    if (!RedisUtils.isExistsObject(redisKey)) {
                        LambdaQueryWrapper<ErpOrder> lqw = Wrappers.lambdaQuery();
                        lqw.likeRight(ErpOrder::getCode, "WD" + dateStr)
                           .orderByDesc(ErpOrder::getCreateTime);
                        List<ErpOrder> orders = baseMapper.selectList(lqw);
                        long lastSeq = 0L;
                        if (!orders.isEmpty()) {
                            String lastCode = orders.get(0).getCode();
                            String numPart = lastCode.substring(lastCode.length() - 3);
                            lastSeq = Long.parseLong(numPart);
                        }
                        RedisUtils.setAtomicValue(redisKey, lastSeq);
                        RedisUtils.expire(redisKey, 60L * 60L * 25L);
                    }
                } finally {
                    lockTemplate.releaseLock(lockInfo);
                }
            }
            long seq = RedisUtils.incrAtomicValue(redisKey);
            return "WD" + dateStr + String.format("%03d", seq);
        } catch (Exception e) {
            log.error("订单号生成失败，降级使用雪花ID", e);
            return "WD" + IdUtil.getSnowflakeNextIdStr();
        }
    }

    @Override
    @com.baomidou.dynamic.datasource.annotation.DSTransactional
    public String insert(org.dromara.erp.domain.bo.ErpOrderBo bo) {
        ErpOrder entity = MapstructUtils.convert(bo, ErpOrder.class);
        if (ObjectUtil.isEmpty(entity.getRowId())) {
            entity.setRowId(IdUtil.fastUUID());
        }
        if (ObjectUtil.isEmpty(entity.getCode())) {
            entity.setCode(generateOrderCode());
        }
        if (entity.getPlacer() == null) {
            try {
                log.info("[调试] 开始自动填充 Placer...");
                log.info("[调试] 当前是否登录: {}", org.dromara.common.satoken.utils.LoginHelper.isLogin());
                log.info("[调试] 当前 Token: {}", cn.dev33.satoken.stp.StpUtil.getTokenValue());

                Long userId = org.dromara.common.satoken.utils.LoginHelper.getUserId();
                log.info("[调试] 获取到的用户 ID: {}", userId);

                if (userId != null) {
                    entity.setPlacer(userId);
                    log.info("[调试] 自动填充 Placer 成功: {}", userId);
                } else {
                    log.warn("[调试] 获取到的用户 ID 为空，请检查 Token 是否有效或 Security 上下文是否正确传递");
                }
            } catch (Exception e) {
                log.error("[调试] 自动填充 Placer 发生异常: {}", e.getMessage(), e);
            }
        }
        if (entity.getPlaceTime() == null) {
            entity.setPlaceTime(new Date());
        }
        if (entity.getIsConfirmed() == null) {
            entity.setIsConfirmed(0);
        }

        boolean result = baseMapper.insert(entity) > 0;

        if (result && ObjectUtil.isNotEmpty(bo.getDetailIds())) {
            // 根据前端传递的明细 ID 列表，精确更新这批明细关联的订单 ID
            com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper<org.dromara.erp.domain.ErpOrderDetail> luw = Wrappers.lambdaUpdate();
            luw.set(org.dromara.erp.domain.ErpOrderDetail::getOrderId, entity.getRowId())
               .in(org.dromara.erp.domain.ErpOrderDetail::getRowId, bo.getDetailIds());
            erpOrderDetailMapper.update(null, luw);
        }
        return result ? entity.getRowId() : null;
    }

    @Override
    public Boolean cancelOrder(String rowId) {
        ErpOrder order = baseMapper.selectById(rowId);
        if (order == null) {
            throw new org.dromara.common.core.exception.ServiceException("订单不存在");
        }
        if (Integer.valueOf(1).equals(order.getIsConfirmed())) {
            throw new org.dromara.common.core.exception.ServiceException("已确认的订单不可以撤销");
        }
        order.setIsConfirmed(0);
        return baseMapper.updateById(order) > 0;
    }

    @Override
    public Boolean markUrgent(String rowId) {
        ErpOrder order = baseMapper.selectById(rowId);
        if (order == null) {
            throw new org.dromara.common.core.exception.ServiceException("订单不存在");
        }
        order.setUrgentFlag(1);
        return baseMapper.updateById(order) > 0;
    }

    @Override
    public void syncErpOrderStatus() {
        log.info("[ERP状态同步] 开始同步...");
        // 查询 erpDocCode 不为空且未确认的订单
        LambdaQueryWrapper<ErpOrder> lqw = Wrappers.lambdaQuery();
        lqw.isNotNull(ErpOrder::getDocCode)
           .ne(ErpOrder::getDocCode, "")
           .eq(ErpOrder::getIsConfirmed, 0);
        List<ErpOrder> orders = baseMapper.selectList(lqw);

        if (orders.isEmpty()) {
            log.info("[ERP状态同步] 无可同步的订单");
            return;
        }

        int updatedCount = 0;
        for (ErpOrder order : orders) {
            try {
                // 根据 erpDocCode 查询 ERP 销售订单
                LambdaQueryWrapper<org.dromara.erp.domain.ErpSaleOrderMaster> masterLqw = Wrappers.lambdaQuery();
                masterLqw.eq(org.dromara.erp.domain.ErpSaleOrderMaster::getDocCode, order.getDocCode());
                org.dromara.erp.domain.ErpSaleOrderMaster master = erpSaleOrderMasterMapper.selectOne(masterLqw);

                if (master == null) {
                    log.warn("[ERP状态同步] 未找到 ERP 单据: {}", order.getDocCode());
                    continue;
                }

                boolean shouldConfirm = false;
                if (Integer.valueOf(1).equals(master.getFinished()) ||
                    Integer.valueOf(1).equals(master.getReviewed()) ||
                    Integer.valueOf(1).equals(master.getApproved())) {
                    shouldConfirm = true;
                }

                if (shouldConfirm) {
                    order.setIsConfirmed(1);
                    baseMapper.updateById(order);
                    updatedCount++;
                    log.info("[ERP状态同步] 订单 {} (ERP:{}) 状态更新为已确认",
                        order.getCode(), order.getDocCode());
                }
            } catch (Exception e) {
                log.error("[ERP状态同步] 处理订单 {} 异常: {}", order.getCode(), e.getMessage(), e);
            }
        }
        log.info("[ERP状态同步] 完成，共处理 {} 条，更新 {} 条", orders.size(), updatedCount);
    }
}
