package com.jeesharp.business.member.controller;

import com.jeesharp.business.member.support.CouponMallCheckoutContextEnricher;
import com.jeesharp.business.modules.coupon.api.MemberCouponMobileApi;
import com.jeesharp.business.modules.coupon.dto.CouponCheckoutContextDTO;
import com.jeesharp.business.modules.coupon.vo.CouponCheckoutListVO;
import com.jeesharp.business.modules.coupon.entity.MemberCoupon;
import com.jeesharp.business.modules.coupon.vo.CouponDemoVO;
import com.jeesharp.business.modules.coupon.vo.CouponTemplateQueryVO;
import com.jeesharp.business.modules.coupon.vo.MemberCouponInfoVO;
import com.jeesharp.business.modules.coupon.vo.MemberCouponListVO;
import com.jeesharp.business.modules.coupon.vo.MemberCouponQueryVO;
import com.jeesharp.framework.memberauth.utils.MemberAuthUtils;
import com.jeesharp.framework.memberauth.web.BaseMobileController;
import com.jeesharp.framework.pojo.AjaxResult;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 移动端会员优惠券接口：可领列表、领取、我的券、试算与积分兑换。
 *
 * @author jeesharp
 * @since 2026-05-07
 */
@Slf4j
@RestController
@RequestMapping("${jeesharp.web.mobilePath}/member/coupon")
@Tag(name = "移动端-优惠券", description = "优惠券领取、查询、试算等接口")
@AllArgsConstructor
public class CouponMobileController extends BaseMobileController {

    private final MemberCouponMobileApi memberCouponMobileApi;
    private final CouponMallCheckoutContextEnricher couponMallCheckoutContextEnricher;

    @Operation(summary = "获取可领取优惠券列表")
    @PostMapping("/available")
    public AjaxResult<Map<String, Object>> available(@RequestBody(required = false) Map<String, Object> params) {
        String memberId = MemberAuthUtils.getLoginUserId();
        CouponTemplateQueryVO q = new CouponTemplateQueryVO();
        if (params != null) {
            Object p = params.get("pageNo");
            Object s = params.get("pageSize");
            if (p instanceof Number) {
                q.setPageNo(((Number) p).longValue());
            }
            if (s instanceof Number) {
                q.setPageSize(((Number) s).longValue());
            }
            if (params.get("couponName") instanceof String str && !str.isBlank()) {
                q.setCouponName(str.trim());
            }
            if (params.get("couponCode") instanceof String str && !str.isBlank()) {
                q.setCouponCode(str.trim());
            }
            if (params.get("couponType") instanceof Number n) {
                q.setCouponType(n.intValue());
            }
        }
        PageRespVO<CouponDemoVO> page =
                memberCouponMobileApi.pageTemplateDemos(memberId, q);
        Map<String, Object> data = new HashMap<>();
        data.put("pageNo", page.getPageNo());
        data.put("pageSize", page.getPageSize());
        data.put("totalCount", page.getTotal());
        List<Map<String, Object>> list = page.getRecords().stream().map(this::demoToAvailableRow).collect(Collectors.toList());
        data.put("list", list);
        return AjaxResult.okData(data);
    }

    private Map<String, Object> demoToAvailableRow(CouponDemoVO d) {
        Map<String, Object> item = new HashMap<>();
        item.put("templateId", d.getId());
        item.put("couponName", d.getName());
        item.put("couponType", typeLabelToInt(d.getCouponType()));
        item.put("couponTypeName", d.getCouponType());
        item.put("discountType", 1);
        item.put("discountValue", parseMoneyFace(d.getFace()));
        item.put("minConsumeAmount", BigDecimal.ZERO);
        item.put("validStartDate", d.getValidFrom());
        item.put("validEndDate", d.getValidTo());
        item.put("remainCount", d.getRemainQuota());
        item.put("isReceived", "已领取".equals(d.getStatus()));
        item.put("perMemberLimit", 1);
        item.put("receivedCount", "已领取".equals(d.getStatus()) ? 1 : 0);
        return item;
    }

    private static int typeLabelToInt(String label) {
        if (label == null) {
            return 1;
        }
        if (label.contains("折扣")) {
            return 2;
        }
        if (label.contains("兑换")) {
            return 4;
        }
        return 1;
    }

    private static BigDecimal parseMoneyFace(String face) {
        if (face == null || !face.startsWith("¥")) {
            return BigDecimal.ZERO;
        }
        try {
            return new BigDecimal(face.substring(1));
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }

    @Operation(summary = "领取优惠券")
    @PostMapping("/receive")
    public AjaxResult<Map<String, Object>> receive(@RequestBody Map<String, String> params) {
        String memberId = MemberAuthUtils.getLoginUserId();
        String templateId = params.get("templateId");
        Map<String, Object> data = memberCouponMobileApi.receiveManual(memberId, templateId);
        return AjaxResult.ok("领取成功", data);
    }

    @Operation(summary = "获取我的优惠券列表")
    @PostMapping("/my")
    public AjaxResult<Map<String, Object>> my(@RequestBody(required = false) Map<String, Object> params) {
        return buildMyCouponPage(params);
    }

    /**
     * 与详细设计文档示例路径 {@code /mobile/member/coupon/myList} 对齐，语义同 {@link #my}。
     */
    @Operation(summary = "我的优惠券列表（myList）")
    @PostMapping("/myList")
    public AjaxResult<Map<String, Object>> myList(@RequestBody(required = false) Map<String, Object> params) {
        return buildMyCouponPage(params);
    }

    private AjaxResult<Map<String, Object>> buildMyCouponPage(Map<String, Object> params) {
        String memberId = MemberAuthUtils.getLoginUserId();
        MemberCouponQueryVO query = new MemberCouponQueryVO();
        if (params != null) {
            query.setPageNo(parseLongParam(params.get("pageNo"), query.getPageNo()));
            query.setPageSize(parseLongParam(params.get("pageSize"), query.getPageSize()));
            Object st = params.get("status");
            if (st instanceof Number) {
                query.setStatus(((Number) st).intValue());
            } else if (st != null && StrUtil.isNotBlank(String.valueOf(st))) {
                try {
                    query.setStatus(Integer.parseInt(String.valueOf(st).trim()));
                } catch (NumberFormatException ignored) {
                    // keep null
                }
            }
        }
        Page<MemberCoupon> page = new Page<>(query);
        PageRespVO<MemberCouponListVO> pr = memberCouponMobileApi.pageMyCoupons(memberId, page, query);
        Map<String, Object> data = new HashMap<>();
        data.put("pageNo", pr.getPageNo());
        data.put("pageSize", pr.getPageSize());
        data.put("totalCount", pr.getTotal());
        List<Map<String, Object>> list = pr.getRecords().stream().map(this::listVoToMyRow).collect(Collectors.toList());
        data.put("list", list);
        return AjaxResult.okData(data);
    }

    private Map<String, Object> listVoToMyRow(MemberCouponListVO v) {
        Map<String, Object> item = new HashMap<>();
        item.put("couponId", v.getId());
        item.put("couponSn", v.getCouponSn());
        item.put("couponName", v.getCouponName());
        item.put("couponType", v.getCouponType());
        item.put("couponTypeName", v.getCouponTypeName());
        item.put("discountType", v.getDiscountType());
        item.put("discountValue", v.getDiscountValue());
        item.put("minConsumeAmount", v.getMinConsumeAmount());
        item.put("validStartDate", v.getValidStartDate());
        item.put("validEndDate", v.getValidEndDate());
        item.put("status", v.getStatus());
        item.put("statusName", v.getStatusName());
        item.put("sceneCode", v.getSceneCode());
        item.put("sceneName", v.getSceneName());
        item.put("useScope", v.getUseScope());
        item.put("useScopeName", StrUtil.blankToDefault(v.getUseScopeName(), "全场通用"));
        return item;
    }

    @Operation(summary = "获取优惠券详情")
    @GetMapping("/detail")
    public AjaxResult<Map<String, Object>> detail(@RequestParam("couponId") String couponId) {
        String memberId = MemberAuthUtils.getLoginUserId();
        MemberCouponInfoVO vo = memberCouponMobileApi.getMemberCouponInfo(memberId, couponId);
        Map<String, Object> data = new HashMap<>();
        data.put("couponId", vo.getId());
        data.put("couponSn", vo.getCouponSn());
        data.put("couponName", vo.getCouponName());
        data.put("couponType", vo.getCouponType());
        data.put("discountValue", vo.getDiscountValue());
        data.put("minConsumeAmount", vo.getMinConsumeAmount());
        data.put("validStartDate", vo.getValidStartDate());
        data.put("validEndDate", vo.getValidEndDate());
        data.put("status", vo.getStatus());
        data.put("sceneCode", vo.getSceneCode());
        data.put("sceneName", vo.getSceneName());
        data.put("useScope", vo.getUseScope());
        data.put("useScopeName", StrUtil.blankToDefault(vo.getUseScopeName(), "全场通用"));
        data.put("description", vo.getCouponTypeName());
        data.put("usePlatforms", List.of("APP", "MINI", "H5"));
        return AjaxResult.okData(data);
    }

    /**
     * 已领取消费券的「卡面」详情（与领券中心 {@link CouponDemoVO} 形态一致，便于小程序复用组件）。
     */
    @Operation(summary = "我的消费券卡面详情")
    @GetMapping("/walletDetail")
    public AjaxResult<CouponDemoVO> walletDetail(@RequestParam("memberCouponId") String memberCouponId) {
        String memberId = MemberAuthUtils.getLoginUserId();
        return AjaxResult.okData(memberCouponMobileApi.getMemberCouponDemo(memberCouponId, memberId));
    }

    /**
     * 结算页选券：返回可用/不可用列表（商城会经 {@link CouponMallCheckoutContextEnricher} 补全 SPU/分类/品牌范围）。
     * <p>与下单时 {@link com.jeesharp.business.modules.mall.application.support.MallCouponCheckoutContextSupport} 使用同一套场景码 MALL。</p>
     */
    @Operation(summary = "获取订单可用优惠券")
    @PostMapping("/usable")
    public AjaxResult<Map<String, Object>> usable(@RequestBody Map<String, Object> params) {
        String memberId = MemberAuthUtils.getLoginUserId();
        if (params == null || params.get("orderAmount") == null) {
            return AjaxResult.failMsg("订单金额不能为空");
        }
        BigDecimal orderAmount = new BigDecimal(params.get("orderAmount").toString());
        CouponCheckoutContextDTO context = new CouponCheckoutContextDTO();
        context.setMemberId(memberId);
        context.setOrderAmount(orderAmount);
        if (params.get("sceneCode") instanceof String scene && !scene.isBlank()) {
            context.setSceneCode(scene.trim());
        }
        if (params.get("platform") instanceof String platform && !platform.isBlank()) {
            context.setPlatform(platform.trim());
        }
        context.setScopeItemIds(readStringListParam(params.get("scopeItemIds")));
        context.setCategoryIds(readStringListParam(params.get("categoryIds")));
        context.setBrandIds(readStringListParam(params.get("brandIds")));
        couponMallCheckoutContextEnricher.enrich(context);

        CouponCheckoutListVO checkoutList = memberCouponMobileApi.usableForCheckout(context);
        Map<String, Object> data = new HashMap<>();
        data.put("usableCoupons", checkoutList.getUsableCoupons());
        data.put("unusableCoupons", checkoutList.getUnusableCoupons());
        return AjaxResult.okData(data);
    }

    @SuppressWarnings("unchecked")
    private static List<String> readStringListParam(Object raw) {
        if (raw == null) {
            return List.of();
        }
        if (raw instanceof List<?> list) {
            return list.stream()
                    .filter(Objects::nonNull)
                    .map(String::valueOf)
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    .toList();
        }
        String single = String.valueOf(raw).trim();
        if (single.isEmpty()) {
            return List.of();
        }
        return List.of(single);
    }

    @Operation(summary = "积分兑换优惠券")
    @PostMapping("/exchange")
    public AjaxResult<Map<String, Object>> exchange(@RequestBody Map<String, String> params) {
        String memberId = MemberAuthUtils.getLoginUserId();
        String templateId = params.get("templateId");
        Map<String, Object> data = memberCouponMobileApi.exchangeByPoints(memberId, templateId);
        return AjaxResult.ok("兑换成功", data);
    }

    private static long parseLongParam(Object val, long defaultValue) {
        if (val == null) {
            return defaultValue;
        }
        if (val instanceof Number number) {
            return number.longValue();
        }
        String s = String.valueOf(val).trim();
        if (StrUtil.isBlank(s)) {
            return defaultValue;
        }
        try {
            return Long.parseLong(s);
        } catch (NumberFormatException ignored) {
            return defaultValue;
        }
    }
}
