package com.zg.project.wisdom.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
import com.zg.common.utils.StringUtils;
import com.zg.common.utils.poi.ExcelUtil;
import com.zg.project.wisdom.domain.vo.*;
import com.zg.project.wisdom.mapper.GysJhMapper;
import com.zg.project.wisdom.mapper.RkStatisticsMapper;
import com.zg.project.wisdom.service.RkStatisticsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

@Service
public class RkStatisticsServiceImpl implements RkStatisticsService {

    @Resource
    private RkStatisticsMapper rkStatisticsMapper;


    @Override
    public List<Map<String, Object>> getAgeStatsAsList() {
        // 这里的 gt10/gt20/gt30 均为“项目数”（COUNT DISTINCT xm_no）
        RkAgeStatVO vo = rkStatisticsMapper.selectAgeStats();

        List<Map<String, Object>> list = new ArrayList<>(3);
        Map<String, Object> m1 = new HashMap<>();
        m1.put("name", ">10天");
        m1.put("value", vo.getGt10());
        list.add(m1);

        Map<String, Object> m2 = new HashMap<>();
        m2.put("name", ">20天");
        m2.put("value", vo.getGt20());
        list.add(m2);

        Map<String, Object> m3 = new HashMap<>();
        m3.put("name", ">30天");
        m3.put("value", vo.getGt30());
        list.add(m3);

        return list;
    }
    /**
     * 库存类型统计（仅未出库）
     */
    @Override
    public List<RkSummaryVO> getTypeSummary() {
        List<RkSummaryVO> list = rkStatisticsMapper.selectTypeSummary();
        return CollectionUtils.isEmpty(list) ? Collections.emptyList() : list;
    }

    /**
     * 县局统计（仅未出库）
     */
    @Override
    public List<RkSummaryVO> getCountySummary() {
        List<RkSummaryVO> list = rkStatisticsMapper.selectCountySummary();
        return CollectionUtils.isEmpty(list) ? Collections.emptyList() : list;
    }

    private static final DateTimeFormatter F = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public Map<String, Object> weekDaily(String start, String end) {
        // 如果携带了 start 和 end，就直接用；否则：end=今天，start=本周周一
        if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
            LocalDate today = LocalDate.now();
            LocalDate monday = today.with(DayOfWeek.MONDAY);
            start = monday.format(F);
            end = today.format(F);
        }

        Map<String, Object> ret = new HashMap<>(2);
        ret.put("in",  rkStatisticsMapper.selectWeekDailyIn(start, end));
        ret.put("out", rkStatisticsMapper.selectWeekDailyOut(start, end));
        return ret;
    }


    @Override
    public Age3060ResultVO getAge3060Detail() {
        // 1) 汇总（同时返回 >30 / >60 的项目数、条目数、总金额）
        AgeSummaryVO summary = rkStatisticsMapper.selectAge3060Summary();

        // 2) 明细（>30）
        List<RkAgeDetailVO> gt30List = rkStatisticsMapper.selectAgeDetails(30);

        // 3) 明细（>60）
        List<RkAgeDetailVO> gt60List = rkStatisticsMapper.selectAgeDetails(60);

        // 4) 组装返回
        Age3060ResultVO vo = new Age3060ResultVO();
        vo.setGt30(summary.getGt30());
        vo.setGt60(summary.getGt60());
        vo.setGt30List(gt30List);
        vo.setGt60List(gt60List);
        return vo;
    }

    @Override
    public List<Map<String, Object>> getAge3060() {
        // 1) 汇总（同时返回 >30 / >60 的项目数、条目数、总金额）
        AgeSummaryVO summary = rkStatisticsMapper.selectAge3060Summary();

        // 2) 用 List<Map> 封装成数组结构
        List<Map<String, Object>> list = new ArrayList<>();

        Map<String, Object> gt30 = new HashMap<>();
        gt30.put("name", ">30天");
        gt30.put("value", summary.getGt30().getGoodsCount()); // 这里取“货物数量”作 value
        list.add(gt30);

        Map<String, Object> gt60 = new HashMap<>();
        gt60.put("name", ">60天");
        gt60.put("value", summary.getGt60().getGoodsCount());
        list.add(gt60);

        return list;
    }


    /**
     * 导出库龄明细（>30天 与 >60天 合并导出为一张表）
     * - 所有业务逻辑均在 Service 层完成
     * - 使用若依 ExcelUtil + @Excel 注解导出
     */
    @Override
    public void exportAge3060(HttpServletResponse response) {
        // 1) 调用已有统计逻辑
        Age3060ResultVO res = this.getAge3060Detail();

        // 2) 合并两组明细，加上导出用的分组字段
        List<RkAgeDetailVO> out = new ArrayList<>();
        if (res.getGt30List() != null) {
            for (RkAgeDetailVO row : res.getGt30List()) {
                normalizeRowForExport(row, ">30天");
                out.add(row);
            }
        }
        if (res.getGt60List() != null) {
            for (RkAgeDetailVO row : res.getGt60List()) {
                normalizeRowForExport(row, ">60天");
                out.add(row);
            }
        }

        // 3) 导出 Excel
        ExcelUtil<RkAgeDetailVO> util = new ExcelUtil<>(RkAgeDetailVO.class);
        util.exportExcel(response, out, "库龄明细");
    }

    private void normalizeRowForExport(RkAgeDetailVO row, String bucket) {
        row.setAgeBucket(bucket);
        if (row.getAmount() == null) {
            BigDecimal dj  = row.getHtDj()    == null ? BigDecimal.ZERO : row.getHtDj();
            BigDecimal qty = row.getRealQty() == null ? BigDecimal.ZERO : row.getRealQty();
            row.setAmount(dj.multiply(qty));
        }
    }

    /**
     * 获取入库类型饼状图数据
     */
    @Override
    public List<RkTypePieVO> getTypePie() {
        return rkStatisticsMapper.selectTypePie();
    }

    @Override
    public List<RkTypePieVO> getTypeSummaryByRange(String start, String end) {
        // 基础入参校验（避免全表扫描/人为误操作）
        if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
            throw new ServiceException("start/end 不能为空，建议格式：yyyy-MM-dd");
        }
        return rkStatisticsMapper.selectTypeSummaryByRange(start, end);
    }

    @Override
    public List<RkTypePieVO> getOutTypeSummaryByRange(String start, String end) {
        if (StringUtils.isBlank(start) || StringUtils.isBlank(end)) {
            throw new ServiceException("start/end 不能为空，建议格式：yyyy-MM-dd");
        }
        return rkStatisticsMapper.selectOutTypeSummaryByRange(start, end);
    }

    private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Override
    public RkMonthInOutSummaryVO getThisMonthInOutSummary() {
        // 本月起止： [YYYY-MM-01 00:00:00, 下月01 00:00:00)
        LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
        LocalDate nextMonthFirst = firstDay.plusMonths(1);

        String start = firstDay.atStartOfDay().format(DF);
        String end   = nextMonthFirst.atStartOfDay().format(DF);

        RkMonthSummaryVO inSummary  = rkStatisticsMapper.selectMonthlyInSummary(start, end);
        RkMonthSummaryVO outSummary = rkStatisticsMapper.selectMonthlyOutSummary(start, end);

        // null 兜底
        if (inSummary == null) {
            inSummary = new RkMonthSummaryVO();
        }
        if (outSummary == null) {
            outSummary = new RkMonthSummaryVO();
        }

        RkMonthInOutSummaryVO vo = new RkMonthInOutSummaryVO();
        vo.setInSummary(inSummary);
        vo.setOutSummary(outSummary);
        return vo;
    }


    @Override
    public GysJhUndeliveredVO getUndeliveredSummary() {
        // 分别查询：未到（status=0）、部分未到（status=2）
        GysJhUndeliveredSummaryVO undelivered = rkStatisticsMapper.selectUndelivered();
        GysJhUndeliveredSummaryVO partial     = rkStatisticsMapper.selectPartialUndelivered();

        // 对象兜底
        if (undelivered == null) undelivered = new GysJhUndeliveredSummaryVO();
        if (partial == null)     partial     = new GysJhUndeliveredSummaryVO();

        // 字段兜底（防止仍有 null 透出）
        if (undelivered.getProjectCount() == null) undelivered.setProjectCount(0);
        if (undelivered.getItemCount()    == null) undelivered.setItemCount(0);
        if (undelivered.getTotalQty()     == null) undelivered.setTotalQty(0L);
        if (undelivered.getAmountPlan()   == null) undelivered.setAmountPlan(BigDecimal.ZERO);

        if (partial.getProjectCount() == null) partial.setProjectCount(0);
        if (partial.getItemCount()    == null) partial.setItemCount(0);
        if (partial.getTotalQty()     == null) partial.setTotalQty(0L);
        if (partial.getAmountPlan()   == null) partial.setAmountPlan(BigDecimal.ZERO);

        // 返回
        GysJhUndeliveredVO vo = new GysJhUndeliveredVO();
        vo.setUndelivered(undelivered);
        vo.setPartialUndelivered(partial);
        return vo;
    }

    @Override
    public List<WlTypeStockStatVO> getCurrentStockByWlType() {
        List<WlTypeStockStatVO> list = rkStatisticsMapper.selectCurrentStockByWlType();
        return list == null ? Collections.emptyList() : list;
    }

    @Override
    public RkTypePieVO getAgeGt30Summary() {
        RkTypePieVO vo = rkStatisticsMapper.selectAgeGt30Summary();
        if (vo == null) vo = new RkTypePieVO();

        // 兜底，避免前端拿到 null
        if (vo.getProjectCount() == null)    vo.setProjectCount(0);
        if (vo.getGoodsCountTotal() == null) vo.setGoodsCountTotal(0);
        if (vo.getSumQty() == null)          vo.setSumQty(BigDecimal.ZERO);
        if (vo.getSumAmount() == null)       vo.setSumAmount(BigDecimal.ZERO);

        // 本接口不设置 rkTypeCode / rkTypeName
        vo.setRkTypeCode(null);
        vo.setRkTypeName(null);
        return vo;
    }


    private static final DateTimeFormatter TS_FMT   = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DAY_FMT  = DateTimeFormatter.ofPattern("MM-dd");
    private static final DateTimeFormatter MON_FMT  = DateTimeFormatter.ofPattern("yyyy-MM");

    @Override
    public List<IOBucketVO> getIOBuckets(Integer range) {
        if (range == null || (range != 0 && range != 2)) {
            throw new IllegalArgumentException("range 仅支持 0(最近一周) 或 2(最近半年)");
        }

        Date now = DateUtils.getNowDate();
        LocalDateTime nowLdt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());

        if (range == 0) {
            // ===== 最近一周（按日），输出 MM-dd =====
            LocalDate endDay = nowLdt.toLocalDate();
            LocalDate startDay = endDay.minusDays(6);
            LocalDateTime startTs = startDay.atStartOfDay();
            LocalDateTime endTs = endDay.plusDays(1).atStartOfDay();

            List<RkInVO>  inRows  = rkStatisticsMapper.selectInRange(startTs.format(TS_FMT), endTs.format(TS_FMT));
            List<RkOutVO> outRows = rkStatisticsMapper.selectOutRange(startTs.format(TS_FMT), endTs.format(TS_FMT));

            // 改为以 LocalDate 作为桶键，防止键格式与输出格式不一致导致匹配失败
            LinkedHashMap<LocalDate, BucketAcc> acc = new LinkedHashMap<>();
            for (int i = 0; i < 7; i++) {
                LocalDate d = startDay.plusDays(i);
                acc.put(d, new BucketAcc());
            }

            // 入库聚合（按 LocalDate）
            for (RkInVO r : inRows) {
                if (r.getRkTime() == null) continue;
                LocalDate d = r.getRkTime().toLocalDate();
                BucketAcc b = acc.get(d);
                if (b == null) continue;
                b.inItemCount++;
                if (StringUtils.isNotBlank(r.getXmNo())) {
                    b.inProjects.add(r.getXmNo().trim());
                }
            }

            // 出库聚合（按 LocalDate；ly_time 优先，否则 update_time）
            for (RkOutVO r : outRows) {
                LocalDateTime t = (r.getLyTime() != null) ? r.getLyTime() : r.getUpdateTime();
                if (t == null) continue;
                LocalDate d = t.toLocalDate();
                BucketAcc b = acc.get(d);
                if (b == null) continue;
                b.outItemCount++;
                String proj = StringUtils.isNotBlank(r.getXmNoCk()) ? r.getXmNoCk().trim() : r.getXmNo();
                if (StringUtils.isNotBlank(proj)) b.outProjects.add(proj);
            }

            ArrayList<IOBucketVO> out = new ArrayList<>(7);
            for (Map.Entry<LocalDate, BucketAcc> e : acc.entrySet()) {
                IOBucketVO row = new IOBucketVO();
                row.setBucket(e.getKey().format(DAY_FMT)); // 仅返回 MM-dd
                row.setInProjectCount(e.getValue().inProjects.size());
                row.setInItemCount(e.getValue().inItemCount);
                row.setOutProjectCount(e.getValue().outProjects.size());
                row.setOutItemCount(e.getValue().outItemCount);
                out.add(row);
            }
            return out;

        } else {
            // ===== 最近半年（按月），输出 yyyy-MM =====
            YearMonth endYm = YearMonth.from(nowLdt.toLocalDate());
            YearMonth startYm = endYm.minusMonths(5);
            LocalDateTime startTs = startYm.atDay(1).atStartOfDay();
            LocalDateTime endTs = endYm.plusMonths(1).atDay(1).atStartOfDay();

            List<RkInVO>  inRows  = rkStatisticsMapper.selectInRange(startTs.format(TS_FMT), endTs.format(TS_FMT));
            List<RkOutVO> outRows = rkStatisticsMapper.selectOutRange(startTs.format(TS_FMT), endTs.format(TS_FMT));

            LinkedHashMap<YearMonth, BucketAcc> acc = new LinkedHashMap<>();
            for (int i = 0; i < 6; i++) {
                YearMonth ym = startYm.plusMonths(i);
                acc.put(ym, new BucketAcc());
            }

            // 入库按月
            for (RkInVO r : inRows) {
                if (r.getRkTime() == null) continue;
                YearMonth ym = YearMonth.from(r.getRkTime().toLocalDate());
                BucketAcc b = acc.get(ym);
                if (b == null) continue;
                b.inItemCount++;
                if (StringUtils.isNotBlank(r.getXmNo())) {
                    b.inProjects.add(r.getXmNo().trim());
                }
            }

            // 出库按月
            for (RkOutVO r : outRows) {
                LocalDateTime t = (r.getLyTime() != null) ? r.getLyTime() : r.getUpdateTime();
                if (t == null) continue;
                YearMonth ym = YearMonth.from(t.toLocalDate());
                BucketAcc b = acc.get(ym);
                if (b == null) continue;
                b.outItemCount++;
                String proj = StringUtils.isNotBlank(r.getXmNoCk()) ? r.getXmNoCk().trim() : r.getXmNo();
                if (StringUtils.isNotBlank(proj)) b.outProjects.add(proj);
            }

            ArrayList<IOBucketVO> out = new ArrayList<>(6);
            for (Map.Entry<YearMonth, BucketAcc> e : acc.entrySet()) {
                IOBucketVO row = new IOBucketVO();
                row.setBucket(e.getKey().format(MON_FMT)); // yyyy-MM
                row.setInProjectCount(e.getValue().inProjects.size());
                row.setInItemCount(e.getValue().inItemCount);
                row.setOutProjectCount(e.getValue().outProjects.size());
                row.setOutItemCount(e.getValue().outItemCount);
                out.add(row);
            }
            return out;
        }
    }

    /** 桶内累加器 */
    private static class BucketAcc {
        int inItemCount = 0;
        int outItemCount = 0;
        Set<String> inProjects = new HashSet<>();
        Set<String> outProjects = new HashSet<>();
    }


    @Override
    public List<SceneAvailableVO> listAvailableByWarehouse(String warehouseCode) {
        List<SceneAvailableVO> list = rkStatisticsMapper.selectAvailableByWarehouse(warehouseCode);

        if (list == null || list.isEmpty()) {
            // 没有查到任何数据时，返回一个默认对象
            SceneAvailableVO vo = new SceneAvailableVO();
//            vo.setSceneCode("N/A");           // 默认场景编码
//            vo.setSceneName("无可用场景");     // 默认场景名称
            vo.setAvailableCount(0);          // 可用数量为0
            vo.setPositions(new ArrayList<>()); // 空数组

            list = new ArrayList<>();
            list.add(vo);
        } else {
            // 保证 positions 不为 null
            for (SceneAvailableVO vo : list) {
                if (vo.getPositions() == null) {
                    vo.setPositions(new ArrayList<>());
                }
            }
        }
        return list;
    }
}
