package com.haha.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haha.common.constant.CommonConstants;
import com.haha.common.enums.ActivityStatusEnum;
import com.haha.common.enums.ActivityTypeEnum;
import com.haha.common.enums.ApplyScopeEnum;
import com.haha.common.exception.BusinessException;
import com.haha.common.vo.StatusLabel;
import com.haha.entity.ActivityDevice;
import com.haha.entity.ActivityProduct;
import com.haha.entity.ActivityShop;
import com.haha.entity.MarketingActivity;
import com.haha.entity.dto.ActivityCreateDTO;
import com.haha.entity.dto.ActivityQueryDTO;
import com.haha.entity.dto.ActivityUpdateDTO;
import com.haha.mapper.ActivityDeviceMapper;
import com.haha.mapper.ActivityProductMapper;
import com.haha.mapper.ActivityShopMapper;
import com.haha.mapper.MarketingActivityMapper;
import com.haha.service.MarketingActivityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class MarketingActivityServiceImpl extends ServiceImpl<MarketingActivityMapper, MarketingActivity> implements MarketingActivityService {

    private final MarketingActivityMapper activityMapper;
    private final ActivityShopMapper activityShopMapper;
    private final ActivityDeviceMapper activityDeviceMapper;
    private final ActivityProductMapper activityProductMapper;

    @Override
    public IPage<MarketingActivity> getPage(ActivityQueryDTO queryDTO) {
        queryDTO.validate();
        Page<MarketingActivity> page = new Page<>(queryDTO.getPage(), queryDTO.getPageSize());

        LambdaQueryWrapper<MarketingActivity> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(queryDTO.getActivityName()), MarketingActivity::getActivityName, queryDTO.getActivityName());
        wrapper.eq(queryDTO.getActivityType() != null, MarketingActivity::getActivityType, queryDTO.getActivityType());
        wrapper.eq(queryDTO.getStatus() != null, MarketingActivity::getStatus, queryDTO.getStatus());
        wrapper.eq(queryDTO.getCreatorId() != null, MarketingActivity::getCreatorId, queryDTO.getCreatorId());
        wrapper.ge(queryDTO.getStartTimeBegin() != null, MarketingActivity::getStartTime, queryDTO.getStartTimeBegin());
        wrapper.le(queryDTO.getStartTimeEnd() != null, MarketingActivity::getStartTime, queryDTO.getStartTimeEnd());
        wrapper.eq(MarketingActivity::getDeleted, CommonConstants.NOT_DELETED);
        wrapper.orderByDesc(MarketingActivity::getCreateTime);

        IPage<MarketingActivity> result = this.page(page, wrapper);
        result.getRecords().forEach(this::fillLabels);

        return result;
    }

    @Override
    public MarketingActivity getDetail(Long id) {
        MarketingActivity activity = this.getById(id);
        if (activity == null || activity.getDeleted() == CommonConstants.DELETED) {
            throw new BusinessException(404, "活动不存在");
        }
        fillLabels(activity);
        return activity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MarketingActivity create(ActivityCreateDTO dto, Long creatorId, String creatorName) {
        MarketingActivity activity = new MarketingActivity();
        activity.setActivityName(dto.getActivityName());
        activity.setActivityType(dto.getActivityType());
        activity.setActivityDesc(dto.getActivityDesc());
        activity.setStartTime(dto.getStartTime());
        activity.setEndTime(dto.getEndTime());
        activity.setStatus(ActivityStatusEnum.DRAFT.getCode());
        activity.setDiscountValue(dto.getDiscountValue());
        activity.setMinAmount(dto.getMinAmount());
        activity.setMaxDiscount(dto.getMaxDiscount());
        activity.setApplyScope(dto.getApplyScope());
        activity.setDeviceScope(dto.getDeviceScope());
        activity.setProductScope(dto.getProductScope());
        activity.setTotalBudget(dto.getTotalBudget());
        activity.setUsedBudget(BigDecimal.ZERO);
        activity.setCreatorId(creatorId);
        activity.setCreatorName(creatorName);
        activity.setDeleted(CommonConstants.NOT_DELETED);

        this.save(activity);

        saveActivityShops(activity.getId(), dto.getShopIds(), dto.getApplyScope());
        saveActivityDevices(activity.getId(), dto.getDeviceIds(), dto.getDeviceScope());
        saveActivityProducts(activity.getId(), dto.getProductIds(), dto.getProductScope());

        log.info("创建营销活动成功: id={}, name={}", activity.getId(), activity.getActivityName());
        return activity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MarketingActivity update(ActivityUpdateDTO dto) {
        MarketingActivity activity = this.getById(dto.getId());
        if (activity == null || activity.getDeleted() == CommonConstants.DELETED) {
            throw new BusinessException(404, "活动不存在");
        }

        if (!ActivityStatusEnum.canEdit(activity.getStatus())) {
            throw new BusinessException(400, "当前状态不允许编辑");
        }

        activity.setActivityName(dto.getActivityName());
        activity.setActivityDesc(dto.getActivityDesc());
        activity.setStartTime(dto.getStartTime());
        activity.setEndTime(dto.getEndTime());
        activity.setDiscountValue(dto.getDiscountValue());
        activity.setMinAmount(dto.getMinAmount());
        activity.setMaxDiscount(dto.getMaxDiscount());
        activity.setApplyScope(dto.getApplyScope());
        activity.setDeviceScope(dto.getDeviceScope());
        activity.setProductScope(dto.getProductScope());
        activity.setTotalBudget(dto.getTotalBudget());

        this.updateById(activity);

        activityShopMapper.deleteByActivityId(activity.getId());
        activityDeviceMapper.deleteByActivityId(activity.getId());
        activityProductMapper.deleteByActivityId(activity.getId());
        saveActivityShops(activity.getId(), dto.getShopIds(), dto.getApplyScope());
        saveActivityDevices(activity.getId(), dto.getDeviceIds(), dto.getDeviceScope());
        saveActivityProducts(activity.getId(), dto.getProductIds(), dto.getProductScope());

        log.info("更新营销活动成功: id={}", activity.getId());
        return activity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publish(Long id) {
        MarketingActivity activity = this.getById(id);
        if (activity == null || activity.getDeleted() == CommonConstants.DELETED) {
            throw new BusinessException(404, "活动不存在");
        }

        if (!ActivityStatusEnum.canPublish(activity.getStatus())) {
            throw new BusinessException(400, "当前状态不允许发布");
        }

        LocalDateTime now = LocalDateTime.now();
        int newStatus = (now.isAfter(activity.getStartTime()) && now.isBefore(activity.getEndTime()))
                ? ActivityStatusEnum.ONGOING.getCode()
                : ActivityStatusEnum.PUBLISHED.getCode();

        boolean result = activityMapper.updateStatus(id, newStatus) > 0;

        if (result) {
            log.info("发布营销活动成功: id={}, status={}", id, newStatus);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pause(Long id) {
        MarketingActivity activity = this.getById(id);
        if (activity == null || activity.getDeleted() == CommonConstants.DELETED) {
            throw new BusinessException(404, "活动不存在");
        }

        if (!ActivityStatusEnum.canPause(activity.getStatus())) {
            throw new BusinessException(400, "当前状态不允许暂停");
        }

        boolean result = activityMapper.updateStatus(id, ActivityStatusEnum.PAUSED.getCode()) > 0;

        if (result) {
            log.info("暂停营销活动成功: id={}", id);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resume(Long id) {
        MarketingActivity activity = this.getById(id);
        if (activity == null || activity.getDeleted() == CommonConstants.DELETED) {
            throw new BusinessException(404, "活动不存在");
        }

        if (!ActivityStatusEnum.canResume(activity.getStatus())) {
            throw new BusinessException(400, "当前状态不允许恢复");
        }

        boolean result = activityMapper.updateStatus(id, ActivityStatusEnum.ONGOING.getCode()) > 0;

        if (result) {
            log.info("恢复营销活动成功: id={}", id);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteActivity(Long id) {
        MarketingActivity activity = this.getById(id);
        if (activity == null) {
            throw new BusinessException(404, "活动不存在");
        }

        if (!ActivityStatusEnum.canDelete(activity.getStatus())) {
            throw new BusinessException(400, "当前状态不允许删除");
        }

        activity.setDeleted(CommonConstants.DELETED);
        boolean result = this.updateById(activity);

        if (result) {
            activityShopMapper.deleteByActivityId(id);
            activityProductMapper.deleteByActivityId(id);
            log.info("删除营销活动成功: id={}", id);
        }
        return result;
    }

    @Override
    public List<MarketingActivity> getOngoingActivities() {
        LocalDateTime now = LocalDateTime.now();
        return activityMapper.selectOngoingActivities(ActivityStatusEnum.ONGOING.getCode(), now);
    }

    @Override
    public List<Long> getActivityShopIds(Long activityId) {
        return activityShopMapper.selectShopIdsByActivityId(activityId);
    }

    @Override
    public List<String> getActivityDeviceIds(Long activityId) {
        return activityDeviceMapper.selectDeviceIdsByActivityId(activityId);
    }

    @Override
    public List<Long> getActivityProductIds(Long activityId) {
        return activityProductMapper.selectProductIdsByActivityId(activityId);
    }

    @Override
    public Map<String, Object> getStatistics(Long activityId) {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalActivities", activityMapper.countTotal());
        stats.put("ongoingActivities", activityMapper.countByStatus(ActivityStatusEnum.ONGOING.getCode()));
        stats.put("pausedActivities", activityMapper.countByStatus(ActivityStatusEnum.PAUSED.getCode()));
        return stats;
    }

    private void saveActivityShops(Long activityId, List<Long> shopIds, Integer applyScope) {
        if (applyScope != null && applyScope == ApplyScopeEnum.SPECIFIED_SHOP.getCode()
                && shopIds != null && !shopIds.isEmpty()) {
            for (Long shopId : shopIds) {
                ActivityShop activityShop = new ActivityShop();
                activityShop.setActivityId(activityId);
                activityShop.setShopId(shopId);
                activityShopMapper.insert(activityShop);
            }
        }
    }

    private void saveActivityDevices(Long activityId, List<String> deviceIds, Integer deviceScope) {
        if (deviceScope != null && deviceScope == ApplyScopeEnum.SPECIFIED_SHOP.getCode()
                && deviceIds != null && !deviceIds.isEmpty()) {
            for (String deviceId : deviceIds) {
                ActivityDevice activityDevice = new ActivityDevice();
                activityDevice.setActivityId(activityId);
                activityDevice.setDeviceId(deviceId);
                activityDeviceMapper.insert(activityDevice);
            }
        }
    }

    private void saveActivityProducts(Long activityId, List<Long> productIds, Integer productScope) {
        if (productScope != null && productScope == ApplyScopeEnum.SPECIFIED_SHOP.getCode()
                && productIds != null && !productIds.isEmpty()) {
            for (Long productId : productIds) {
                ActivityProduct activityProduct = new ActivityProduct();
                activityProduct.setActivityId(activityId);
                activityProduct.setProductId(productId);
                activityProductMapper.insert(activityProduct);
            }
        }
    }

    private void fillLabels(MarketingActivity activity) {
        StatusLabel statusLabel = ActivityStatusEnum.getLabelByCode(activity.getStatus());
        activity.setStatusLabel(statusLabel.getLabel());
        activity.setStatusColor(statusLabel.getColor());

        StatusLabel typeLabel = ActivityTypeEnum.getLabelByCode(activity.getActivityType());
        activity.setTypeLabel(typeLabel.getLabel());

        StatusLabel applyScopeLabel = ApplyScopeEnum.getLabelByCode(activity.getApplyScope());
        activity.setApplyScopeLabel(applyScopeLabel.getLabel());
    }
}
