package com.ruoyi.clock.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.clock.domain.ClockProductRecord;
import com.ruoyi.clock.domain.bo.ActivityClockRecordBo;
import com.ruoyi.clock.domain.bo.ActivityShopSaleBo;
import com.ruoyi.clock.domain.bo.AnalysisQueryBo;
import com.ruoyi.clock.domain.bo.ClockCalendarBo;
import com.ruoyi.clock.domain.bo.ClockProductRecordBo;
import com.ruoyi.clock.domain.bo.SaleStatisticBo;
import com.ruoyi.clock.domain.vo.*;
import com.ruoyi.clock.enums.ClockStatusEnum;
import com.ruoyi.clock.exception.ClockRecordExceptionEnum;
import com.ruoyi.clock.mapper.ClockProductRecordMapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.clock.domain.bo.ClockRecordBo;
import com.ruoyi.clock.domain.ClockRecord;
import com.ruoyi.clock.mapper.ClockRecordMapper;
import com.ruoyi.clock.service.IClockRecordService;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 打卡记录信息Service业务层处理
 *
 * @author pengc
 * @date 2026-03-04
 */
@RequiredArgsConstructor
@Service
public class ClockRecordServiceImpl implements IClockRecordService {

    private final ClockRecordMapper baseMapper;
    private final ClockProductRecordMapper clockProductRecordMapper;

    /**
     * 查询打卡记录信息分页
     *
     * @param bo 打卡记录信息
     * @return 打卡记录信息
     */
    @Override
    public TableDataInfo<ClockRecordVo> queryPageList(ClockRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ClockRecord> lqw = buildQueryWrapper(bo);
        Page<ClockRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询打卡记录信息列表
     *
     * @param bo 打卡记录信息
     * @return 打卡记录信息
     */
    @Override
    public List<ClockRecordVo> queryList(ClockRecordBo bo) {
        LambdaQueryWrapper<ClockRecord> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ClockRecord> buildQueryWrapper(ClockRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ClockRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getActivityId() != null, ClockRecord::getActivityId, bo.getActivityId());
        lqw.eq(bo.getEmployeeId() != null, ClockRecord::getEmployeeId, bo.getEmployeeId());
        lqw.eq(bo.getClockDate() != null, ClockRecord::getClockDate, bo.getClockDate());
        lqw.eq(StringUtils.isNotBlank(bo.getScreenshot()), ClockRecord::getScreenshot, bo.getScreenshot());
        lqw.eq(bo.getStatus() != null, ClockRecord::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 查询打卡记录信息
     *
     * @param recordId 打卡记录信息主键
     * @return 打卡记录信息
     */
    @Override
    public ClockRecordVo queryById(Long recordId){
        return baseMapper.selectVoById(recordId);
    }

    /**
     * 详情打卡记录信息
     *
     * @param recordId 打卡记录信息主键
     * @return 打卡记录信息
     */
    @Override
    public ClockRecord loadById(Long recordId, Boolean tw){
        ClockRecord info = this.baseMapper.selectById(recordId);
        if(ObjectUtil.isEmpty(info) && tw){
            throw new ServiceException(ClockRecordExceptionEnum.ClockRecord_IS_NOT_EXISTS);
        }
        return info;
    }

    /**
     * 新增打卡记录信息
     *
     * @param bo 打卡记录信息
     * @return 结果
     */
    @Override
    public Boolean insertByBo(ClockRecordBo bo) {
        ClockRecord add = BeanUtil.toBean(bo, ClockRecord.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRecordId(add.getRecordId());
        }
        return flag;
    }

    /**
     * 修改打卡记录信息
     *
     * @param bo 打卡记录信息
     * @return 结果
     */
    @Override
    public Boolean updateByBo(ClockRecordBo bo) {
        ClockRecord clockRecord = baseMapper.selectById(bo.getRecordId());
        ClockRecord update = BeanCopyUtils.copy(bo, clockRecord);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(ClockRecord entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除打卡记录信息
     *
     * @param ids 需要删除的打卡记录信息主键
     * @return 结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Long queryClockCount(Long activityId, Long employeeId) {
        LambdaQueryWrapper<ClockRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(ClockRecord::getActivityId, activityId);
        lqw.eq(ClockRecord::getEmployeeId, employeeId);
        return this.baseMapper.selectCount(lqw);
    }

    @Override
    public ClockStatisticRecordVo queryClockStatisticRecord(Long employeeId) {
        return this.baseMapper.queryClockStatisticRecord(employeeId);
    }

    @Override
    public List<SaleStatisticRecordVo> querySaleStatisticRecordList(SaleStatisticBo bo) {
        return this.baseMapper.querySaleStatisticRecordList(bo);
    }

    @Override
    public MySaleStatisticRecordVo mySaleRank(SaleStatisticBo bo) {
        return this.baseMapper.mySaleRank(bo);
    }

    @Override
    public MyActivityStatisticVo myActivityStatistic(SaleStatisticBo bo) {
        return this.baseMapper.myActivityStatistic(bo);
    }

    @Override
    public TableDataInfo<ActivityClockRecordVo> queryActivityClockRecordPage(ActivityClockRecordBo bo, PageQuery pageQuery) {
        Page<ActivityClockRecordVo> page = baseMapper.queryActivityClockRecordPage(pageQuery.build(), bo);
        return TableDataInfo.build(page);
    }

    @Override
    public ActivityClockStatisticVo queryActivityClockStatistic(ActivityClockRecordBo bo) {
        return baseMapper.queryActivityClockStatistic(bo);
    }

    @Override
    public Boolean invalidateEmployeeClock(Long activityId, Long employeeId) {
        ClockRecord update = new ClockRecord();
        update.setStatus(ClockStatusEnum.EXPIRE.getCode()); // 设为失效
        return baseMapper.update(update,
            Wrappers.<ClockRecord>lambdaUpdate()
                .eq(ClockRecord::getActivityId, activityId)
                .eq(ClockRecord::getEmployeeId, employeeId)
                .eq(ClockRecord::getStatus, ClockStatusEnum.NORMAL.getCode()) // 只更新有效的记录
        ) > 0;
    }

    @Override
    public TableDataInfo<ActivityShopSaleVo> queryActivityShopSalePage(ActivityShopSaleBo bo, PageQuery pageQuery) {
        Page<ActivityShopSaleVo> page = baseMapper.queryActivityShopSalePage(pageQuery.build(), bo);
        return TableDataInfo.build(page);
    }

    @Override
    public DashboardStatisticVo queryDashboardStatistic() {
        return baseMapper.queryDashboardStatistic();
    }

    @Override
    public List<AgentRankVo> queryYesterdayAgentRank() {
        return baseMapper.queryYesterdayAgentRank();
    }

    @Override
    public List<ShopRankVo> queryYesterdayShopRank() {
        return baseMapper.queryYesterdayShopRank();
    }

    @Override
    public AnalysisOverviewVo queryAnalysisOverview() {
        return baseMapper.queryAnalysisOverview();
    }

    @Override
    public List<ShopActivityRankVo> queryShopActivityRank(AnalysisQueryBo bo) {
        return baseMapper.queryShopActivityRank(bo);
    }

    @Override
    public List<TrendVo> queryTrend(AnalysisQueryBo bo) {
        return baseMapper.queryTrend(bo);
    }

    @Override
    public List<MonthlyComparisonVo> queryMonthlyComparison(AnalysisQueryBo bo) {
        return baseMapper.queryMonthlyComparison(bo);
    }

    @Override
    public List<ShopSalesRankVo> queryShopSalesRank() {
        List<ShopSalesRankVo> list = baseMapper.queryShopSalesRank();
        // 设置排名
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setRank(i + 1);
        }
        return list;
    }

    /**
     * 查询打卡日历（按年月，标注每天打卡状态及详情）
     */
    @Override
    public List<ClockCalendarDayVo> queryCalendar(ClockCalendarBo bo, Long employeeId) {
        // 查询该月所有打卡记录
        List<ClockRecord> recordList = baseMapper.selectList(
            Wrappers.<ClockRecord>lambdaQuery()
                .eq(ClockRecord::getActivityId, bo.getActivityId())
                .eq(ClockRecord::getEmployeeId, employeeId)
                .eq(ClockRecord::getStatus, ClockStatusEnum.NORMAL.getCode())
                .apply("DATE_FORMAT(clock_date, '%Y-%m') = {0}",
                    String.format("%04d-%02d", bo.getYear(), bo.getMonth()))
        );

        // 以日期字符串为 key 建立 map，方便快速查找
        Map<String, ClockRecord> recordMap = new java.util.LinkedHashMap<>();
        for (ClockRecord r : recordList) {
            if (r.getClockDate() != null) {
                String key = new java.text.SimpleDateFormat("yyyy-MM-dd").format(r.getClockDate());
                recordMap.put(key, r);
            }
        }

        // 批量查询本月有打卡的产品记录
        Map<Long, List<ClockProductRecordVo>> productMap = new java.util.HashMap<>();
        if (!recordList.isEmpty()) {
            List<Long> recordIds = new java.util.ArrayList<>();
            for (ClockRecord r : recordList) {
                recordIds.add(r.getRecordId());
            }
            List<ClockProductRecord> products = clockProductRecordMapper.selectList(
                Wrappers.<ClockProductRecord>lambdaQuery()
                    .in(ClockProductRecord::getRecordId, recordIds)
            );
            for (ClockProductRecord p : products) {
                productMap.computeIfAbsent(p.getRecordId(), k -> new java.util.ArrayList<>())
                    .add(cn.hutool.core.bean.BeanUtil.toBean(p, ClockProductRecordVo.class));
            }
        }

        // 枚举本月所有天，组装日历列表
        java.time.YearMonth yearMonth = java.time.YearMonth.of(bo.getYear(), bo.getMonth());
        int daysInMonth = yearMonth.lengthOfMonth();
        List<ClockCalendarDayVo> result = new java.util.ArrayList<>(daysInMonth);

        java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int day = 1; day <= daysInMonth; day++) {
            java.time.LocalDate localDate = java.time.LocalDate.of(bo.getYear(), bo.getMonth(), day);
            String dateStr = localDate.format(formatter);
            java.util.Date date = java.util.Date.from(localDate.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant());

            ClockCalendarDayVo dayVo = new ClockCalendarDayVo();
            dayVo.setDate(date);

            ClockRecord record = recordMap.get(dateStr);
            if (record != null) {
                dayVo.setClocked(true);
                dayVo.setRecordId(record.getRecordId());
                dayVo.setScreenshot(record.getScreenshot());
                dayVo.setClockDate(record.getClockDate());
                dayVo.setProductList(productMap.getOrDefault(record.getRecordId(), java.util.Collections.emptyList()));
            } else {
                dayVo.setClocked(false);
            }
            result.add(dayVo);
        }
        return result;
    }

    /**
     * 打卡（每天只能打卡一次，已打卡则更新）
     * 支持晒单打卡（activityType=0）和销量打卡（activityType=1，需传 productList）
     *
     * @param bo         打卡记录信息（含 productList 用于销量打卡）
     * @param employeeId 员工id
     * @return 打卡记录id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long submitClock(ClockRecordBo bo, Long employeeId) {
        bo.setEmployeeId(employeeId);

        // 今日日期
        LocalDate today = LocalDate.now();
        String todayStr = today.toString(); // yyyy-MM-dd

        // 查询当天是否已打卡
        ClockRecord existing = baseMapper.selectOne(
            Wrappers.<ClockRecord>lambdaQuery()
                .eq(ClockRecord::getActivityId, bo.getActivityId())
                .eq(ClockRecord::getEmployeeId, employeeId)
                .apply("DATE(clock_date) = {0}", todayStr)
                .last("limit 1")
        );

        Long recordId;
        if (ObjectUtil.isNotNull(existing)) {
            // 今天已打卡 → 更新打卡记录
            existing.setScreenshot(bo.getScreenshot());
            existing.setClockDate(bo.getClockDate() != null ? bo.getClockDate() : new Date());
            baseMapper.updateById(existing);
            recordId = existing.getRecordId();

            // 销量打卡：删除旧产品记录再重新插入
            if (CollUtil.isNotEmpty(bo.getProductList())) {
                clockProductRecordMapper.delete(
                    Wrappers.<ClockProductRecord>lambdaQuery()
                        .eq(ClockProductRecord::getRecordId, recordId)
                );
                for (ClockProductRecordBo productBo : bo.getProductList()) {
                    ClockProductRecord productRecord = BeanUtil.toBean(productBo, ClockProductRecord.class);
                    productRecord.setRecordId(recordId);
                    clockProductRecordMapper.insert(productRecord);
                }
            }
        } else {
            // 今天未打卡 → 新增打卡记录
            ClockRecord add = BeanUtil.toBean(bo, ClockRecord.class);
            add.setEmployeeId(employeeId);
            if (add.getClockDate() == null) {
                add.setClockDate(new Date());
            }
            add.setStatus(ClockStatusEnum.NORMAL.getCode());
            baseMapper.insert(add);
            recordId = add.getRecordId();

            // 销量打卡：插入产品记录
            if (CollUtil.isNotEmpty(bo.getProductList())) {
                for (ClockProductRecordBo productBo : bo.getProductList()) {
                    ClockProductRecord productRecord = BeanUtil.toBean(productBo, ClockProductRecord.class);
                    productRecord.setRecordId(recordId);
                    clockProductRecordMapper.insert(productRecord);
                }
            }
        }

        return recordId;
    }
}
