package com.ai.da.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ai.da.common.config.exception.BusinessException;
import com.ai.da.common.response.ResultEnum;
import com.ai.da.common.utils.CopyUtil;
import com.ai.da.common.utils.PantoneUtils;
import com.ai.da.mapper.primary.entity.ColorLookupTable;
import com.ai.da.mapper.primary.entity.PanTone;
import com.ai.da.mapper.primary.PanToneMapper;
import com.ai.da.model.dto.GetRgbByHsvBatchDTO;
import com.ai.da.model.vo.PantoneVO;
import com.ai.da.service.ColorLoopUpTableService;
import com.ai.da.service.PanToneService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.netty.util.internal.StringUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class PanToneServiceImpl extends ServiceImpl<PanToneMapper, PanTone> implements PanToneService {

    @Resource
    private PanToneMapper panToneMapper;
    @Resource
    private PanToneService panToneService;
    @Resource
    private ColorLoopUpTableService colorLoopUpTableService;

    @Override
    public PantoneVO getByHSV(Integer h, Integer s, Integer v) {
        int value = (h * 101 * 101) + (s * 101) + v;
        ColorLookupTable colorLookupTable = colorLoopUpTableService.getByColorValue(value);
        if (Objects.isNull(colorLookupTable)) {
            return new PantoneVO();
        }
        QueryWrapper<PanTone> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pantone_index", colorLookupTable.getColorIndex());
        PanTone panTone = panToneMapper.selectOne(queryWrapper);
        if (Objects.isNull(panTone)) {
            return null;
        }
        return coverPanToneToVo(panTone);
    }

    @Override
    public PantoneVO getByTCX(String txc) {
        QueryWrapper<PanTone> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tcx", txc);
        List<PanTone> panTones = panToneMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(panTones)) {
            throw new BusinessException("panTones.not.found", ResultEnum.PROMPT.getCode());
        }
        return coverPanToneToVo(panTones.get(0));
    }

    @Override
    public PantoneVO getByRGB(Integer r, Integer g, Integer b) {
        QueryWrapper<PanTone> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("r", r);
        queryWrapper.eq("g", g);
        queryWrapper.eq("b", b);
        PanTone panTones = panToneMapper.selectOne(queryWrapper);
        return coverPanToneToVo(panTones);
    }

    @Override
    public Map<String, PantoneVO> getPantoneByRgbBatch(List<String> colors) {
        /*HashMap<Integer, String> colorValueRgb = new HashMap<>();
        HashMap<Integer, String> colorIndexRgb = new HashMap<>();
        ArrayList<Integer> values = new ArrayList<>();
        colors.forEach(color -> {
            int[] rgb = Arrays.stream(color.split("\\s+")).mapToInt(Integer::parseInt).toArray();
            int[] hsv = PantoneUtils.rgbToHsv(rgb);

            int value = (hsv[0] * 101 * 101) + (hsv[1] * 101) + hsv[2];
            colorValueRgb.put(value, color);
            values.add(value);
        });
        List<ColorLookupTable> colorValueList = colorLoopUpTableService.getByColorValueList(values);
        colorValueList.forEach(colorValue -> {
            // 不同的colorValue可能会有相同的colorIndex
            colorIndexRgb.put(colorValue.getColorIndex(), colorValueRgb.get(colorValue.getColorValue()));
        });

        List<PanTone> panTones = panToneService.listByIds(colorIndexRgb.keySet()); // pantone数据不完整，导致有的index无对应pantone值
        ArrayList<PantoneVO> pantoneVOS = new ArrayList<>();
        panTones.forEach(panTone -> {
            pantoneVOS.add(coverPanToneToVo(panTone));
        });
        HashMap<String, PantoneVO> colorPantoneVO = new HashMap<>();
        pantoneVOS.forEach(pantoneVO -> {
            int colorIndex = pantoneVO.getId();
            List<ColorLookupTable> collect = colorValueList.stream().filter(colorValue -> colorValue.getColorIndex().equals(colorIndex)).collect(Collectors.toList());
            if (collect.size() > 1) {
                for (ColorLookupTable colorLookupTable : collect) {
                    colorPantoneVO.put(colorValueRgb.get(colorLookupTable.getColorValue()), pantoneVO);
                }
            } else if (collect.size() == 1) {
                colorPantoneVO.put(colorIndexRgb.get(pantoneVO.getId()), pantoneVO);
            }
        });
        // 覆盖pantone中的rgb值,使用前端传过来的rgb值
        for (Map.Entry<String, PantoneVO> pantoneVOEntry : colorPantoneVO.entrySet()) {
            int[] rgb = Arrays.stream(pantoneVOEntry.getKey().split("\\s+")).mapToInt(Integer::parseInt).toArray();
            pantoneVOEntry.getValue().setR(rgb[0]);
            pantoneVOEntry.getValue().setG(rgb[1]);
            pantoneVOEntry.getValue().setB(rgb[2]);
        }
        return colorPantoneVO;*/
        // 用于存储 RGB 值对应的 HSV 计算值
        Map<Integer, String> colorValueRgb = new HashMap<>();
        // 用于存储 ColorIndex 对应的 RGB 值
        Map<Integer, String> colorIndexRgb = new HashMap<>();
        // 存储所有计算出的 HSV 值
        List<Integer> values = new ArrayList<>();

        // 1. 遍历 colors，计算 HSV 值并存储
        colors.forEach(color -> {
            int[] rgb = Arrays.stream(color.split("\\s+")).mapToInt(Integer::parseInt).toArray();
            int[] hsv = PantoneUtils.rgbToHsv(rgb);
            int value = (hsv[0] * 101 * 101) + (hsv[1] * 101) + hsv[2];
            colorValueRgb.put(value, color);
            values.add(value);
        });

        // 2. 查询 ColorLookupTable 数据
        List<ColorLookupTable> colorValueList = colorLoopUpTableService.getByColorValueList(values);
        colorValueList.forEach(colorValue -> {
            colorIndexRgb.put(colorValue.getColorIndex(), colorValueRgb.get(colorValue.getColorValue()));
        });

        // 3. 查询 Pantone 数据
        Set<Integer> colorIndexes = colorIndexRgb.keySet();
        List<PanTone> panTones = panToneService.listByIds(colorIndexes);

        // 4. 将 PanTone 转换为 PantoneVO，并处理缺失的 Pantone 数据
        Map<Integer, PantoneVO> pantoneVOMap = new HashMap<>();
        panTones.forEach(panTone -> {
            pantoneVOMap.put(panTone.getPantoneIndex(), coverPanToneToVo(panTone));
        });

        // 5. 处理缺失的 Pantone 数据，创建默认的 PantoneVO
        for (Integer colorIndex : colorIndexes) {
            String rgbValue = colorIndexRgb.get(colorIndex);
            int[] rgb = Arrays.stream(rgbValue.split("\\s+")).mapToInt(Integer::parseInt).toArray();
            if (!pantoneVOMap.containsKey(colorIndex)) {
                PantoneVO defaultPantoneVO = new PantoneVO();
                defaultPantoneVO.setR(rgb[0]);
                defaultPantoneVO.setG(rgb[1]);
                defaultPantoneVO.setB(rgb[2]);
                pantoneVOMap.put(colorIndex, defaultPantoneVO);
            } else {
                PantoneVO pantoneVO = pantoneVOMap.get(colorIndex);
                pantoneVO.setR(rgb[0]);
                pantoneVO.setG(rgb[1]);
                pantoneVO.setB(rgb[2]);
            }
        }

        // 6. 构建最终结果
        Map<String, PantoneVO> colorPantoneVO = new HashMap<>();
        for (Map.Entry<Integer, PantoneVO> entry : pantoneVOMap.entrySet()) {
            Integer colorIndex = entry.getKey();
            PantoneVO pantoneVO = entry.getValue();
            String rgbValue = colorIndexRgb.get(colorIndex);
            colorPantoneVO.put(rgbValue, pantoneVO);
        }

        return colorPantoneVO;
    }


    @Override
    public PantoneVO getPantoneByRgb(String color) {
        GetRgbByHsvBatchDTO getRgbByHsvBatchDTO = new GetRgbByHsvBatchDTO();
        int[] rgb = Arrays.stream(color.split("\\s+")).mapToInt(Integer::parseInt).toArray();
        int[] hsv = PantoneUtils.rgbToHsv(rgb);
        if (!StringUtil.isNullOrEmpty(color)) {

            getRgbByHsvBatchDTO.setH(hsv[0]);
            getRgbByHsvBatchDTO.setS(hsv[1]);
            getRgbByHsvBatchDTO.setV(hsv[2]);
        }
        PantoneVO pantoneVO = getByHSV(getRgbByHsvBatchDTO.getH(), getRgbByHsvBatchDTO.getS(), getRgbByHsvBatchDTO.getV());
        if (Objects.isNull(pantoneVO)) {
            pantoneVO = new PantoneVO(rgb[0], rgb[1], rgb[2], hsv[0], hsv[1], hsv[2]);
        }
        pantoneVO.setR(rgb[0]);
        pantoneVO.setG(rgb[1]);
        pantoneVO.setB(rgb[2]);
        return pantoneVO;
    }

    @Override
    public List<PantoneVO> getRgbByHsvBatch(List<GetRgbByHsvBatchDTO> hsvBatch) {
        if (hsvBatch.size() > 8) {
            throw new BusinessException("hsv.value.cannot.exceed.the.maximum.of.8", ResultEnum.PROMPT.getCode());
        }
        List<Integer> colorValues = Lists.newArrayList();
        Map<Integer, GetRgbByHsvBatchDTO> valueToHsv = Maps.newHashMap();
        hsvBatch.forEach(hsv -> {
            if (Objects.isNull(hsv)) {
                return;
            }
            Integer h = hsv.getH();
            Integer s = hsv.getS();
            Integer v = hsv.getV();
            int value = (h * 101 * 101) + (s * 101) + v;
            colorValues.add(value);
            valueToHsv.put(value, hsv);
        });
        List<ColorLookupTable> colorLookupTables = colorLoopUpTableService.getByColorValueList(colorValues);
        if (Objects.isNull(colorLookupTables)) {
            return Lists.newArrayList();
        }
        Map<Integer, Integer> IndexToValue = colorLookupTables.stream()
                .collect(Collectors.toMap(v -> v.getColorIndex(), v -> v.getColorValue(), (V1, V2) -> V1));
        QueryWrapper<PanTone> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("pantone_index", colorLookupTables.stream()
                .map(ColorLookupTable::getColorIndex).collect(Collectors.toList()));
        List<PantoneVO> pantoneVOS = coverPanToneToVoList(panToneMapper.selectList(queryWrapper), IndexToValue, valueToHsv, hsvBatch);
        if (pantoneVOS.isEmpty() && hsvBatch.size() == 1){
            int[] rgb = PantoneUtils.hsvToRgb(hsvBatch.get(0).getH(), hsvBatch.get(0).getS(), hsvBatch.get(0).getV());
            pantoneVOS.add(new PantoneVO(rgb[0], rgb[1], rgb[2], hsvBatch.get(0).getH(), hsvBatch.get(0).getS(), hsvBatch.get(0).getV()));
        }
        return pantoneVOS;
    }

    private PantoneVO coverPanToneToVo(PanTone panTone) {
        if (Objects.isNull(panTone)) {
            return null;
        }
        PantoneVO pantoneVO = CopyUtil.copyObject(panTone, PantoneVO.class);
//        pantoneVO.setR(panTone.getR());
//        pantoneVO.setG(panTone.getG());
//        pantoneVO.setB(panTone.getB());
        pantoneVO.setId(panTone.getPantoneIndex());
        return pantoneVO;
    }

    private List<PantoneVO> coverPanToneToVoList(List<PanTone> panTones
            , Map<Integer, Integer> indexToValue, Map<Integer, GetRgbByHsvBatchDTO> valueToHsv,
                                                 List<GetRgbByHsvBatchDTO> hsvBatch) {
        if (CollectionUtil.isEmpty(panTones)) {
            return Lists.newArrayList();
//            throw new BusinessException("panTones.not.found", ResultEnum.PROMPT.getCode());
        }
        List<PantoneVO> templateResposne = CopyUtil.copyList(panTones, PantoneVO.class, (o, d) -> {
            d.setId(o.getPantoneIndex());
            GetRgbByHsvBatchDTO getRgbByHsvBatchDTO = valueToHsv.get(indexToValue.get(o.getPantoneIndex()));
            if (Objects.nonNull(getRgbByHsvBatchDTO)) {
                d.setH(getRgbByHsvBatchDTO.getH());
                d.setS(getRgbByHsvBatchDTO.getS());
                d.setV(getRgbByHsvBatchDTO.getV());
            }
        });
        Map<Integer, PantoneVO> valueToPantoneVo = templateResposne.stream().collect(Collectors.toMap(
                v -> (v.getH() * 101 * 101) + (v.getS() * 101) + v.getV(), Function.identity(), (value1, value2) -> value1
        ));
        List<PantoneVO> response = Lists.newArrayList();
        //排序给前端
        hsvBatch.forEach(hsv -> {
            if (Objects.isNull(hsv)) {
                return;
            }
            int value = (hsv.getH() * 101 * 101) + (hsv.getS() * 101) + hsv.getV();
            PantoneVO pantoneVO = valueToPantoneVo.get(value);
            if (Objects.isNull(pantoneVO)) {
                response.add(new PantoneVO("None", "11-1111"));
            } else {
                response.add(pantoneVO);
            }
        });
        return response;

    }
}
