package com.liquidnet.service.sweet.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.sweet.dto.SweetManualExtConfigDto;
import com.liquidnet.service.sweet.dto.SweetManualPosterTemplateDto;
import com.liquidnet.service.sweet.entity.SweetManual;
import com.liquidnet.service.sweet.mapper.SweetManualMapper;
import com.liquidnet.service.sweet.param.SweetManualExtConfigParam;
import com.liquidnet.service.sweet.param.SweetManualMapGeojsonParam;
import com.liquidnet.service.sweet.service.ISweetManualExtConfigService;
import com.liquidnet.service.sweet.utils.RedisDataUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

@Service
public class SweetManualExtConfigServiceImpl implements ISweetManualExtConfigService {

    private static final Pattern THEME_COLOR_PATTERN = Pattern.compile("^#[0-9A-Fa-f]{6}$");
    private static final Pattern POSTER_DATE_PATTERN = Pattern.compile("^\\d{4}-\\d{2}-\\d{2}$");

    @Autowired
    private SweetManualMapper sweetManualMapper;

    @Autowired
    private RedisDataUtils redisDataUtils;

    @Override
    public ResponseDto<SweetManualExtConfigDto> get(String manualId) {
        SweetManual manual = sweetManualMapper.selectOne(
                Wrappers.lambdaQuery(SweetManual.class).eq(SweetManual::getManualId, manualId));
        if (manual == null) {
            return ResponseDto.failure("手册不存在");
        }
        return ResponseDto.success(toDto(manual));
    }

    @Override
    public ResponseDto<Boolean> save(SweetManualExtConfigParam param) {
        if (StringUtil.isBlank(param.getManualId())) {
            return ResponseDto.failure("手册id不能为空");
        }
        String themeColorError = validateThemeColor(param.getThemeColor());
        if (themeColorError != null) {
            return ResponseDto.failure(themeColorError);
        }
        String posterError = validatePosterTemplates(param.getPosterTemplates());
        if (posterError != null) {
            return ResponseDto.failure(posterError);
        }
        SweetManual exist = sweetManualMapper.selectOne(
                Wrappers.lambdaQuery(SweetManual.class).eq(SweetManual::getManualId, param.getManualId()));
        if (exist == null) {
            return ResponseDto.failure("手册不存在");
        }
        SweetManual update = SweetManual.getNew();
        update.setFoodGuideUrl(nullToEmpty(param.getFoodGuideUrl()));
        update.setAlbumUrl(nullToEmpty(param.getAlbumUrl()));
        update.setLostFoundWjxId(nullToEmpty(param.getLostFoundWjxId()));
        if (param.getMapGeojson() != null) {
            update.setMapGeojson(serializeGeojson(param.getMapGeojson()));
        }
        if (param.getThemeColor() != null) {
            update.setThemeColor(normalizeThemeColor(param.getThemeColor()));
        }
        if (param.getPosterTemplates() != null) {
            update.setPosterTemplates(serializePosterTemplates(param.getPosterTemplates()));
        }
        update.setUpdatedAt(LocalDateTime.now());
        sweetManualMapper.update(update, Wrappers.lambdaUpdate(SweetManual.class)
                .eq(SweetManual::getManualId, param.getManualId()));
        redisDataUtils.setManualExtConfigRedisData(param.getManualId(), toDto(exist, param));
        return ResponseDto.success(true);
    }

    @Override
    public ResponseDto<Object> getMapGeojson(String manualId) {
        SweetManual manual = sweetManualMapper.selectOne(
                Wrappers.lambdaQuery(SweetManual.class).eq(SweetManual::getManualId, manualId));
        if (manual == null) {
            return ResponseDto.failure("手册不存在");
        }
        return ResponseDto.success(parseGeojson(manual.getMapGeojson()));
    }

    @Override
    public ResponseDto<Boolean> saveMapGeojson(SweetManualMapGeojsonParam param) {
        if (StringUtil.isBlank(param.getManualId())) {
            return ResponseDto.failure("手册id不能为空");
        }
        if (param.getMapGeojson() == null) {
            return ResponseDto.failure("地图GeoJSON数据不能为空");
        }
        SweetManual exist = sweetManualMapper.selectOne(
                Wrappers.lambdaQuery(SweetManual.class).eq(SweetManual::getManualId, param.getManualId()));
        if (exist == null) {
            return ResponseDto.failure("手册不存在");
        }
        String geojson = serializeGeojson(param.getMapGeojson());
        SweetManual update = SweetManual.getNew();
        update.setMapGeojson(geojson);
        update.setUpdatedAt(LocalDateTime.now());
        sweetManualMapper.update(update, Wrappers.lambdaUpdate(SweetManual.class)
                .eq(SweetManual::getManualId, param.getManualId()));
        SweetManualExtConfigDto cacheDto = toDto(exist);
        cacheDto.setMapGeojson(parseGeojson(geojson));
        redisDataUtils.setManualExtConfigRedisData(param.getManualId(), cacheDto);
        return ResponseDto.success(true);
    }

    private SweetManualExtConfigDto toDto(SweetManual manual) {
        SweetManualExtConfigDto dto = new SweetManualExtConfigDto();
        dto.setManualId(manual.getManualId());
        dto.setFoodGuideUrl(manual.getFoodGuideUrl());
        dto.setAlbumUrl(manual.getAlbumUrl());
        dto.setLostFoundWjxId(manual.getLostFoundWjxId());
        dto.setMapGeojson(parseGeojson(manual.getMapGeojson()));
        dto.setThemeColor(nullToEmpty(manual.getThemeColor()));
        dto.setPosterTemplates(parsePosterTemplates(manual.getPosterTemplates()));
        return dto;
    }

    private SweetManualExtConfigDto toDto(SweetManual exist, SweetManualExtConfigParam param) {
        SweetManualExtConfigDto dto = new SweetManualExtConfigDto();
        dto.setManualId(param.getManualId());
        dto.setFoodGuideUrl(nullToEmpty(param.getFoodGuideUrl()));
        dto.setAlbumUrl(nullToEmpty(param.getAlbumUrl()));
        dto.setLostFoundWjxId(nullToEmpty(param.getLostFoundWjxId()));
        if (param.getMapGeojson() != null) {
            dto.setMapGeojson(param.getMapGeojson());
        } else {
            dto.setMapGeojson(parseGeojson(exist.getMapGeojson()));
        }
        if (param.getThemeColor() != null) {
            dto.setThemeColor(normalizeThemeColor(param.getThemeColor()));
        } else {
            dto.setThemeColor(nullToEmpty(exist.getThemeColor()));
        }
        if (param.getPosterTemplates() != null) {
            dto.setPosterTemplates(normalizePosterTemplates(param.getPosterTemplates()));
        } else {
            dto.setPosterTemplates(parsePosterTemplates(exist.getPosterTemplates()));
        }
        return dto;
    }

    private Object parseGeojson(String geojson) {
        if (StringUtil.isBlank(geojson)) {
            return null;
        }
        return JsonUtils.fromJson(geojson, Object.class);
    }

    private String serializeGeojson(Object geojson) {
        if (geojson == null) {
            return null;
        }
        if (geojson instanceof String) {
            String json = ((String) geojson).trim();
            return json.isEmpty() ? null : json;
        }
        return JsonUtils.toJson(geojson);
    }

    private List<SweetManualPosterTemplateDto> parsePosterTemplates(String json) {
        if (StringUtil.isBlank(json)) {
            return new ArrayList<>();
        }
        try {
            List<SweetManualPosterTemplateDto> list = JsonUtils.fromJson(json,
                    new TypeReference<List<SweetManualPosterTemplateDto>>() {
                    });
            return list == null ? new ArrayList<>() : list;
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    private String serializePosterTemplates(List<SweetManualPosterTemplateDto> posters) {
        return JsonUtils.toJson(normalizePosterTemplates(posters));
    }

    private List<SweetManualPosterTemplateDto> normalizePosterTemplates(List<SweetManualPosterTemplateDto> posters) {
        List<SweetManualPosterTemplateDto> result = new ArrayList<>();
        if (posters == null) {
            return result;
        }
        for (SweetManualPosterTemplateDto item : posters) {
            if (item == null || StringUtil.isBlank(item.getDate())) {
                continue;
            }
            SweetManualPosterTemplateDto dto = new SweetManualPosterTemplateDto();
            dto.setDate(item.getDate().trim());
            dto.setPosterUrl(nullToEmpty(item.getPosterUrl()).trim());
            result.add(dto);
        }
        return result;
    }

    private String validateThemeColor(String themeColor) {
        if (StringUtil.isBlank(themeColor)) {
            return null;
        }
        if (!THEME_COLOR_PATTERN.matcher(themeColor.trim()).matches()) {
            return "主题色格式不正确，需为 #xxxxxx";
        }
        return null;
    }

    private String normalizeThemeColor(String themeColor) {
        if (StringUtil.isBlank(themeColor)) {
            return "";
        }
        return themeColor.trim().toUpperCase();
    }

    private String validatePosterTemplates(List<SweetManualPosterTemplateDto> posters) {
        if (posters == null) {
            return null;
        }
        for (SweetManualPosterTemplateDto item : posters) {
            if (item == null || StringUtil.isBlank(item.getDate())) {
                return "海报模版日期不能为空";
            }
            if (!POSTER_DATE_PATTERN.matcher(item.getDate().trim()).matches()) {
                return "海报模版日期格式不正确，需为 yyyy-MM-dd";
            }
        }
        return null;
    }

    private String nullToEmpty(String value) {
        return value == null ? "" : value;
    }
}
