package com.spot.controller;

import com.spot.entity.ConfigCoinSymbol;
import com.spot.entity.ConfigSymbol;
import com.spot.enums.MessageCode;
import com.spot.enums.SymbolCategoryEnum;
import com.spot.enums.SymbolTagEnum;
import com.spot.resp.AdminSymbolResp;
import com.spot.resp.ApiResultVo;
import com.spot.resp.EnumItemResp;
import com.spot.resp.OpenCoinSymbolResp;
import com.spot.resp.OpenSymbolResp;
import com.spot.service.ConfigCoinSymbolService;
import com.spot.service.ConfigSymbolService;
import com.spot.service.ConfigSymbolSlippageService;
import org.springframework.util.StringUtils;
import com.spot.utils.RequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/v1/config")
public class ConfigController {

    @Autowired
    private ConfigCoinSymbolService configCoinSymbolService;

    @Autowired
    private ConfigSymbolService configSymbolService;

    @Autowired
    private ConfigSymbolSlippageService configSymbolSlippageService;

    @GetMapping("/coin/list")
    @ResponseBody
    public ApiResultVo<List<OpenCoinSymbolResp>> getCoinList(HttpServletRequest request) {
        String lang = RequestUtils.getLangFromHeader(request);
        try {
            List<ConfigCoinSymbol> openCoins = configCoinSymbolService.getOpenCoinSymbols();
            List<OpenCoinSymbolResp> result = openCoins.stream()
                    .map(this::buildOpenCoinSymbolResp)
                    .collect(Collectors.toList());
            return ApiResultVo.success(lang, result);
        } catch (Exception e) {
            log.error("获取币种列表失败", e);
            return ApiResultVo.fail(lang, MessageCode.UNKNOWN_ERROR);
        }
    }

    /**
     * 获取已发布交易对列表
     * 支持按分类和标签过滤，不传则返回全部
     *
     * @param category 分类码（可选），见 SymbolCategoryEnum：0-暂无
     * @param label    标签码（可选），见 SymbolTagEnum：0-暂无，1-减半，2-上新，3-热门，4-ETF
     */
    @GetMapping("/symbol/list")
    @ResponseBody
    public ApiResultVo<List<OpenSymbolResp>> getSymbolList(
            HttpServletRequest request,
            @RequestParam(required = false) Integer category,
            @RequestParam(required = false) String label) {
        String lang = RequestUtils.getLangFromHeader(request);
        try {
            List<ConfigSymbol> symbols = configSymbolService.getPublishedSymbols(category, label);
            List<OpenSymbolResp> result = symbols.stream()
                    .map(s -> buildOpenSymbolResp(s, lang))
                    .collect(Collectors.toList());
            return ApiResultVo.success(lang, result);
        } catch (Exception e) {
            log.error("获取交易对列表失败", e);
            return ApiResultVo.fail(lang, MessageCode.UNKNOWN_ERROR);
        }
    }

    /**
     * 后台获取交易对列表（含各交易对的滑点区间配置）
     *
     * @param request HTTP 请求（用于获取语言标识）
     * @return 交易对列表，每项附带对应的滑点配置列表
     * @author jean
     * @date 2026-05-18
     */
    @GetMapping("/admin/symbol/list")
    @ResponseBody
    public ApiResultVo<List<AdminSymbolResp>> adminSymbolList(HttpServletRequest request) {
        String lang = RequestUtils.getLangFromHeader(request);
        List<ConfigSymbol> symbols = configSymbolService.getAllSymbols();
        List<AdminSymbolResp> result = symbols.stream()
                .map(this::buildAdminSymbolResp)
                .collect(Collectors.toList());
        return ApiResultVo.success(lang, result);
    }

    /**
     * 构建后台交易对响应，附带对应滑点配置列表
     *
     * @param symbol 交易对配置
     * @return 后台交易对响应 VO
     */
    private AdminSymbolResp buildAdminSymbolResp(ConfigSymbol symbol) {
        AdminSymbolResp resp = new AdminSymbolResp();
        resp.setSymbol(symbol);
        resp.setSlippageList(configSymbolSlippageService.listBySymbol(symbol.getSymbol()));
        return resp;
    }

    /**
     * 获取现货交易对标签枚举列表
     * 返回所有 SymbolTagEnum 枚举项的 code 和多语言描述
     *
     * @param request HTTP 请求（用于获取语言标识）
     * @return 标签枚举列表
     */
    @GetMapping("/symbol/tags")
    @ResponseBody
    public ApiResultVo<List<EnumItemResp>> getSymbolTags(HttpServletRequest request) {
        String lang = RequestUtils.getLangFromHeader(request);
        List<EnumItemResp> result = Arrays.stream(SymbolTagEnum.values())
                .map(tag -> new EnumItemResp(tag.getCode(), tag.getDesc(lang)))
                .collect(Collectors.toList());
        return ApiResultVo.success(lang, result);
    }

    /**
     * 获取现货交易对分类枚举列表
     * 返回所有 SymbolCategoryEnum 枚举项的 code 和多语言描述
     *
     * @param request HTTP 请求（用于获取语言标识）
     * @return 分类枚举列表
     */
    @GetMapping("/symbol/categories")
    @ResponseBody
    public ApiResultVo<List<EnumItemResp>> getSymbolCategories(HttpServletRequest request) {
        String lang = RequestUtils.getLangFromHeader(request);
        List<EnumItemResp> result = Arrays.stream(SymbolCategoryEnum.values())
                .map(cat -> new EnumItemResp(cat.getCode(), cat.getDesc(lang)))
                .collect(Collectors.toList());
        return ApiResultVo.success(lang, result);
    }

    private OpenCoinSymbolResp buildOpenCoinSymbolResp(ConfigCoinSymbol coin) {
        OpenCoinSymbolResp resp = new OpenCoinSymbolResp();
        resp.setSymbol(coin.getCoinSymbol());
        resp.setName(coin.getName());
        resp.setIcon(coin.getIcon());
        resp.setShowPrecision(coin.getShowPrecision());
        resp.setIsQuote(coin.getIsQuote());
        return resp;
    }

    /**
     * 将交易对配置转换为响应 VO，分类和标签描述根据语言返回对应翻译
     *
     * @param symbol 交易对配置
     * @param lang   语言标识（如 zh_CN、en_US）
     * @return 交易对响应 VO
     */
    private OpenSymbolResp buildOpenSymbolResp(ConfigSymbol symbol, String lang) {
        OpenSymbolResp resp = new OpenSymbolResp();
        resp.setSymbol(symbol.getSymbol());
        resp.setBase(symbol.getBase());
        resp.setQuote(symbol.getQuote());

        // 取基准币图标
        if (StringUtils.hasText(symbol.getBase())) {
            ConfigCoinSymbol baseCoin = configCoinSymbolService.getConfigCoinSymbol(symbol.getBase());
            if (baseCoin != null) {
                resp.setIcon(baseCoin.getIcon());
            }
        }
        resp.setPricePre(symbol.getPricePre());
        resp.setVolumePre(symbol.getVolumePre());
        resp.setTakerFee(symbol.getTakerFee());
        resp.setMakerFee(symbol.getMakerFee());
        resp.setLimitPriceMin(symbol.getLimitPriceMin());
        resp.setLimitVolumeMin(symbol.getLimitVolumeMin());
        resp.setMarketBuyMin(symbol.getMarketBuyMin());
        resp.setMarketSellMin(symbol.getMarketSellMin());
        resp.setDepth0Pre(symbol.getDepth0Pre());
        resp.setDepth1Pre(symbol.getDepth1Pre());
        resp.setDepth2Pre(symbol.getDepth2Pre());
        resp.setSort(symbol.getSort());
        resp.setDescription(symbol.getDescription());

        // 分类码 + 多语言描述
        resp.setCategory(symbol.getCategory());
        SymbolCategoryEnum categoryEnum = SymbolCategoryEnum.fromCode(symbol.getCategory());
        resp.setCategoryDesc(categoryEnum != null ? categoryEnum.getDesc(lang) : null);

        // 标签码 + 多语言描述
        resp.setLabel(symbol.getLabel());
        SymbolTagEnum tagEnum = SymbolTagEnum.fromCode(symbol.getLabel());
        resp.setLabelDesc(tagEnum != null ? tagEnum.getDesc(lang) : null);

        // 填充滑点区间配置列表
        resp.setSlippageList(configSymbolSlippageService.listBySymbol(symbol.getSymbol()));

        return resp;
    }
}
