package com.cool.modules.dailyreport.service.impl;

import com.cool.core.base.BaseServiceImpl;
import com.cool.modules.dailyreport.entity.DailyReportEntity;
import com.cool.modules.dailyreport.mapper.DailyReportMapper;
import com.cool.modules.dailyreport.service.DailyReportService;
import com.cool.modules.user.service.UserInfoService;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 日报服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DailyReportServiceImpl
        extends BaseServiceImpl<DailyReportMapper, DailyReportEntity>
        implements DailyReportService {

    private final UserInfoService userInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DailyReportEntity saveDraft(DailyReportEntity entity) {
        log.info("【日报服务】保存草稿, userId: {}, reportDate: {}", entity.getUserId(), entity.getReportDate());

        try {
            // 检查是否已存在该用户当天的日报
            DailyReportEntity existing = getByUserIdAndDate(entity.getUserId(), entity.getReportDate());

            if (existing != null) {
                // 更新已有日报
                log.info("【日报服务】更新已有草稿, id: {}", existing.getId());
                entity.setId(existing.getId());
                entity.setStatus(0); // 草稿状态
                entity.setSubmitTime(null); // 清空提交时间
                this.updateById(entity);
                log.info("【日报服务】草稿更新成功, id: {}", entity.getId());
            } else {
                // 新增日报
                entity.setStatus(0); // 草稿状态
                entity.setSubmitTime(null);
                this.save(entity);
                log.info("【日报服务】草稿保存成功, id: {}", entity.getId());
            }

            return entity;

        } catch (Exception e) {
            log.error("【日报服务】保存草稿失败", e);
            throw new RuntimeException("保存草稿失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DailyReportEntity submitReport(DailyReportEntity entity) {
        log.info("【日报服务】提交日报, userId: {}, reportDate: {}", entity.getUserId(), entity.getReportDate());

        try {
            // 验证内容不能为空
            if (entity.getUserEditedContent() == null || entity.getUserEditedContent().trim().isEmpty()) {
                log.error("【日报服务】提交失败：日报内容为空");
                throw new RuntimeException("日报内容不能为空");
            }

            // 检查是否已存在该用户当天的日报
            DailyReportEntity existing = getByUserIdAndDate(entity.getUserId(), entity.getReportDate());

            if (existing != null) {
                // 更新已有日报
                log.info("【日报服务】更新已有日报并提交, id: {}", existing.getId());
                entity.setId(existing.getId());
            }

            // 设置提交状态和时间
            entity.setStatus(1); // 已提交
            entity.setSubmitTime(LocalDateTime.now());

            if (entity.getId() != null) {
                this.updateById(entity);
            } else {
                this.save(entity);
            }

            log.info("【日报服务】日报提交成功, id: {}, submitTime: {}", entity.getId(), entity.getSubmitTime());
            return entity;

        } catch (Exception e) {
            log.error("【日报服务】提交日报失败", e);
            throw new RuntimeException("提交日报失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DailyReportEntity updateReport(DailyReportEntity entity) {
        log.info("【日报服务】更新日报, id: {}, userId: {}", entity.getId(), entity.getUserId());

        try {
            if (entity.getId() == null) {
                log.error("【日报服务】更新失败：日报ID为空");
                throw new RuntimeException("日报ID不能为空");
            }

            // 验证日报是否存在
            DailyReportEntity existing = this.getById(entity.getId());
            if (existing == null) {
                log.error("【日报服务】更新失败：日报不存在, id: {}", entity.getId());
                throw new RuntimeException("日报不存在");
            }

            // 验证用户权限（只能更新自己的日报）
            if (!existing.getUserId().equals(entity.getUserId())) {
                log.error("【日报服务】更新失败：无权限, userId: {}, ownerId: {}", entity.getUserId(), existing.getUserId());
                throw new RuntimeException("无权限更新此日报");
            }

            // 更新日报
            this.updateById(entity);
            log.info("【日报服务】日报更新成功, id: {}", entity.getId());

            return entity;

        } catch (Exception e) {
            log.error("【日报服务】更新日报失败", e);
            throw new RuntimeException("更新日报失败: " + e.getMessage());
        }
    }

    @Override
    public DailyReportEntity getByUserIdAndDate(Long userId, LocalDate reportDate) {
        log.info("【日报服务】查询用户日报, userId: {}, reportDate: {}", userId, reportDate);

        try {
            QueryWrapper qw = QueryWrapper.create()
                    .eq(DailyReportEntity::getUserId, userId)
                    .eq(DailyReportEntity::getReportDate, reportDate);

            DailyReportEntity entity = this.getOne(qw);

            if (entity != null) {
                log.info("【日报服务】查询成功, id: {}, status: {}", entity.getId(), entity.getStatus());
            } else {
                log.info("【日报服务】未找到该日期的日报");
            }

            return entity;

        } catch (Exception e) {
            log.error("【日报服务】查询用户日报失败", e);
            throw new RuntimeException("查询用户日报失败: " + e.getMessage());
        }
    }

    @Override
    public List<DailyReportEntity> getUserReports(Long userId, LocalDate startDate, LocalDate endDate, Integer status) {
        log.info("【日报服务】查询用户日报列表, userId: {}, startDate: {}, endDate: {}, status: {}",
                userId, startDate, endDate, status);

        try {
            QueryWrapper qw = QueryWrapper.create()
                    .eq(DailyReportEntity::getUserId, userId);

            // 添加可选条件
            if (startDate != null) {
                qw.ge(DailyReportEntity::getReportDate, startDate);
            }
            if (endDate != null) {
                qw.le(DailyReportEntity::getReportDate, endDate);
            }
            if (status != null) {
                qw.eq(DailyReportEntity::getStatus, status);
            }

            qw.orderBy(DailyReportEntity::getReportDate, false); // 按日期倒序

            List<DailyReportEntity> list = this.list(qw);
            log.info("【日报服务】查询成功, 数量: {}", list.size());

            return list;

        } catch (Exception e) {
            log.error("【日报服务】查询用户日报列表失败", e);
            throw new RuntimeException("查询用户日报列表失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getStatistics(LocalDate startDate, LocalDate endDate) {
        log.info("【日报服务】获取统计信息, startDate: {}, endDate: {}", startDate, endDate);

        try {
            Map<String, Object> result = new HashMap<>();

            // 查询指定时间范围内的日报
            QueryWrapper qw = QueryWrapper.create();
            if (startDate != null) {
                qw.ge(DailyReportEntity::getReportDate, startDate);
            }
            if (endDate != null) {
                qw.le(DailyReportEntity::getReportDate, endDate);
            }

            List<DailyReportEntity> reports = this.list(qw);

            // 统计已提交数量
            long submittedCount = reports.stream()
                    .filter(r -> r.getStatus() == 1)
                    .count();

            // 统计草稿数量
            long draftCount = reports.stream()
                    .filter(r -> r.getStatus() == 0)
                    .count();

            // 统计总用户数
            long totalUserCount = userInfoService.count();

            // 计算提交率（假设每天每人应提交一篇日报）
            long daysBetween = endDate != null && startDate != null
                    ? java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate) + 1
                    : 1;
            long expectedSubmissions = totalUserCount * daysBetween;
            double submissionRate = expectedSubmissions > 0
                    ? (double) submittedCount / expectedSubmissions * 100
                    : 0;

            result.put("totalReports", reports.size());
            result.put("submittedCount", submittedCount);
            result.put("draftCount", draftCount);
            result.put("totalUserCount", totalUserCount);
            result.put("expectedSubmissions", expectedSubmissions);
            result.put("submissionRate", String.format("%.2f%%", submissionRate));

            log.info("【日报服务】统计完成: {}", result);
            return result;

        } catch (Exception e) {
            log.error("【日报服务】获取统计信息失败", e);
            throw new RuntimeException("获取统计信息失败: " + e.getMessage());
        }
    }

    @Override
    public List<Long> getUnsubmittedUserIds(LocalDate reportDate) {
        log.info("【日报服务】获取未提交人员列表, reportDate: {}", reportDate);

        try {
            // 查询所有用户ID
            List<Long> allUserIds = userInfoService.list()
                    .stream()
                    .map(user -> user.getId())
                    .toList();

            // 查询已提交的用户ID
            QueryWrapper qw = QueryWrapper.create()
                    .eq(DailyReportEntity::getReportDate, reportDate)
                    .eq(DailyReportEntity::getStatus, 1); // 只统计已提交的

            List<Long> submittedUserIds = this.list(qw)
                    .stream()
                    .map(DailyReportEntity::getUserId)
                    .toList();

            // 计算未提交的用户ID
            List<Long> unsubmittedUserIds = allUserIds.stream()
                    .filter(userId -> !submittedUserIds.contains(userId))
                    .toList();

            log.info("【日报服务】未提交人员数量: {}", unsubmittedUserIds.size());
            return unsubmittedUserIds;

        } catch (Exception e) {
            log.error("【日报服务】获取未提交人员列表失败", e);
            throw new RuntimeException("获取未提交人员列表失败: " + e.getMessage());
        }
    }
}
