package com.mosquito.project.service;

import com.mosquito.project.persistence.entity.UserRewardEntity;
import com.mosquito.project.persistence.repository.UserRewardRepository;
import com.mosquito.project.persistence.repository.ActivityRepository;
import com.mosquito.project.permission.ApprovalFlowService;
import com.mosquito.project.permission.PermissionCheckService;
import org.springframework.context.annotation.Lazy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 奖励管理服务
 * PRD要求: 按金额分级审批（业务流程细化版）
 * - <1000: 自动发放
 * - 1000-9999: 风控审批
 * - 10000-49999: 风控+财务审批
 * - >=50000: 风控+财务+总监三级审批
 */
@Service
public class RewardService {

    private static final Logger log = LoggerFactory.getLogger(RewardService.class);

    // 分级审批阈值（按业务流程文档）
    public static final int THRESHOLD_AUTO = 1000;
    public static final int THRESHOLD_RISK = 10000;
    public static final int THRESHOLD_DIRECTOR = 50000;  // 新增：总监审批阈值

    // 审批类型
    public static final String APPROVAL_TYPE_AUTO = "AUTO";           // 自动发放
    public static final String APPROVAL_TYPE_RISK = "RISK";          // 风控审批（单级）
    public static final String APPROVAL_TYPE_RISK_FINANCE = "RISK_FINANCE"; // 风控+财务审批（两级）
    public static final String APPROVAL_TYPE_RISK_FINANCE_DIRECTOR = "RISK_FINANCE_DIRECTOR"; // 风控+财务+总监审批（三级）

    // 奖励状态常量
    public static final String STATUS_PENDING = "PENDING";           // 待审批
    public static final String STATUS_APPROVED = "APPROVED";         // 审批通过
    public static final String STATUS_REJECTED = "REJECTED";         // 审批拒绝
    public static final String STATUS_GRANTED = "GRANTED";           // 已发放
    public static final String STATUS_CANCELLED = "CANCELLED";       // 已取消

    // 业务类型常量
    public static final String BIZ_TYPE_REWARD = "REWARD_APPLY";     // 奖励申请业务类型

    private final UserRewardRepository userRewardRepository;
    private final ActivityRepository activityRepository;
    private final PermissionCheckService permissionCheckService;
    private final ApprovalFlowService approvalFlowService;

    public RewardService(UserRewardRepository userRewardRepository,
                         ActivityRepository activityRepository,
                         PermissionCheckService permissionCheckService,
                         @Lazy ApprovalFlowService approvalFlowService) {
        this.userRewardRepository = userRewardRepository;
        this.activityRepository = activityRepository;
        this.permissionCheckService = permissionCheckService;
        this.approvalFlowService = approvalFlowService;
    }

    /**
     * 根据金额获取审批类型
     */
    public static String getApprovalType(int points) {
        if (points < THRESHOLD_AUTO) {
            return APPROVAL_TYPE_AUTO;
        } else if (points < THRESHOLD_RISK) {
            return APPROVAL_TYPE_RISK;
        } else if (points < THRESHOLD_DIRECTOR) {
            return APPROVAL_TYPE_RISK_FINANCE;
        } else {
            return APPROVAL_TYPE_RISK_FINANCE_DIRECTOR;
        }
    }

    /**
     * 获取审批类型对应的审批级别数量
     */
    public static int getApprovalLevelCount(String approvalType) {
        if (APPROVAL_TYPE_AUTO.equals(approvalType)) {
            return 0;
        } else if (APPROVAL_TYPE_RISK.equals(approvalType)) {
            return 1;
        } else if (APPROVAL_TYPE_RISK_FINANCE.equals(approvalType)) {
            return 2;
        } else if (APPROVAL_TYPE_RISK_FINANCE_DIRECTOR.equals(approvalType)) {
            return 3;
        }
        return 0;
    }

    /**
     * 获取奖励列表（带数据权限过滤）
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getRewards(Integer page, Integer size, String status, String rewardType, Long currentUserId) {
        int pageNum = page != null && page > 0 ? page - 1 : 0;
        int pageSize = size != null && size > 0 ? size : 10;
        Pageable pageable = PageRequest.of(pageNum, pageSize, Sort.by(Sort.Direction.DESC, "createdAt"));

        Page<UserRewardEntity> rewardPage;

        // 数据权限过滤
        if (currentUserId != null) {
            String dataScope = permissionCheckService.getUserDataScope(currentUserId);

            if ("ALL".equals(dataScope)) {
                // 全部数据权限，不过滤
                if (status != null && !status.isEmpty()) {
                    rewardPage = userRewardRepository.findByStatus(status, pageable);
                } else if (rewardType != null && !rewardType.isEmpty()) {
                    rewardPage = userRewardRepository.findByType(rewardType, pageable);
                } else {
                    rewardPage = userRewardRepository.findAll(pageable);
                }
            } else if ("DEPARTMENT".equals(dataScope)) {
                // 部门数据权限
                List<Long> deptIds = permissionCheckService.getUserDepartmentAndChildIds(currentUserId);
                if (status != null && !status.isEmpty()) {
                    rewardPage = userRewardRepository.findByDepartmentIdInAndStatus(deptIds, status, pageable);
                } else if (rewardType != null && !rewardType.isEmpty()) {
                    rewardPage = userRewardRepository.findByDepartmentIdInAndType(deptIds, rewardType, pageable);
                } else {
                    rewardPage = userRewardRepository.findByDepartmentIdIn(deptIds, pageable);
                }
            } else {
                // 个人数据权限 (OWN)
                if (status != null && !status.isEmpty()) {
                    rewardPage = userRewardRepository.findByUserIdAndStatusWithScope(currentUserId, status, pageable);
                } else if (rewardType != null && !rewardType.isEmpty()) {
                    rewardPage = userRewardRepository.findByUserIdAndTypeWithScope(currentUserId, rewardType, pageable);
                } else {
                    rewardPage = userRewardRepository.findByUserIdWithScope(currentUserId, pageable);
                }
            }
        } else {
            // 无用户ID时返回全部（保守策略）
            if (status != null && !status.isEmpty()) {
                rewardPage = userRewardRepository.findByStatus(status, pageable);
            } else if (rewardType != null && !rewardType.isEmpty()) {
                rewardPage = userRewardRepository.findByType(rewardType, pageable);
            } else {
                rewardPage = userRewardRepository.findAll(pageable);
            }
        }

        List<Map<String, Object>> rewards = rewardPage.getContent().stream()
                .map(this::convertToMap)
                .toList();

        Map<String, Object> result = new HashMap<>();
        result.put("data", rewards);
        result.put("total", rewardPage.getTotalElements());
        result.put("page", pageNum + 1);
        result.put("size", pageSize);
        result.put("totalPages", rewardPage.getTotalPages());

        return result;
    }

    /**
     * 获取奖励详情
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getRewardById(Long id) {
        return userRewardRepository.findById(id)
                .map(this::convertToMap)
                .orElse(null);
    }

    /**
     * 申请奖励 - 根据金额自动判定审批流程
     * PRD要求:
     * - <1000: 自动发放
     * - 1000-9999: 风控审批
     * - 10000-49999: 风控+财务审批
     * - >=50000: 风控+财务+总监三级审批
     */
    @Transactional
    public Long applyReward(Map<String, Object> request) {
        int points = getIntValue(request, "points", 0);
        Long applicantId = getLongValue(request, "applicantId");
        String approvalType = getApprovalType(points);
        int requiredLevels = getApprovalLevelCount(approvalType);

        UserRewardEntity reward = new UserRewardEntity();
        Long activityId = getLongValue(request, "activityId");
        reward.setActivityId(activityId);
        reward.setUserId(getLongValue(request, "userId"));
        reward.setType(getStringValue(request, "type", "POINTS"));
        reward.setPoints(points);
        reward.setCreatedAt(OffsetDateTime.now(ZoneOffset.ofHours(8)));

        // 从活动获取部门ID，用于数据权限过滤
        if (activityId != null) {
            activityRepository.findById(activityId).ifPresent(activity -> {
                reward.setDepartmentId(activity.getDepartmentId());
                log.debug("设置奖励departmentId={} from activityId={}", activity.getDepartmentId(), activityId);
            });
        }

        // 设置审批相关信息
        reward.setApprovalType(approvalType);
        reward.setCurrentApprovalLevel(0);
        reward.setRequiredApprovalLevels(requiredLevels);

        // 根据审批类型设置初始状态
        if (APPROVAL_TYPE_AUTO.equals(approvalType)) {
            // 小于阈值，自动发放（状态为GRANTED表示已发放完成）
            reward.setStatus(STATUS_GRANTED);
            log.info("奖励自动通过并发放: points={}, approvalType={}", points, approvalType);
            // 自动发放需要保存奖励记录
            UserRewardEntity saved = userRewardRepository.save(reward);
            log.info("奖励自动发放成功: rewardId={}, points={}", saved.getId(), points);
            return saved.getId();
        } else {
            // 需要审批，调用审批流服务
            reward.setStatus(STATUS_PENDING);
            log.info("奖励需要审批: points={}, approvalType={}, requiredLevels={}", points, approvalType, requiredLevels);

            try {
                // 先保存奖励记录获取ID
                UserRewardEntity saved = userRewardRepository.save(reward);

                // 根据审批类型选择不同的流程模板
                String triggerEvent = getTriggerEventByApprovalType(approvalType);
                String title = String.format("奖励申请审批 - %d积分 - %s", points, getApprovalLevelName(0));

                // 提交审批申请，使用真实的reward ID作为bizId
                Map<String, Object> approvalResult = approvalFlowService.submitApprovalByEvent(
                    triggerEvent,
                    BIZ_TYPE_REWARD,
                    saved.getId(), // 使用真实的reward ID作为bizId
                    title,
                    applicantId,
                    getStringValue(request, "applyReason", "申请奖励")
                );

                // 更新审批记录ID
                Long recordId = (Long) approvalResult.get("recordId");
                reward.setApprovalRecordId(recordId);
                userRewardRepository.save(reward);

                log.info("奖励审批流程已创建: rewardId={}, approvalRecordId={}, bizId={}", saved.getId(), recordId, saved.getId());
                return saved.getId();

            } catch (Exception e) {
                log.error("创建审批流程失败，拒绝执行敏感操作: points={}, error={}", points, e.getMessage());
                // 审批流程创建失败时，拒绝执行敏感操作（Fail-Closed）
                throw new RuntimeException("审批服务不可用，无法执行敏感操作，请稍后重试");
            }
        }
    }

    /**
     * 根据审批类型获取触发事件
     */
    private String getTriggerEventByApprovalType(String approvalType) {
        if (APPROVAL_TYPE_RISK.equals(approvalType)) {
            return "REWARD_RISK_APPROVAL";
        } else if (APPROVAL_TYPE_RISK_FINANCE.equals(approvalType)) {
            return "REWARD_RISK_FINANCE_APPROVAL";
        } else if (APPROVAL_TYPE_RISK_FINANCE_DIRECTOR.equals(approvalType)) {
            return "REWARD_RISK_FINANCE_DIRECTOR_APPROVAL";
        }
        return "REWARD_APPLY";
    }

    /**
     * 获取审批级别名称
     */
    private String getApprovalLevelName(int level) {
        return switch (level) {
            case 0 -> "风控审批";
            case 1 -> "财务审批";
            case 2 -> "总监审批";
            default -> "未知审批";
        };
    }

    /**
     * 审批奖励 - 支持多级审批推进
     * @param currentUserId 当前登录用户ID，从登录态获取，禁止伪造
     * @return 审批结果，包含是否完成整个审批流程
     */
    @Transactional
    public Map<String, Object> approveReward(Long id, Map<String, Object> request, Long currentUserId) {
        Map<String, Object> result = new HashMap<>();

        UserRewardEntity reward = userRewardRepository.findById(id).orElse(null);
        if (reward == null) {
            result.put("success", false);
            result.put("message", "奖励记录不存在");
            return result;
        }

        String action = getStringValue(request, "action", "approve");
        // 强制使用当前登录用户ID，禁止从请求体中获取以防止伪造
        Long operatorId = currentUserId;
        String comment = getStringValue(request, "comment", "");

        // 如果有审批记录ID，调用审批流服务处理
        if (reward.getApprovalRecordId() != null) {
            try {
                String approvalAction = "approve".equals(action) ?
                    ApprovalFlowService.ACTION_APPROVE : ApprovalFlowService.ACTION_REJECT;

                Map<String, Object> approvalResult = approvalFlowService.handleApproval(
                    reward.getApprovalRecordId(),
                    approvalAction,
                    operatorId,
                    comment
                );

                String approvalStatus = (String) approvalResult.get("status");

                if (ApprovalFlowService.STATUS_REJECTED.equals(approvalStatus)) {
                    // 审批拒绝
                    reward.setStatus(STATUS_REJECTED);
                    userRewardRepository.save(reward);
                    result.put("success", true);
                    result.put("completed", true);
                    result.put("message", "审批已拒绝");
                    result.put("status", STATUS_REJECTED);
                } else if (ApprovalFlowService.STATUS_APPROVED.equals(approvalStatus)) {
                    // 审批通过（多级审批全部完成），状态变为APPROVED等待发放
                    // 注意：不再自动发放，由人工确认后调用grantReward发放
                    reward.setStatus(STATUS_APPROVED);
                    reward.setCurrentApprovalLevel(reward.getRequiredApprovalLevels());
                    userRewardRepository.save(reward);
                    result.put("success", true);
                    result.put("completed", true);
                    result.put("message", "审批已通过，等待发放");
                    result.put("status", STATUS_APPROVED);
                } else {
                    // 审批处理中（多级审批还有后续级别）
                    int currentLevel = reward.getCurrentApprovalLevel();
                    reward.setCurrentApprovalLevel(currentLevel + 1);
                    userRewardRepository.save(reward);
                    result.put("success", true);
                    result.put("completed", false);
                    result.put("message", "已提交给下一审批人: " + getApprovalLevelName(currentLevel + 1));
                    result.put("currentLevel", currentLevel + 1);
                    result.put("status", STATUS_PENDING);
                }
                return result;

            } catch (Exception e) {
                log.error("审批流服务调用失败，拒绝执行敏感操作: rewardId={}, error={}", id, e.getMessage());
                // 审批流服务调用失败，拒绝执行敏感操作（Fail-Closed）
                result.put("success", false);
                result.put("message", "审批服务不可用，无法执行敏感操作，请稍后重试");
                return result;
            }
        }

        // 如果没有审批服务，拒绝执行（Fail-Closed原则）
        result.put("success", false);
        result.put("message", "审批服务不可用，无法执行敏感操作");
        return result;
    }

    /**
     * 审批奖励（简化版，返回boolean）
     */
    @Transactional
    public boolean approveRewardSimple(Long id, Map<String, Object> request, Long currentUserId) {
        Map<String, Object> result = approveReward(id, request, currentUserId);
        return Boolean.TRUE.equals(result.get("success"));
    }

    /**
     * 拒绝奖励
     * 使用独立的 reward.index.reject.ALL 权限
     * @param id 奖励ID
     * @param request 请求体，包含comment等
     * @param currentUserId 当前登录用户ID，从登录态获取，禁止伪造
     * @return 拒绝结果
     */
    @Transactional
    public Map<String, Object> rejectReward(Long id, Map<String, Object> request, Long currentUserId) {
        Map<String, Object> result = new HashMap<>();

        UserRewardEntity reward = userRewardRepository.findById(id).orElse(null);
        if (reward == null) {
            result.put("success", false);
            result.put("message", "奖励记录不存在");
            return result;
        }

        // 强制使用当前登录用户ID，禁止从请求体中获取以防止伪造
        Long operatorId = currentUserId;
        String comment = getStringValue(request, "comment", "");

        // 如果有审批记录ID，调用审批流服务处理
        if (reward.getApprovalRecordId() != null) {
            try {
                Map<String, Object> approvalResult = approvalFlowService.handleApproval(
                    reward.getApprovalRecordId(),
                    ApprovalFlowService.ACTION_REJECT,
                    operatorId,
                    comment
                );

                String approvalStatus = (String) approvalResult.get("status");

                if (ApprovalFlowService.STATUS_REJECTED.equals(approvalStatus)) {
                    // 审批拒绝
                    reward.setStatus(STATUS_REJECTED);
                    userRewardRepository.save(reward);
                    result.put("success", true);
                    result.put("completed", true);
                    result.put("message", "奖励已拒绝");
                    result.put("status", STATUS_REJECTED);
                } else {
                    // 审批处理中或已通过（多级审批还有后续级别或已完成）
                    reward.setStatus(STATUS_REJECTED);
                    userRewardRepository.save(reward);
                    result.put("success", true);
                    result.put("completed", true);
                    result.put("message", "奖励已拒绝");
                    result.put("status", STATUS_REJECTED);
                }
                return result;

            } catch (Exception e) {
                log.error("审批流服务调用失败，拒绝执行敏感操作: rewardId={}, error={}", id, e.getMessage());
                // 审批流服务调用失败，拒绝执行敏感操作（Fail-Closed）
                result.put("success", false);
                result.put("message", "审批服务不可用，无法执行敏感操作，请稍后重试");
                return result;
            }
        }

        // 如果没有审批服务，拒绝执行（Fail-Closed原则）
        result.put("success", false);
        result.put("message", "审批服务不可用，无法执行敏感操作");
        return result;
    }

    /**
     * 发放奖励
     * 支持 APPROVED 状态（审批通过待发放）或 PENDING 状态（自动通过场景）
     */
    @Transactional
    public boolean grantReward(Long id) {
        return userRewardRepository.findById(id)
                .map(reward -> {
                    // 已发放状态直接返回成功（幂等）
                    if (STATUS_GRANTED.equals(reward.getStatus())) {
                        return true;
                    }
                    // 只有 APPROVED 状态可以发放（审批通过待发放）
                    // PENDING状态不允许发放，需要先完成审批流程
                    if (!STATUS_APPROVED.equals(reward.getStatus())) {
                        log.warn("奖励发放失败: rewardId={}, status={}, 状态不允许发放", id, reward.getStatus());
                        return false;
                    }
                    reward.setStatus(STATUS_GRANTED);
                    userRewardRepository.save(reward);
                    log.info("奖励发放成功: rewardId={}, status={}", id, STATUS_GRANTED);
                    return true;
                })
                .orElse(false);
    }

    /**
     * 批量发放奖励
     */
    @Transactional
    public int batchGrantRewards(List<Long> ids) {
        int count = 0;
        for (Long id : ids) {
            if (grantReward(id)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 取消奖励
     */
    @Transactional
    public boolean cancelReward(Long id, String reason) {
        return userRewardRepository.findById(id)
                .map(reward -> {
                    reward.setStatus("CANCELLED");
                    userRewardRepository.save(reward);
                    return true;
                })
                .orElse(false);
    }

    /**
     * 获取待审批奖励数量
     */
    @Transactional(readOnly = true)
    public long getPendingCount() {
        return userRewardRepository.countByStatus("PENDING");
    }

    /**
     * 奖励对账
     */
    @Transactional(readOnly = true)
    public Map<String, Object> reconcile(String startDate, String endDate) {
        long totalCount = userRewardRepository.count();
        long pendingCount = userRewardRepository.countByStatus("PENDING");
        long approvedCount = userRewardRepository.countByStatus("APPROVED");
        long grantedCount = userRewardRepository.countByStatus("GRANTED");
        long rejectedCount = userRewardRepository.countByStatus("REJECTED");
        long cancelledCount = userRewardRepository.countByStatus("CANCELLED");

        Long totalPoints = userRewardRepository.sumPointsByStatus("GRANTED");
        Long pendingPoints = userRewardRepository.sumPointsByStatus("PENDING");
        Long approvedPoints = userRewardRepository.sumPointsByStatus("APPROVED");

        Map<String, Object> result = new HashMap<>();
        result.put("totalAmount", totalPoints != null ? totalPoints : 0);
        result.put("totalCount", totalCount);
        result.put("successCount", grantedCount);
        result.put("failCount", rejectedCount + cancelledCount);
        // 修复：正确使用 PENDING 状态计数
        result.put("pendingCount", pendingCount);
        result.put("pendingAmount", (pendingPoints != null ? pendingPoints : 0) + (approvedPoints != null ? approvedPoints : 0));

        return result;
    }

    /**
     * 导出奖励列表为CSV格式（带数据权限过滤）
     */
    public byte[] exportRewards(String status, String rewardType, String startDate, String endDate, Long currentUserId) {
        // 数据权限过滤
        List<UserRewardEntity> rewards;

        if (currentUserId != null) {
            String dataScope = permissionCheckService.getUserDataScope(currentUserId);

            if ("ALL".equals(dataScope)) {
                // 全部数据权限，不过滤
                rewards = userRewardRepository.findAll();
            } else if ("DEPARTMENT".equals(dataScope)) {
                // 部门数据权限
                List<Long> deptIds = permissionCheckService.getUserDepartmentAndChildIds(currentUserId);
                rewards = userRewardRepository.findByDepartmentIdIn(deptIds);
            } else {
                // 个人数据权限 (OWN)
                rewards = userRewardRepository.findByUserId(currentUserId);
            }
        } else {
            // 无用户ID时返回空（保守策略）
            rewards = java.util.Collections.emptyList();
        }

        // 内存中过滤其他条件
        if (status != null && !status.isEmpty()) {
            rewards = rewards.stream()
                .filter(r -> status.equals(r.getStatus()))
                .toList();
        }
        if (rewardType != null && !rewardType.isEmpty()) {
            rewards = rewards.stream()
                .filter(r -> rewardType.equals(r.getType()))
                .toList();
        }

        // 构建CSV内容
        StringBuilder csv = new StringBuilder();
        csv.append("ID,活动ID,用户ID,类型,积分,状态,创建时间\n");

        for (UserRewardEntity reward : rewards) {
            csv.append(reward.getId()).append(",");
            csv.append(reward.getActivityId()).append(",");
            csv.append(reward.getUserId()).append(",");
            csv.append(reward.getType()).append(",");
            csv.append(reward.getPoints()).append(",");
            csv.append(reward.getStatus()).append(",");
            csv.append(reward.getCreatedAt() != null ? reward.getCreatedAt().toString() : "");
            csv.append("\n");
        }

        return csv.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8);
    }

    private Map<String, Object> convertToMap(UserRewardEntity reward) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", reward.getId());
        map.put("activityId", reward.getActivityId());
        map.put("userId", reward.getUserId());
        map.put("type", reward.getType());
        map.put("points", reward.getPoints());
        map.put("status", reward.getStatus());
        map.put("createdAt", reward.getCreatedAt() != null ? reward.getCreatedAt().toString() : null);
        return map;
    }

    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return null;
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return Long.parseLong(value.toString());
    }

    private Integer getIntValue(Map<String, Object> map, String key, int defaultValue) {
        Object value = map.get(key);
        if (value == null) return defaultValue;
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return Integer.parseInt(value.toString());
    }

    private String getStringValue(Map<String, Object> map, String key, String defaultValue) {
        Object value = map.get(key);
        return value != null ? value.toString() : defaultValue;
    }

    /**
     * 获取活动的总奖励成本（CAC计算用）
     * 只统计已发放(GRANTED)状态的奖励，与实际发放状态保持一致
     */
    public double getTotalRewardCostByActivity(Long activityId) {
        Double totalPoints = userRewardRepository.sumPointsByActivityIdAndStatusGranted(activityId);
        return totalPoints != null ? totalPoints : 0.0;
    }
}
