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

import com.jeesharp.business.modules.common.api.BizSceneApi;
import com.jeesharp.business.modules.common.bizscene.support.BizSceneAdminListRecordSupport;
import com.jeesharp.business.modules.common.bizscene.support.BizSceneCouponLegacySupport;
import com.jeesharp.business.modules.common.bizscene.support.BizScenePickerSupport;
import com.jeesharp.business.modules.common.bizscene.vo.BizSceneOptionVO;
import com.jeesharp.business.modules.common.enums.ShelfStatusEnum;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.jeesharp.business.modules.coupon.entity.CouponTemplate;
import com.jeesharp.business.modules.coupon.enums.CouponTemplateStatusEnum;
import com.jeesharp.business.modules.coupon.service.CouponTemplateService;
import com.jeesharp.business.modules.coupon.vo.CouponTemplateQueryVO;
import com.jeesharp.business.modules.food.entity.FoodRestaurant;
import com.jeesharp.business.modules.food.service.FoodRestaurantService;
import com.jeesharp.business.modules.food.vo.FoodRestaurantQueryVO;
import com.jeesharp.business.modules.mall.entity.MallSpu;
import com.jeesharp.business.modules.mall.service.MallSpuService;
import com.jeesharp.business.modules.mall.vo.MallSpuQueryVO;
import com.jeesharp.business.modules.setting.entity.CmsHomeGridIntro;
import com.jeesharp.business.modules.setting.entity.MarketingActivity;
import com.jeesharp.business.modules.setting.enums.HomeBannerBizTypeEnum;
import com.jeesharp.business.modules.setting.enums.SettingPublishStatusEnum;
import com.jeesharp.business.modules.setting.service.HomeGridIntroService;
import com.jeesharp.business.modules.setting.service.MarketingActivityService;
import com.jeesharp.business.modules.setting.vo.HomeBannerJumpBizOptionVO;
import com.jeesharp.business.modules.setting.vo.HomeGridIntroQueryVO;
import com.jeesharp.business.modules.setting.vo.MarketingActivityQueryVO;
import com.jeesharp.framework.pojo.Page;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 轮播跳转目标候选项查询与存在性校验（编排各业态 Domain Service 只读查询）。
 *
 * @author jeesharp
 * @since 2026-07-03
 */
@Component
@AllArgsConstructor
public class HomeBannerJumpBizQuerySupport {

    private static final int OPTION_PAGE_SIZE = 20;
    private static final String MARKETING_STATUS_ENABLED = "enabled";

    private final FoodRestaurantService foodRestaurantService;
    private final HomeGridIntroService homeGridIntroService;
    private final MallSpuService mallSpuService;
    private final CouponTemplateService couponTemplateService;
    private final MarketingActivityService marketingActivityService;
    private final BizSceneApi bizSceneApi;
    private final AdminInProcessListClient adminInProcessListClient;

    public List<HomeBannerJumpBizOptionVO> listOptions(String bizTypeCode, String keyword) {
        String canonical = BizSceneCouponLegacySupport.resolveCanonicalSceneCode(bizTypeCode);
        if (StrUtil.isBlank(canonical)) {
            return List.of();
        }
        BizSceneOptionVO scene = bizSceneApi.getOptionByCode(canonical, null);
        if (scene != null) {
            if (hasRegistryListUrl(scene)) {
                return listOptionsByRegistry(scene, keyword);
            }
            return List.of();
        }
        HomeBannerBizTypeEnum biz = HomeBannerBizTypeEnum.fromCode(canonical);
        if (biz != null) {
            return listOptionsByEnum(biz, keyword);
        }
        return List.of();
    }

    private static boolean hasRegistryListUrl(BizSceneOptionVO scene) {
        if (scene == null) {
            return false;
        }
        BizScenePickerSupport.PickerFields picker =
                BizScenePickerSupport.resolve(scene, BizScenePickerSupport.PICKER_BANNER_TARGET);
        return StrUtil.isNotBlank(picker.getListUrl());
    }

    private List<HomeBannerJumpBizOptionVO> listOptionsByRegistry(BizSceneOptionVO scene, String keyword) {
        BizScenePickerSupport.PickerFields picker =
                BizScenePickerSupport.resolve(scene, BizScenePickerSupport.PICKER_BANNER_TARGET);
        if (StrUtil.isBlank(picker.getListUrl())) {
            return List.of();
        }
        String body = BizSceneAdminListRecordSupport.buildListRequestBody(
                picker.getKeywordField(), StrUtil.nullToEmpty(keyword).trim(), OPTION_PAGE_SIZE);
        String response = adminInProcessListClient.postAdminList(picker.getListUrl(), body);
        List<BizSceneAdminListRecordSupport.AdminListRow> rows =
                BizSceneAdminListRecordSupport.parseRows(response, picker.getNameField());
        List<HomeBannerJumpBizOptionVO> out = new ArrayList<>();
        for (BizSceneAdminListRecordSupport.AdminListRow row : rows) {
            HomeBannerJumpBizOptionVO vo = new HomeBannerJumpBizOptionVO();
            vo.setId(row.getId());
            vo.setLabel(row.getLabel());
            out.add(vo);
        }
        return out;
    }

    private List<HomeBannerJumpBizOptionVO> listOptionsByEnum(HomeBannerBizTypeEnum biz, String keyword) {
        String kw = StrUtil.nullToEmpty(keyword).trim();
        return switch (biz) {
            case FOOD_RESTAURANT -> {
                FoodRestaurantQueryVO q = foodQuery(kw);
                yield mapFoodOptions(foodRestaurantService.findPage(new Page<>(q), q));
            }
            case HOME_GRID_INTRO -> {
                HomeGridIntroQueryVO q = introQuery(kw);
                yield mapIntroOptions(homeGridIntroService.findPage(new Page<>(q), q));
            }
            case MALL_SPU -> {
                MallSpuQueryVO q = mallSpuQuery(kw);
                yield mapMallSpuOptions(mallSpuService.findPage(new Page<>(q), q));
            }
            case COUPON -> {
                CouponTemplateQueryVO q = couponQuery(kw);
                yield mapCouponOptions(couponTemplateService.findPage(new Page<>(q), q));
            }
            case MARKETING -> {
                MarketingActivityQueryVO q = marketingQuery(kw);
                yield mapMarketingOptions(marketingActivityService.findPage(new Page<>(q), q));
            }
            default -> List.of();
        };
    }

    public void assertBizTargetExists(String bizTypeCode, String bizId) {
        String canonical = BizSceneCouponLegacySupport.resolveCanonicalSceneCode(bizTypeCode);
        if (StrUtil.isBlank(canonical) || StrUtil.isBlank(bizId)) {
            throw new IllegalArgumentException("跳转目标不存在或已下线");
        }
        String id = bizId.trim();
        BizSceneOptionVO scene = bizSceneApi.getOptionByCode(canonical, null);
        if (scene != null) {
            if (hasRegistryListUrl(scene)) {
                assertRegistryTargetExists(scene, id);
                return;
            }
            throw new IllegalArgumentException("跳转目标不存在或已下线");
        }
        HomeBannerBizTypeEnum biz = HomeBannerBizTypeEnum.fromCode(canonical);
        if (biz == null) {
            throw new IllegalArgumentException("跳转目标不存在或已下线");
        }
        boolean ok = switch (biz) {
            case FOOD_RESTAURANT -> isOnline(foodRestaurantService.get(id));
            case HOME_GRID_INTRO -> isPublished(homeGridIntroService.get(id));
            case MALL_SPU -> isOnShelfMallSpu(mallSpuService.get(id));
            case COUPON -> isClaimableCoupon(couponTemplateService.get(id));
            case MARKETING -> isEnabledMarketing(marketingActivityService.get(id));
            default -> false;
        };
        if (!ok) {
            throw new IllegalArgumentException("跳转目标不存在或已下线");
        }
    }

    /**
     * 解析已保存的跳转目标展示名（详情回显、列表展示）。
     */
    public String resolveBizTargetLabel(String bizTypeCode, String bizId) {
        String canonical = BizSceneCouponLegacySupport.resolveCanonicalSceneCode(bizTypeCode);
        if (StrUtil.isBlank(canonical) || StrUtil.isBlank(bizId)) {
            return "";
        }
        String id = bizId.trim();
        BizSceneOptionVO scene = bizSceneApi.getOptionByCode(canonical, null);
        if (scene != null) {
            if (hasRegistryListUrl(scene)) {
                return resolveRegistryTargetLabel(scene, id);
            }
            return "";
        }
        HomeBannerBizTypeEnum biz = HomeBannerBizTypeEnum.fromCode(canonical);
        if (biz == null) {
            return "";
        }
        return switch (biz) {
            case FOOD_RESTAURANT -> labelOf(foodRestaurantService.get(id), FoodRestaurant::getName);
            case HOME_GRID_INTRO -> labelOf(homeGridIntroService.get(id), CmsHomeGridIntro::getTitle);
            case MALL_SPU -> labelOf(mallSpuService.get(id), MallSpu::getSpuName);
            case COUPON -> labelOf(couponTemplateService.get(id), CouponTemplate::getCouponName);
            case MARKETING -> labelOf(marketingActivityService.get(id), MarketingActivity::getActivityName);
            default -> "";
        };
    }

    private void assertRegistryTargetExists(BizSceneOptionVO scene, String id) {
        JSONObject row = loadRegistryInfoRow(scene, id);
        if (!BizSceneAdminListRecordSupport.isSelectableRow(row)) {
            throw new IllegalArgumentException("跳转目标不存在或已下线");
        }
    }

    private String resolveRegistryTargetLabel(BizSceneOptionVO scene, String id) {
        BizScenePickerSupport.PickerFields picker =
                BizScenePickerSupport.resolve(scene, BizScenePickerSupport.PICKER_BANNER_TARGET);
        JSONObject row = loadRegistryInfoRow(scene, id);
        return BizSceneAdminListRecordSupport.resolveRowLabel(row, picker.getNameField());
    }

    private JSONObject loadRegistryInfoRow(BizSceneOptionVO scene, String id) {
        BizScenePickerSupport.PickerFields picker =
                BizScenePickerSupport.resolve(scene, BizScenePickerSupport.PICKER_BANNER_TARGET);
        String response = adminInProcessListClient.getAdminInfo(picker.getListUrl(), id);
        return BizSceneAdminListRecordSupport.parseInfoData(response);
    }

    private static <T> String labelOf(T entity, java.util.function.Function<T, String> labelFn) {
        if (entity == null || labelFn == null) {
            return "";
        }
        return StrUtil.nullToEmpty(labelFn.apply(entity)).trim();
    }

    private static FoodRestaurantQueryVO foodQuery(String keyword) {
        FoodRestaurantQueryVO q = new FoodRestaurantQueryVO();
        q.setPageNo(1L);
        q.setPageSize((long) OPTION_PAGE_SIZE);
        q.setStatus(1);
        if (StrUtil.isNotBlank(keyword)) {
            q.setName(keyword);
        }
        return q;
    }

    private static HomeGridIntroQueryVO introQuery(String keyword) {
        HomeGridIntroQueryVO q = new HomeGridIntroQueryVO();
        q.setPageNo(1L);
        q.setPageSize((long) OPTION_PAGE_SIZE);
        q.setStatus(SettingPublishStatusEnum.PUBLISHED.getValue());
        if (StrUtil.isNotBlank(keyword)) {
            q.setTitle(keyword);
        }
        return q;
    }

    private static MallSpuQueryVO mallSpuQuery(String keyword) {
        MallSpuQueryVO q = new MallSpuQueryVO();
        q.setPageNo(1L);
        q.setPageSize((long) OPTION_PAGE_SIZE);
        q.setStatus(ShelfStatusEnum.ONLINE.getValue());
        if (StrUtil.isNotBlank(keyword)) {
            q.setSpuName(keyword);
        }
        return q;
    }

    private static CouponTemplateQueryVO couponQuery(String keyword) {
        CouponTemplateQueryVO q = new CouponTemplateQueryVO();
        q.setPageNo(1L);
        q.setPageSize((long) OPTION_PAGE_SIZE);
        q.setStatus(CouponTemplateStatusEnum.IN_PROGRESS.getValue());
        if (StrUtil.isNotBlank(keyword)) {
            q.setCouponName(keyword);
        }
        return q;
    }

    private static MarketingActivityQueryVO marketingQuery(String keyword) {
        MarketingActivityQueryVO q = new MarketingActivityQueryVO();
        q.setPageNo(1L);
        q.setPageSize((long) OPTION_PAGE_SIZE);
        q.setStatus(MARKETING_STATUS_ENABLED);
        if (StrUtil.isNotBlank(keyword)) {
            q.setActivityName(keyword);
        }
        return q;
    }

    private static List<HomeBannerJumpBizOptionVO> mapFoodOptions(Page<FoodRestaurant> page) {
        return mapNameOptions(page, FoodRestaurant::getId, FoodRestaurant::getName, FoodRestaurant::getCategory);
    }

    private static List<HomeBannerJumpBizOptionVO> mapIntroOptions(Page<CmsHomeGridIntro> page) {
        return mapNameOptions(page, CmsHomeGridIntro::getId, CmsHomeGridIntro::getTitle, CmsHomeGridIntro::getSummary);
    }

    private static List<HomeBannerJumpBizOptionVO> mapMallSpuOptions(Page<MallSpu> page) {
        return mapNameOptions(page, MallSpu::getId, MallSpu::getSpuName, null);
    }

    private static List<HomeBannerJumpBizOptionVO> mapCouponOptions(Page<CouponTemplate> page) {
        return mapNameOptions(page, CouponTemplate::getId, CouponTemplate::getCouponName, CouponTemplate::getCouponCode);
    }

    private static List<HomeBannerJumpBizOptionVO> mapMarketingOptions(Page<MarketingActivity> page) {
        return mapNameOptions(page, MarketingActivity::getId, MarketingActivity::getActivityName, MarketingActivity::getActivityType);
    }

    private static <T> List<HomeBannerJumpBizOptionVO> mapNameOptions(
            Page<T> page,
            java.util.function.Function<T, String> idFn,
            java.util.function.Function<T, String> labelFn,
            java.util.function.Function<T, String> subFn) {
        if (page == null || page.getRecords() == null || page.getRecords().isEmpty()) {
            return List.of();
        }
        List<HomeBannerJumpBizOptionVO> out = new ArrayList<>();
        for (T row : page.getRecords()) {
            if (row == null || StrUtil.isBlank(idFn.apply(row))) {
                continue;
            }
            HomeBannerJumpBizOptionVO vo = new HomeBannerJumpBizOptionVO();
            vo.setId(idFn.apply(row));
            vo.setLabel(StrUtil.nullToEmpty(labelFn.apply(row)));
            if (subFn != null) {
                vo.setSubLabel(StrUtil.nullToEmpty(subFn.apply(row)));
            }
            out.add(vo);
        }
        return out;
    }

    private static boolean isOnline(FoodRestaurant entity) {
        return entity != null && entity.getStatus() != null && entity.getStatus() == 1;
    }

    private static boolean isPublished(CmsHomeGridIntro entity) {
        return entity != null
                && entity.getStatus() != null
                && SettingPublishStatusEnum.PUBLISHED.getValue().equals(entity.getStatus());
    }

    private static boolean isOnShelfMallSpu(MallSpu entity) {
        return entity != null
                && entity.getStatus() != null
                && ShelfStatusEnum.ONLINE.getValue().equals(entity.getStatus());
    }

    private static boolean isClaimableCoupon(CouponTemplate entity) {
        if (entity == null || entity.getStatus() == null) {
            return false;
        }
        Integer status = entity.getStatus();
        return CouponTemplateStatusEnum.IN_PROGRESS.getValue().equals(status)
                || CouponTemplateStatusEnum.PENDING_START.getValue().equals(status);
    }

    private static boolean isEnabledMarketing(MarketingActivity entity) {
        return entity != null
                && MARKETING_STATUS_ENABLED.equalsIgnoreCase(StrUtil.nullToEmpty(entity.getStatus()).trim());
    }
}
