package com.jeesharp.business.modules.marketing.tenantQrcode.application;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.marketing.application.support.MarketingChannelPresetSupport;
import com.jeesharp.business.modules.marketing.application.support.MarketingChannelPresetSupport.ResolvedChannel;
import com.jeesharp.business.modules.marketing.application.support.MarketingTenantWxQrcodeSupport;
import com.jeesharp.business.modules.marketing.application.support.MarketingWxSceneSupport;
import com.jeesharp.business.modules.marketing.tenantQrcode.convert.MarketingTenantQrcodeConvert;
import com.jeesharp.business.modules.marketing.tenantQrcode.dto.MarketingTenantQrcodeCreateDTO;
import com.jeesharp.business.modules.marketing.tenantQrcode.entity.MarketingTenantQrcode;
import com.jeesharp.business.modules.marketing.tenantQrcode.enums.MarketingChannelPresetEnum;
import com.jeesharp.business.modules.marketing.tenantQrcode.service.MarketingTenantQrcodeService;
import com.jeesharp.business.modules.marketing.tenantQrcode.vo.MarketingTenantQrcodeChannelPresetVO;
import com.jeesharp.business.modules.marketing.tenantQrcode.vo.MarketingTenantQrcodeCreateResultVO;
import com.jeesharp.business.modules.marketing.tenantQrcode.vo.MarketingTenantQrcodeListVO;
import com.jeesharp.business.modules.marketing.tenantQrcode.vo.MarketingTenantQrcodeQueryVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 店铺推广二维码应用服务。
 *
 * @author jeesharp
 * @since 2026-06-25
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MarketingTenantQrcodeApplicationService {

    private static final String DEFAULT_PAGE_PATH = "pages/home/index";

    private final MarketingTenantQrcodeService marketingTenantQrcodeService;
    private final MarketingTenantWxQrcodeSupport marketingTenantWxQrcodeSupport;

    public PageRespVO<MarketingTenantQrcodeListVO> findPage(Page<MarketingTenantQrcode> page, MarketingTenantQrcodeQueryVO query) {
        Page<MarketingTenantQrcode> result = marketingTenantQrcodeService.findPage(page, query != null ? query : new MarketingTenantQrcodeQueryVO());
        PageRespVO<MarketingTenantQrcodeListVO> resp = new PageRespVO<>();
        resp.setTotal(result.getTotal());
        resp.setPageNo(result.getPageNo());
        resp.setPageSize(result.getPageSize());
        List<MarketingTenantQrcodeListVO> records = MarketingTenantQrcodeConvert.INSTANCE.toListVOList(result.getRecords());
        records.forEach(this::normalizeListQrcodeUrl);
        resp.setRecords(records);
        return resp;
    }

    public List<MarketingTenantQrcodeChannelPresetVO> listChannelPresets() {
        List<MarketingTenantQrcode> existing = marketingTenantQrcodeService.findList(new MarketingTenantQrcodeQueryVO());
        Set<String> existingCodes = new HashSet<>();
        for (MarketingTenantQrcode row : existing) {
            if (StrUtil.isNotBlank(row.getChannelCode())) {
                existingCodes.add(row.getChannelCode().trim().toUpperCase());
            }
        }
        List<MarketingTenantQrcodeChannelPresetVO> presets = new ArrayList<>();
        for (MarketingChannelPresetEnum preset : MarketingChannelPresetEnum.values()) {
            MarketingTenantQrcodeChannelPresetVO vo = new MarketingTenantQrcodeChannelPresetVO();
            vo.setPresetCode(preset.getCode());
            vo.setChannelCode(preset.getCode());
            vo.setChannelName(preset.getName());
            vo.setDescription(preset.getDescription());
            vo.setCreated(existingCodes.contains(preset.getCode()));
            presets.add(vo);
        }
        return presets;
    }

    @Transactional(readOnly = false)
    public MarketingTenantQrcodeCreateResultVO create(MarketingTenantQrcodeCreateDTO dto) {
        ResolvedChannel resolved = MarketingChannelPresetSupport.resolve(dto);
        String channelCode = resolved.getChannelCode();
        MarketingTenantQrcode entity = new MarketingTenantQrcode();
        entity.setChannelCode(channelCode);
        entity.setChannelName(resolved.getChannelName());
        entity.setPagePath(StrUtil.blankToDefault(dto.getPagePath(), DEFAULT_PAGE_PATH));
        entity.preInsert();
        if (StrUtil.isBlank(entity.getTenantCode())) {
            throw new BizErrorException("无法识别当前店铺租户，请确认登录上下文");
        }
        MarketingTenantQrcode exists = marketingTenantQrcodeService.getByTenantAndChannelIncludingDeleted(entity.getTenantId(), channelCode);
        if (exists != null && MarketingTenantQrcode.DEL_FLAG_NORMAL.equals(exists.getDelFlag())) {
            throw new BizErrorException("「" + resolved.getChannelName() + "」推广码已存在，请直接下载或更换渠道");
        }
        if (exists != null) {
            entity.setId(exists.getId());
        }
        entity.setWxScene(MarketingWxSceneSupport.buildWxScene(entity.getTenantCode(), channelCode));
        String qrcodeUrl = marketingTenantWxQrcodeSupport.generateAndUpload(
                entity.getWxScene(),
                entity.getPagePath(),
                entity.getId()
        );
        entity.setQrcodeUrl(MarketingTenantWxQrcodeSupport.normalizeDisplayUrl(qrcodeUrl));
        if (exists != null) {
            marketingTenantQrcodeService.restoreDeletedMarketingTenantQrcode(entity);
        } else {
            marketingTenantQrcodeService.createMarketingTenantQrcode(entity);
        }
        MarketingTenantQrcodeCreateResultVO resultVO = MarketingTenantQrcodeConvert.INSTANCE.toCreateResultVO(entity);
        resultVO.setQrcodeUrl(entity.getQrcodeUrl());
        return resultVO;
    }

    public void writeQrcodeImage(String id, HttpServletResponse response) throws IOException {
        MarketingTenantQrcode entity = marketingTenantQrcodeService.get(id);
        if (entity == null || StrUtil.isBlank(entity.getQrcodeUrl())) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "推广码不存在");
            return;
        }
        response.setContentType(MarketingTenantWxQrcodeSupport.resolveImageContentType(entity.getQrcodeUrl()));
        response.setHeader(HttpHeaders.CACHE_CONTROL, "private, max-age=3600");
        marketingTenantWxQrcodeSupport.writeImage(entity.getQrcodeUrl(), response.getOutputStream());
    }

    private void normalizeListQrcodeUrl(MarketingTenantQrcodeListVO vo) {
        if (vo == null) {
            return;
        }
        vo.setQrcodeUrl(MarketingTenantWxQrcodeSupport.normalizeDisplayUrl(vo.getQrcodeUrl()));
    }

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

    public MarketingTenantQrcode getByWxScene(String wxScene) {
        return marketingTenantQrcodeService.getByWxScene(wxScene);
    }

    @Transactional(readOnly = false)
    public void incrementScanCount(String id) {
        marketingTenantQrcodeService.incrementScanCount(id);
    }
}
