package com.ycwl.basic.pricing.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.pricing.entity.PriceCouponClaimRecord;
import com.ycwl.basic.pricing.entity.PriceCouponConfig;
import com.ycwl.basic.pricing.enums.CouponStatus;
import com.ycwl.basic.pricing.mapper.PriceCouponClaimRecordMapper;
import com.ycwl.basic.pricing.mapper.PriceCouponConfigMapper;
import com.ycwl.basic.pricing.service.ICouponManagementService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 优惠券管理服务实现（管理端）
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CouponManagementServiceImpl implements ICouponManagementService {

    private static final TypeReference<List<String>> STRING_LIST_TYPE = new TypeReference<>() {};
    
    private final PriceCouponConfigMapper couponConfigMapper;
    private final PriceCouponClaimRecordMapper claimRecordMapper;
    private final ObjectMapper objectMapper;
    
    // ==================== 优惠券配置管理 ====================
    
    @Override
    @Transactional
    public Long createCouponConfig(PriceCouponConfig config) {
        log.info("创建优惠券配置: {}", config.getCouponName());

        validateCouponConfig(config);
        
        // 设置默认值
        if (config.getUsedQuantity() == null) {
            config.setUsedQuantity(0);
        }
        if (config.getIsActive() == null) {
            config.setIsActive(true);
        }
        
        int result = couponConfigMapper.insertCoupon(config);
        if (result > 0) {
            log.info("优惠券配置创建成功，ID: {}", config.getId());
            return config.getId();
        } else {
            log.error("优惠券配置创建失败");
            return null;
        }
    }
    
    @Override
    @Transactional
    public boolean updateCouponConfig(PriceCouponConfig config) {
        log.info("更新优惠券配置，ID: {}", config.getId());

        validateCouponConfig(config);
        
        PriceCouponConfig existing = couponConfigMapper.selectById(config.getId());
        if (existing == null) {
            log.error("优惠券配置不存在，ID: {}", config.getId());
            return false;
        }
        
        int result = couponConfigMapper.updateCoupon(config);
        if (result > 0) {
            log.info("优惠券配置更新成功，ID: {}", config.getId());
            return true;
        } else {
            log.error("优惠券配置更新失败，ID: {}", config.getId());
            return false;
        }
    }

    private void validateCouponConfig(PriceCouponConfig config) {
        validateRequiredAttributeKeys(config.getRequiredAttributeKeys());
    }

    private void validateRequiredAttributeKeys(String requiredAttributeKeys) {
        if (requiredAttributeKeys == null || requiredAttributeKeys.isBlank()) {
            return;
        }

        List<String> keys;
        try {
            keys = objectMapper.readValue(requiredAttributeKeys, STRING_LIST_TYPE);
        } catch (Exception e) {
            throw new IllegalArgumentException("requiredAttributeKeys格式错误，必须是JSON数组字符串，例如 [\"TYPE_3\"]");
        }

        if (keys == null || keys.isEmpty()) {
            return;
        }

        boolean hasBlankKey = keys.stream().anyMatch(key -> key == null || key.trim().isEmpty());
        if (hasBlankKey) {
            throw new IllegalArgumentException("requiredAttributeKeys不能包含空值");
        }
    }
    
    @Override
    @Transactional
    public boolean deleteCouponConfig(Long id) {
        log.info("删除优惠券配置，ID: {}", id);
        
        PriceCouponConfig existing = couponConfigMapper.selectById(id);
        if (existing == null) {
            log.error("优惠券配置不存在，ID: {}", id);
            return false;
        }
        
        int result = couponConfigMapper.deleteCoupon(id);
        if (result > 0) {
            log.info("优惠券配置删除成功，ID: {}", id);
            return true;
        } else {
            log.error("优惠券配置删除失败，ID: {}", id);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean updateCouponConfigStatus(Long id, Boolean isActive) {
        log.info("更新优惠券配置状态，ID: {}, 状态: {}", id, isActive);
        
        PriceCouponConfig existing = couponConfigMapper.selectById(id);
        if (existing == null) {
            log.error("优惠券配置不存在，ID: {}", id);
            return false;
        }
        
        int result = couponConfigMapper.updateCouponStatus(id, isActive);
        if (result > 0) {
            log.info("优惠券配置状态更新成功，ID: {}", id);
            return true;
        } else {
            log.error("优惠券配置状态更新失败，ID: {}", id);
            return false;
        }
    }
    
    @Override
    public List<PriceCouponConfig> getAllCouponConfigs() {
        log.info("查询所有优惠券配置");
        return couponConfigMapper.selectAllForAdmin();
    }
    
    @Override
    public PageInfo<PriceCouponConfig> getCouponConfigsPage(Integer pageNum, Integer pageSize, 
                                                            Boolean isActive, String couponName, String scenicId) {
        log.info("分页查询优惠券配置，页码: {}, 页大小: {}, 状态: {}, 名称: {}, 景区ID: {}", 
                pageNum, pageSize, isActive, couponName, scenicId);
        
        PageHelper.startPage(pageNum, pageSize);
        List<PriceCouponConfig> configs = couponConfigMapper.selectByConditionsForAdmin(isActive, couponName, scenicId);
        return new PageInfo<>(configs);
    }
    
    @Override
    public List<PriceCouponConfig> getCouponConfigsByStatus(Boolean isActive) {
        log.info("根据状态查询优惠券配置，状态: {}", isActive);
        return couponConfigMapper.selectByStatusForAdmin(isActive);
    }
    
    @Override
    public PriceCouponConfig getCouponConfigById(Long id) {
        log.info("根据ID查询优惠券配置，ID: {}", id);
        return couponConfigMapper.selectById(id);
    }
    
    // ==================== 优惠券领取记录查询 ====================
    
    @Override
    public List<PriceCouponClaimRecord> getAllClaimRecords() {
        log.info("查询所有优惠券领取记录");
        return claimRecordMapper.selectAllForAdmin();
    }
    
    @Override
    public PageInfo<PriceCouponClaimRecord> getClaimRecordsPage(Integer pageNum, Integer pageSize, 
                                                                Long userId, Long couponId, CouponStatus status,
                                                                String startTime, String endTime, String scenicId) {
        log.info("分页查询优惠券领取记录，页码: {}, 页大小: {}, 用户ID: {}, 优惠券ID: {}, 状态: {}, 开始时间: {}, 结束时间: {}, 景区ID: {}", 
                pageNum, pageSize, userId, couponId, status, startTime, endTime, scenicId);
        
        PageHelper.startPage(pageNum, pageSize);
        List<PriceCouponClaimRecord> records = claimRecordMapper.selectByConditionsForAdmin(userId, couponId, status, startTime, endTime, scenicId);
        return new PageInfo<>(records);
    }
    
    @Override
    public List<PriceCouponClaimRecord> getClaimRecordsByUserId(Long userId) {
        log.info("根据用户ID查询优惠券领取记录，用户ID: {}", userId);
        return claimRecordMapper.selectByUserIdForAdmin(userId);
    }
    
    @Override
    public List<PriceCouponClaimRecord> getClaimRecordsByCouponId(Long couponId) {
        log.info("根据优惠券ID查询领取记录，优惠券ID: {}", couponId);
        return claimRecordMapper.selectByCouponIdForAdmin(couponId);
    }
    
    @Override
    public List<PriceCouponClaimRecord> getClaimRecordsByStatus(CouponStatus status) {
        log.info("根据状态查询领取记录，状态: {}", status);
        return claimRecordMapper.selectByStatusForAdmin(status);
    }
    
    @Override
    public Map<String, Object> getCouponUsageStats(Long couponId) {
        log.info("查询优惠券使用统计，优惠券ID: {}", couponId);
        return claimRecordMapper.selectCouponUsageStats(couponId);
    }
    
    @Override
    public Map<String, Object> getCouponDetailStats(Long couponId) {
        log.info("查询优惠券详细统计，优惠券ID: {}", couponId);
        return claimRecordMapper.selectCouponDetailStats(couponId);
    }
    
    @Override
    public Map<String, Object> getPeriodStats(String startDate, String endDate, String scenicId) {
        log.info("查询时间范围统计，开始日期: {}, 结束日期: {}, 景区ID: {}", startDate, endDate, scenicId);
        return claimRecordMapper.selectPeriodStats(startDate, endDate, scenicId);
    }
    
    @Override
    public List<Map<String, Object>> getAllCouponUsageOverview() {
        log.info("查询所有优惠券使用统计概览");
        
        List<PriceCouponConfig> allCoupons = couponConfigMapper.selectAllForAdmin();
        List<Map<String, Object>> overview = new ArrayList<>();
        
        for (PriceCouponConfig coupon : allCoupons) {
            Map<String, Object> stats = new HashMap<>();
            stats.put("couponId", coupon.getId());
            stats.put("couponName", coupon.getCouponName());
            stats.put("couponType", coupon.getCouponType());
            stats.put("totalQuantity", coupon.getTotalQuantity());
            stats.put("usedQuantity", coupon.getUsedQuantity());
            stats.put("remainingQuantity", coupon.getTotalQuantity() - coupon.getUsedQuantity());
            stats.put("isActive", coupon.getIsActive());
            stats.put("validFrom", coupon.getValidFrom());
            stats.put("validUntil", coupon.getValidUntil());
            
            // 获取详细统计
            Map<String, Object> usageStats = claimRecordMapper.selectCouponUsageStats(coupon.getId());
            stats.putAll(usageStats);
            
            overview.add(stats);
        }
        
        return overview;
    }
    
    @Override
    public Map<String, Object> getScenicCouponStats(String scenicId) {
        log.info("查询景区优惠券统计，景区ID: {}", scenicId);
        
        // 获取景区优惠券配置统计
        Map<String, Object> configStats = couponConfigMapper.selectScenicCouponConfigStats(scenicId);
        
        // 获取景区优惠券使用统计
        Map<String, Object> usageStats = claimRecordMapper.selectScenicCouponUsageStats(scenicId);
        
        // 合并统计结果
        Map<String, Object> result = new HashMap<>();
        result.put("scenic_id", scenicId);
        result.putAll(configStats);
        result.putAll(usageStats);
        
        return result;
    }
}
