package com.jeesharp.business.modules.setting.application;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.setting.application.support.OperationPopupCouponPackSupport;
import com.jeesharp.business.modules.setting.convert.OperationPopupConvert;
import com.jeesharp.business.modules.setting.dto.OperationPopupExtConfigDTO;
import com.jeesharp.business.modules.setting.dto.OperationPopupSaveDTO;
import com.jeesharp.business.modules.setting.entity.OperationPopup;
import com.jeesharp.business.modules.setting.enums.OperationPopupClosableEnum;
import com.jeesharp.business.modules.setting.enums.OperationPopupDisplayModeEnum;
import com.jeesharp.business.modules.setting.enums.OperationPopupStatusEnum;
import com.jeesharp.business.modules.setting.service.OperationPopupService;
import com.jeesharp.business.modules.setting.vo.OperationPopupClientVO;
import com.jeesharp.business.modules.setting.vo.OperationPopupListVO;
import com.jeesharp.business.modules.setting.vo.OperationPopupQueryVO;
import com.jeesharp.business.modules.setting.vo.OperationPopupVO;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * 运营首页弹窗应用服务：后台 CRUD 与 C 端小程序首页弹窗列表。
 *
 * @author jeesharp
 * @since 2026-05-12
 */
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class OperationPopupApplicationService {

    private static final DateTimeFormatter ISO_LOCAL = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

    private final OperationPopupService operationPopupService;
    private final OperationPopupCouponPackSupport couponPackSupport;

    public OperationPopupVO get(String id) {
        return OperationPopupConvert.INSTANCE.toInfoVO(operationPopupService.get(id));
    }

    public PageRespVO<OperationPopupListVO> findPage(Page<OperationPopup> page, OperationPopupQueryVO query) {
        Page<OperationPopup> result = operationPopupService.findPage(page, query);
        return OperationPopupConvert.INSTANCE.toPageRespVO(result);
    }

    @Transactional(readOnly = false)
    public void save(OperationPopupSaveDTO dto) {
        if (OperationPopupClosableEnum.fromValue(dto.getClosable()) == null) {
            throw new IllegalArgumentException("是否可关闭取值不合法");
        }
        if (dto.getStatus() != null && OperationPopupStatusEnum.fromValue(dto.getStatus()) == null) {
            throw new IllegalArgumentException("状态取值不合法");
        }
        OperationPopupDisplayModeEnum mode = resolveDisplayMode(dto.getDisplayMode());
        validateSaveByMode(mode, dto);
        OperationPopup entity = OperationPopupConvert.INSTANCE.toEntity(dto);
        entity.setDisplayMode(mode.getValue());
        entity.setExtConfig(couponPackSupport.normalizeExtConfigJson(dto.getExtConfig()));
        if (StrUtil.isBlank(dto.getId())) {
            operationPopupService.createPopup(entity);
            return;
        }
        operationPopupService.updatePopup(entity);
    }

    @Transactional(readOnly = false)
    public void delete(String ids) {
        operationPopupService.batchDelete(StrUtil.splitTrim(ids, ','));
    }

    /**
     * 微信小程序首页弹窗列表（按排序返回；无配置时为空）。
     *
     * @return 弹窗项，可能为空列表
     */
    public List<OperationPopupClientVO> listForWechatMiniHome() {
        List<OperationPopup> rows = operationPopupService.listActiveForWechatMiniHome();
        List<OperationPopupClientVO> out = new ArrayList<>(rows.size());
        for (OperationPopup r : rows) {
            out.add(toClientVo(r));
        }
        return out;
    }

    private void validateSaveByMode(OperationPopupDisplayModeEnum mode, OperationPopupSaveDTO dto) {
        if (mode.requiresImage() && StrUtil.isBlank(dto.getImageUrl())) {
            throw new IllegalArgumentException("当前展示方式须上传配图");
        }
        if (mode == OperationPopupDisplayModeEnum.COUPON_PACK) {
            OperationPopupExtConfigDTO ext = couponPackSupport.parseExtConfig(dto.getExtConfig());
            if (ext.getTemplateIds() == null || ext.getTemplateIds().isEmpty()) {
                throw new IllegalArgumentException("券包模式须配置关联优惠券模板");
            }
            if (StrUtil.isBlank(dto.getTitle())) {
                throw new IllegalArgumentException("券包模式须填写标题");
            }
        }
        if (mode == OperationPopupDisplayModeEnum.ACTIVITY && StrUtil.isBlank(dto.getImageUrl())
                && StrUtil.isBlank(dto.getTitle())) {
            throw new IllegalArgumentException("营销活动模式须填写标题或上传封面");
        }
    }

    private static OperationPopupDisplayModeEnum resolveDisplayMode(String displayMode) {
        OperationPopupDisplayModeEnum mode = OperationPopupDisplayModeEnum.fromValue(displayMode);
        if (mode == null) {
            throw new IllegalArgumentException("展示方式取值不合法");
        }
        return mode;
    }

    private OperationPopupClientVO toClientVo(OperationPopup r) {
        OperationPopupDisplayModeEnum mode = OperationPopupDisplayModeEnum.fromValue(r.getDisplayMode());
        if (mode == null) {
            mode = OperationPopupDisplayModeEnum.IMAGE_H;
        }
        OperationPopupExtConfigDTO ext = couponPackSupport.parseExtConfig(r.getExtConfig());

        OperationPopupClientVO vo = new OperationPopupClientVO();
        vo.setId(r.getId());
        vo.setDisplayMode(mode.getValue());
        vo.setTitle(r.getTitle());
        vo.setSubtitle(r.getSubtitle());
        vo.setImageUrl(r.getImageUrl());
        vo.setLinkPath(r.getLinkPath());
        vo.setExtConfig(ext);
        vo.setClosable(r.getClosable() != null && OperationPopupClosableEnum.YES.getValue().equals(r.getClosable()));
        vo.setStartTime(r.getDisplayBegin() != null ? ISO_LOCAL.format(r.getDisplayBegin()) : null);
        vo.setEndTime(r.getDisplayEnd() != null ? ISO_LOCAL.format(r.getDisplayEnd()) : null);
        vo.setCoupons(couponPackSupport.buildCouponItems(mode, r.getExtConfig(), r.getLinkPath()));
        return vo;
    }
}
