package com.nanri.aiimage.modules.productrisk.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nanri.aiimage.common.exception.BusinessException;
import com.nanri.aiimage.modules.productrisk.mapper.ProductRiskCountryPrefMapper;
import com.nanri.aiimage.modules.productrisk.mapper.ProductRiskShopCandidateMapper;
import com.nanri.aiimage.modules.productrisk.model.dto.ProductRiskCandidateAddRequest;
import com.nanri.aiimage.modules.productrisk.model.dto.ProductRiskCountryPreferenceSaveRequest;
import com.nanri.aiimage.modules.productrisk.model.dto.ProductRiskMatchShopsRequest;
import com.nanri.aiimage.modules.productrisk.model.entity.ProductRiskCountryPrefEntity;
import com.nanri.aiimage.modules.productrisk.model.entity.ProductRiskShopCandidateEntity;
import com.nanri.aiimage.modules.productrisk.model.enums.ProductRiskCountryCode;
import com.nanri.aiimage.modules.productrisk.model.vo.ProductRiskCandidateVo;
import com.nanri.aiimage.modules.productrisk.model.vo.ProductRiskCountryPreferenceVo;
import com.nanri.aiimage.modules.productrisk.model.vo.ProductRiskMatchShopsVo;
import com.nanri.aiimage.modules.productrisk.model.vo.ProductRiskShopQueueItemVo;
import com.nanri.aiimage.modules.ziniao.model.vo.ZiniaoShopMatchResultVo;
import com.nanri.aiimage.modules.ziniao.service.ZiniaoShopIndexService;
import com.nanri.aiimage.modules.ziniao.service.ZiniaoShopSwitchService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class ProductRiskResolveService {

    /**
     * 默认处理顺序：德国 → 英国 → 法国 → 意大利 → 西班牙（与前端一致）。
     */
    public static final List<String> DEFAULT_COUNTRY_PREFERENCE_ORDER = List.of("DE", "UK", "FR", "IT", "ES");

    private final ProductRiskShopCandidateMapper candidateMapper;
    private final ProductRiskCountryPrefMapper countryPrefMapper;
    private final ObjectMapper objectMapper;
    private final ZiniaoShopSwitchService ziniaoShopSwitchService;

    public List<ProductRiskCandidateVo> listCandidates(Long userId) {
        if (userId == null || userId <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        List<ProductRiskShopCandidateEntity> rows = candidateMapper.selectList(
                new LambdaQueryWrapper<ProductRiskShopCandidateEntity>()
                        .eq(ProductRiskShopCandidateEntity::getUserId, userId)
                        .orderByDesc(ProductRiskShopCandidateEntity::getId));
        List<ProductRiskCandidateVo> list = new ArrayList<>();
        for (ProductRiskShopCandidateEntity row : rows) {
            if (row == null) {
                continue;
            }
            ProductRiskCandidateVo vo = new ProductRiskCandidateVo();
            vo.setId(row.getId());
            vo.setShopName(row.getShopName());
            vo.setCreatedAt(row.getCreatedAt());
            list.add(vo);
        }
        return list;
    }

    @Transactional
    public ProductRiskCandidateVo addCandidate(ProductRiskCandidateAddRequest request) {
        if (request.getUserId() == null || request.getUserId() <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        String normalized = ziniaoShopSwitchService.normalizeShopName(request.getShopName());
        if (normalized.isBlank()) {
            throw new BusinessException("店铺名不能为空");
        }
        ZiniaoShopMatchResultVo indexHit = ziniaoShopSwitchService.findIndexedStoreByName(normalized, false);
        if (indexHit == null || !indexHit.isMatched()) {
            String hint = indexHit != null && indexHit.getMatchMessage() != null && !indexHit.getMatchMessage().isBlank()
                    ? indexHit.getMatchMessage()
                    : "店铺索引未命中，无法加入备选";
            throw new BusinessException(hint);
        }
        if (ZiniaoShopIndexService.MATCH_STATUS_CONFLICT.equals(indexHit.getMatchStatus())) {
            throw new BusinessException(indexHit.getMatchMessage() != null ? indexHit.getMatchMessage() : "存在多个同名店铺，请人工确认");
        }
        ProductRiskShopCandidateEntity existing = candidateMapper.selectOne(
                new LambdaQueryWrapper<ProductRiskShopCandidateEntity>()
                        .eq(ProductRiskShopCandidateEntity::getUserId, request.getUserId())
                        .eq(ProductRiskShopCandidateEntity::getShopName, normalized)
                        .last("LIMIT 1"));
        if (existing != null) {
            ProductRiskCandidateVo vo = new ProductRiskCandidateVo();
            vo.setId(existing.getId());
            vo.setShopName(existing.getShopName());
            vo.setCreatedAt(existing.getCreatedAt());
            return vo;
        }
        ProductRiskShopCandidateEntity entity = new ProductRiskShopCandidateEntity();
        entity.setUserId(request.getUserId());
        entity.setShopName(normalized);
        entity.setCreatedAt(LocalDateTime.now());
        candidateMapper.insert(entity);
        ProductRiskCandidateVo vo = new ProductRiskCandidateVo();
        vo.setId(entity.getId());
        vo.setShopName(entity.getShopName());
        vo.setCreatedAt(entity.getCreatedAt());
        return vo;
    }

    @Transactional
    public void deleteCandidate(Long userId, Long id) {
        if (userId == null || userId <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        if (id == null || id <= 0) {
            throw new BusinessException("id 不合法");
        }
        ProductRiskShopCandidateEntity row = candidateMapper.selectById(id);
        if (row == null || !userId.equals(row.getUserId())) {
            throw new BusinessException("记录不存在");
        }
        candidateMapper.deleteById(id);
    }

    public ProductRiskMatchShopsVo matchShops(ProductRiskMatchShopsRequest request) {
        if (request.getUserId() == null || request.getUserId() <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        LinkedHashSet<String> ordered = new LinkedHashSet<>();
        for (String raw : request.getShopNames()) {
            String n = ziniaoShopSwitchService.normalizeShopName(raw);
            if (!n.isBlank()) {
                ordered.add(n);
            }
        }
        if (ordered.isEmpty()) {
            throw new BusinessException("shop_names 无有效店铺名");
        }
        ProductRiskMatchShopsVo vo = new ProductRiskMatchShopsVo();
        for (String shopName : ordered) {
            vo.getItems().add(matchOneShop(shopName));
        }
        return vo;
    }

    public ProductRiskCountryPreferenceVo getCountryPreference(Long userId) {
        if (userId == null || userId <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        ProductRiskCountryPrefEntity row = countryPrefMapper.selectById(userId);
        ProductRiskCountryPreferenceVo vo = new ProductRiskCountryPreferenceVo();
        if (row == null || row.getCountryCodesJson() == null || row.getCountryCodesJson().isBlank()) {
            vo.getCountryCodes().addAll(DEFAULT_COUNTRY_PREFERENCE_ORDER);
            return vo;
        }
        try {
            List<String> parsed = objectMapper.readValue(row.getCountryCodesJson(), new TypeReference<List<String>>() {
            });
            vo.getCountryCodes().addAll(sanitizeStoredCodes(parsed));
        } catch (Exception ex) {
            vo.getCountryCodes().addAll(DEFAULT_COUNTRY_PREFERENCE_ORDER);
        }
        return vo;
    }

    @Transactional
    public ProductRiskCountryPreferenceVo saveCountryPreference(ProductRiskCountryPreferenceSaveRequest request) {
        if (request.getUserId() == null || request.getUserId() <= 0) {
            throw new BusinessException("user_id 不合法");
        }
        List<String> normalized = validateCountryCodesForSave(request.getCountryCodes());
        String json;
        try {
            json = objectMapper.writeValueAsString(normalized);
        } catch (Exception ex) {
            throw new BusinessException("保存偏好失败");
        }
        ProductRiskCountryPrefEntity row = countryPrefMapper.selectById(request.getUserId());
        if (row == null) {
            row = new ProductRiskCountryPrefEntity();
            row.setUserId(request.getUserId());
            row.setCountryCodesJson(json);
            countryPrefMapper.insert(row);
        } else {
            row.setCountryCodesJson(json);
            countryPrefMapper.updateById(row);
        }
        ProductRiskCountryPreferenceVo vo = new ProductRiskCountryPreferenceVo();
        vo.getCountryCodes().addAll(normalized);
        return vo;
    }

    private static List<String> sanitizeStoredCodes(List<String> raw) {
        List<String> parsed = parseValidCountryCodes(raw);
        if (parsed.isEmpty()) {
            return new ArrayList<>(DEFAULT_COUNTRY_PREFERENCE_ORDER);
        }
        return parsed;
    }

    private static List<String> validateCountryCodesForSave(List<String> raw) {
        if (raw == null || raw.isEmpty()) {
            throw new BusinessException("country_codes 至少选择 1 个国家");
        }
        LinkedHashSet<String> seen = new LinkedHashSet<>();
        List<String> out = new ArrayList<>();
        for (String s : raw) {
            if (s == null || s.isBlank()) {
                throw new BusinessException("country_codes 含空项");
            }
            String u = s.trim().toUpperCase();
            try {
                ProductRiskCountryCode.valueOf(u);
            } catch (IllegalArgumentException ex) {
                throw new BusinessException("非法国家代码: " + s);
            }
            if (!seen.add(u)) {
                throw new BusinessException("country_codes 存在重复: " + u);
            }
            out.add(u);
        }
        if (out.size() > ProductRiskCountryCode.values().length) {
            throw new BusinessException("country_codes 最多 5 项");
        }
        return out;
    }

    /**
     * 仅保留合法枚举名，去重并保持顺序；非法项静默丢弃（用于读取库内数据）。
     */
    private static List<String> parseValidCountryCodes(List<String> raw) {
        if (raw == null || raw.isEmpty()) {
            return new ArrayList<>();
        }
        LinkedHashSet<String> seen = new LinkedHashSet<>();
        List<String> out = new ArrayList<>();
        for (String s : raw) {
            if (s == null || s.isBlank()) {
                continue;
            }
            String u = s.trim().toUpperCase();
            try {
                ProductRiskCountryCode.valueOf(u);
            } catch (IllegalArgumentException ex) {
                continue;
            }
            if (seen.add(u)) {
                out.add(u);
            }
        }
        return out;
    }

    private ProductRiskShopQueueItemVo matchOneShop(String shopName) {
        ProductRiskShopQueueItemVo item = new ProductRiskShopQueueItemVo();
        item.setShopName(shopName);
        try {
            ZiniaoShopMatchResultVo m = ziniaoShopSwitchService.findIndexedStoreByName(shopName, false);
            if (m == null) {
                item.setMatched(false);
                item.setMatchStatus("PENDING");
                item.setMatchMessage("匹配结果为空");
                return item;
            }
            item.setMatched(m.isMatched());
            item.setShopId(m.getShopId());
            item.setPlatform(m.getPlatform());
            item.setCompanyName(m.getCompanyName());
            item.setMatchedUserId(m.getMatchedUserId());
            item.setMatchStatus(m.getMatchStatus());
            item.setMatchMessage(m.getMatchMessage());
        } catch (BusinessException ex) {
            item.setMatched(false);
            item.setMatchStatus("PENDING");
            item.setMatchMessage(ex.getMessage());
        } catch (Exception ex) {
            item.setMatched(false);
            item.setMatchStatus("PENDING");
            item.setMatchMessage(Objects.toString(ex.getMessage(), "匹配异常"));
        }
        return item;
    }
}
