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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.exception.BizException;
import com.ycwl.basic.pricing.dto.req.VoucherBatchCreateReq;
import com.ycwl.basic.pricing.dto.req.VoucherBatchCreateReqV2;
import com.ycwl.basic.pricing.dto.req.VoucherBatchQueryReq;
import com.ycwl.basic.pricing.dto.resp.VoucherBatchResp;
import com.ycwl.basic.pricing.dto.resp.VoucherBatchStatsResp;
import com.ycwl.basic.pricing.entity.PriceVoucherBatchConfig;
import com.ycwl.basic.pricing.enums.VoucherDiscountType;
import com.ycwl.basic.pricing.mapper.PriceVoucherBatchConfigMapper;
import com.ycwl.basic.pricing.service.VoucherBatchService;
import com.ycwl.basic.pricing.service.VoucherCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;

@Service
public class VoucherBatchServiceImpl implements VoucherBatchService {
    @Autowired
    private PriceVoucherBatchConfigMapper voucherBatchMapper;
    @Autowired
    @Lazy
    private VoucherCodeService voucherCodeService;
    
    @Override
    @Transactional
    public Long createBatch(VoucherBatchCreateReq req) {
        if (req.getBatchName() == null || req.getBatchName().trim().isEmpty()) {
            throw new BizException(400, "券码批次名称不能为空");
        }
        if (req.getScenicId() == null) {
            throw new BizException(400, "景区ID不能为空");
        }
        if (req.getBrokerId() == null) {
            throw new BizException(400, "推客ID不能为空");
        }
        if (req.getDiscountType() == null) {
            throw new BizException(400, "优惠类型不能为空");
        }
        if (req.getTotalCount() == null || req.getTotalCount() < 1) {
            throw new BizException(400, "券码数量必须大于0");
        }
        
        VoucherDiscountType discountType = VoucherDiscountType.getByCode(req.getDiscountType());
        if (discountType == null) {
            throw new BizException(400, "无效的优惠类型");
        }
        
        if (discountType != VoucherDiscountType.FREE_ALL && req.getDiscountValue() == null) {
            throw new BizException(400, "优惠金额不能为空");
        }
        
        PriceVoucherBatchConfig batch = new PriceVoucherBatchConfig();
        BeanUtils.copyProperties(req, batch);
        batch.setUsedCount(0);
        batch.setClaimedCount(0);
        batch.setStatus(1);
        batch.setCreateTime(new Date());
        String userIdStr = BaseContextHandler.getUserId();
        if (userIdStr != null) {
            batch.setCreateBy(Long.valueOf(userIdStr));
        }
        batch.setDeleted(0);
        
        voucherBatchMapper.insert(batch);
        
        voucherCodeService.generateVoucherCodes(batch.getId(), req.getScenicId(), req.getTotalCount());
        
        return batch.getId();
    }
    
    @Override
    @Transactional
    public Long createBatchV2(VoucherBatchCreateReqV2 req) {
        if (req.getBatchName() == null || req.getBatchName().trim().isEmpty()) {
            throw new BizException(400, "券码批次名称不能为空");
        }
        if (req.getScenicId() == null) {
            throw new BizException(400, "景区ID不能为空");
        }
        if (req.getBrokerId() == null) {
            throw new BizException(400, "推客ID不能为空");
        }
        if (req.getDiscountType() == null) {
            throw new BizException(400, "优惠类型不能为空");
        }
        if (req.getTotalCount() == null || req.getTotalCount() < 1) {
            throw new BizException(400, "券码数量必须大于0");
        }
        
        VoucherDiscountType discountType = VoucherDiscountType.getByCode(req.getDiscountType());
        if (discountType == null) {
            throw new BizException(400, "无效的优惠类型");
        }
        
        if (discountType != VoucherDiscountType.FREE_ALL && req.getDiscountValue() == null) {
            throw new BizException(400, "优惠金额不能为空");
        }
        
        // 验证可重复使用参数
        if (req.getMaxUseCount() != null && req.getMaxUseCount() < 1) {
            throw new BizException(400, "最大使用次数必须大于0");
        }
        if (req.getMaxUsePerUser() != null && req.getMaxUsePerUser() < 1) {
            throw new BizException(400, "每用户最大使用次数必须大于0");
        }
        if (req.getUseIntervalHours() != null && req.getUseIntervalHours() < 0) {
            throw new BizException(400, "使用间隔小时数不能为负数");
        }
        
        // 验证时间范围参数
        if (req.getValidStartTime() != null && req.getValidEndTime() != null) {
            if (req.getValidStartTime().after(req.getValidEndTime())) {
                throw new BizException(400, "有效期开始时间不能晚于结束时间");
            }
        }
        
        PriceVoucherBatchConfig batch = new PriceVoucherBatchConfig();
        BeanUtils.copyProperties(req, batch);
        
        // 设置适用商品类型
        if (req.getApplicableProducts() != null) {
            batch.setApplicableProducts(req.getApplicableProducts());
        }
        
        batch.setUsedCount(0);
        batch.setClaimedCount(0);
        batch.setStatus(1);
        batch.setCreateTime(new Date());
        
        String userIdStr = BaseContextHandler.getUserId();
        if (userIdStr != null) {
            batch.setCreateBy(Long.valueOf(userIdStr));
        }
        batch.setDeleted(0);
        
        voucherBatchMapper.insert(batch);
        
        // 生成券码，初始状态为UNCLAIMED，currentUseCount为0
        voucherCodeService.generateVoucherCodes(batch.getId(), req.getScenicId(), req.getTotalCount());
        
        return batch.getId();
    }
    
    @Override
    public PageInfo<VoucherBatchResp> queryBatchList(VoucherBatchQueryReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());

        LambdaQueryWrapper<PriceVoucherBatchConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PriceVoucherBatchConfig::getDeleted, 0)
                .eq(req.getScenicId() != null, PriceVoucherBatchConfig::getScenicId, req.getScenicId())
                .eq(req.getBrokerId() != null, PriceVoucherBatchConfig::getBrokerId, req.getBrokerId())
                .eq(req.getStatus() != null, PriceVoucherBatchConfig::getStatus, req.getStatus())
                .like(StringUtils.hasText(req.getBatchName()), PriceVoucherBatchConfig::getBatchName, req.getBatchName())
                .orderByDesc(PriceVoucherBatchConfig::getCreateTime);

        java.util.List<PriceVoucherBatchConfig> list = voucherBatchMapper.selectList(wrapper);
        java.util.List<VoucherBatchResp> respList = list.stream().map(this::convertToResp).toList();

        return new PageInfo<>(respList);
    }
    
    @Override
    public VoucherBatchResp getBatchDetail(Long id) {
        PriceVoucherBatchConfig batch = voucherBatchMapper.selectById(id);
        if (batch == null || batch.getDeleted() == 1) {
            throw new BizException(404, "券码批次不存在");
        }
        
        return convertToResp(batch);
    }
    
    @Override
    public VoucherBatchStatsResp getBatchStats(Long id) {
        PriceVoucherBatchConfig batch = voucherBatchMapper.selectById(id);
        if (batch == null || batch.getDeleted() == 1) {
            throw new BizException(404, "券码批次不存在");
        }
        
        VoucherBatchStatsResp stats = new VoucherBatchStatsResp();
        stats.setBatchId(batch.getId());
        stats.setBatchName(batch.getBatchName());
        stats.setTotalCount(batch.getTotalCount());
        stats.setClaimedCount(batch.getClaimedCount());
        stats.setUsedCount(batch.getUsedCount());
        stats.setAvailableCount(batch.getTotalCount() - batch.getClaimedCount());
        
        if (batch.getTotalCount() > 0) {
            stats.setClaimedRate((double) batch.getClaimedCount() / batch.getTotalCount() * 100);
            stats.setUsedRate((double) batch.getUsedCount() / batch.getTotalCount() * 100);
        } else {
            stats.setClaimedRate(0.0);
            stats.setUsedRate(0.0);
        }
        
        return stats;
    }
    
    @Override
    public void updateBatchStatus(Long id, Integer status) {
        PriceVoucherBatchConfig batch = new PriceVoucherBatchConfig();
        batch.setId(id);
        batch.setStatus(status);
        
        int updated = voucherBatchMapper.updateById(batch);
        if (updated == 0) {
            throw new BizException(404, "券码批次不存在");
        }
    }
    
    @Override
    public void updateBatchClaimedCount(Long batchId) {
        PriceVoucherBatchConfig batch = voucherBatchMapper.selectById(batchId);
        if (batch != null) {
            batch.setClaimedCount(batch.getClaimedCount() + 1);
            voucherBatchMapper.updateById(batch);
        }
    }
    
    @Override
    public void updateBatchUsedCount(Long batchId) {
        PriceVoucherBatchConfig batch = voucherBatchMapper.selectById(batchId);
        if (batch != null) {
            batch.setUsedCount(batch.getUsedCount() + 1);
            voucherBatchMapper.updateById(batch);
        }
    }
    
    @Override
    public PriceVoucherBatchConfig getAvailableBatch(Long scenicId, Long brokerId) {
        LambdaQueryWrapper<PriceVoucherBatchConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PriceVoucherBatchConfig::getScenicId, scenicId)
                .eq(PriceVoucherBatchConfig::getBrokerId, brokerId)
                .eq(PriceVoucherBatchConfig::getStatus, 1)
                .eq(PriceVoucherBatchConfig::getDeleted, 0)
                .apply("claimed_count < total_count")
                .orderByDesc(PriceVoucherBatchConfig::getCreateTime);
        
        return voucherBatchMapper.selectOne(wrapper);
    }
    
    private VoucherBatchResp convertToResp(PriceVoucherBatchConfig batch) {
        VoucherBatchResp resp = new VoucherBatchResp();
        BeanUtils.copyProperties(batch, resp);
        
        VoucherDiscountType discountType = VoucherDiscountType.getByCode(batch.getDiscountType());
        if (discountType != null) {
            resp.setDiscountTypeName(discountType.getName());
        }
        
        resp.setStatusName(batch.getStatus() == 1 ? "启用" : "禁用");
        resp.setAvailableCount(batch.getTotalCount() - batch.getClaimedCount());
        resp.setApplicableProducts(batch.getApplicableProducts());
        
        return resp;
    }
}