package com.ycwl.basic.repository;

import com.ycwl.basic.facebody.enums.FaceBodyAdapterType;
import com.ycwl.basic.integration.common.util.ConfigValueUtil;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2ListResponse;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2WithConfigDTO;
import com.ycwl.basic.integration.scenic.service.ScenicIntegrationService;
import com.ycwl.basic.mapper.MpConfigMapper;
import com.ycwl.basic.mapper.MpNotifyConfigMapper;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.mp.MpNotifyConfigEntity;
import com.ycwl.basic.model.pc.mp.ScenicMpNotifyVO;
import com.ycwl.basic.model.pc.scenic.entity.ScenicConfigEntity;
import com.ycwl.basic.model.pc.scenic.entity.ScenicEntity;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.pay.enums.PayAdapterType;
import com.ycwl.basic.storage.enums.StorageType;
import com.ycwl.basic.utils.JacksonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class ScenicRepository {
    @Autowired
    private MpConfigMapper mpConfigMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ScenicIntegrationService scenicIntegrationService;

    public static final String SCENIC_CACHE_KEY = "scenic:%s";
    public static final String SCENIC_BASIC_CACHE_KEY = "scenic:basic:%s";
    public static final String SCENIC_FULL_CACHE_KEY = "scenic:f%s";
    public static final String SCENIC_CONFIG_CACHE_KEY = "scenic:%s:config";
    public static final String SCENIC_MP_CACHE_KEY = "scenic:%s:mp";
    public static final String SCENIC_MP_NOTIFY_CACHE_KEY = "scenic:%s:mpNotify";
    @Autowired
    private MpNotifyConfigMapper mpNotifyConfigMapper;

    public ScenicV2DTO getScenicBasic(Long id) {
        String key = String.format(SCENIC_BASIC_CACHE_KEY, id);
        try {
            ScenicV2DTO scenicDTO = scenicIntegrationService.getScenic(id);
            
            // 请求成功，写入缓存
            if (scenicDTO != null) {
                redisTemplate.opsForValue().set(
                    key,
                    JacksonUtil.toJSONString(scenicDTO)
                );
            }
            return scenicDTO;
        } catch (Exception e) {
            // 请求失败，尝试从缓存获取历史成功数据
            String cacheKey = key;
            if (redisTemplate.hasKey(cacheKey)) {
                return JacksonUtil.parseObject(redisTemplate.opsForValue().get(cacheKey), ScenicV2DTO.class);
            }
            // 缓存也没有，返回null
            return null;
        }
    }

    public ScenicEntity getScenic(Long id) {
        String key = String.format(SCENIC_CACHE_KEY, id);
        try {
            ScenicV2WithConfigDTO scenicDTO = scenicIntegrationService.getScenicWithConfig(id);
            ScenicEntity scenicEntity = convertToScenicEntity(scenicDTO);
            
            // 请求成功，写入缓存
            if (scenicEntity != null) {
                redisTemplate.opsForValue().set(
                        key,
                    JacksonUtil.toJSONString(scenicEntity)
                );
            }
            return scenicEntity;
        } catch (Exception e) {
            // 请求失败，尝试从缓存获取历史成功数据
            String cacheKey = key;
            if (redisTemplate.hasKey(cacheKey)) {
                return JacksonUtil.parseObject(redisTemplate.opsForValue().get(cacheKey), ScenicEntity.class);
            }
            // 缓存也没有，返回null
            return null;
        }
    }

    public ScenicConfigEntity getScenicConfig(Long scenicId) {
        String key = String.format(SCENIC_CONFIG_CACHE_KEY, scenicId);
        try {
            ScenicV2WithConfigDTO scenicWithConfigDTO = scenicIntegrationService.getScenicWithConfig(scenicId);
            ScenicConfigEntity configEntity = convertToScenicConfigEntity(scenicWithConfigDTO, scenicId);
            
            // 请求成功，写入缓存
            if (configEntity != null) {
                redisTemplate.opsForValue().set(
                        key,
                    JacksonUtil.toJSONString(configEntity)
                );
            }
            return configEntity;
        } catch (Exception e) {
            // 请求失败，尝试从缓存获取历史成功数据
            String cacheKey = key;
            if (redisTemplate.hasKey(cacheKey)) {
                return JacksonUtil.parseObject(redisTemplate.opsForValue().get(cacheKey), ScenicConfigEntity.class);
            }
            // 缓存也没有，返回null
            return null;
        }
    }

    public MpConfigEntity getScenicMpConfig(Long scenicId) {
        if (redisTemplate.hasKey(String.format(SCENIC_MP_CACHE_KEY, scenicId))) {
            return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(SCENIC_MP_CACHE_KEY, scenicId)), MpConfigEntity.class);
        }
        ScenicEntity scenic = getScenic(scenicId);
        MpConfigEntity mpConfigEntity = mpConfigMapper.selectById(scenic.getMpId());
        if (mpConfigEntity != null) {
            redisTemplate.opsForValue().set(String.format(SCENIC_MP_CACHE_KEY, scenicId), JacksonUtil.toJSONString(mpConfigEntity));
        }
        return mpConfigEntity;
    }

    public ScenicMpNotifyVO getScenicMpNotifyConfig(Long scenicId) {
        if (redisTemplate.hasKey(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId))) {
            return JacksonUtil.parseObject(redisTemplate.opsForValue().get(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId)), ScenicMpNotifyVO.class);
        }
        MpConfigEntity mpConfig = getScenicMpConfig(scenicId);
        if (mpConfig == null) {
            return null;
        }
        ScenicMpNotifyVO mpNotifyConfig = new ScenicMpNotifyVO();
        mpNotifyConfig.setAppId(mpConfig.getAppId());
        mpNotifyConfig.setAppSecret(mpConfig.getAppSecret());
        mpNotifyConfig.setMpId(mpConfig.getId());
        mpNotifyConfig.setAppState(mpConfig.getState());
        List<MpNotifyConfigEntity> mpNotifyConfigList = mpNotifyConfigMapper.listByMpId(mpConfig.getId());
        mpNotifyConfigList.forEach(item -> {
            switch (item.getType()) {
                case 0:
                    mpNotifyConfig.setVideoGeneratedTemplateId(item.getTemplateId());
                    break;
                case 1:
                    mpNotifyConfig.setVideoDownloadTemplateId(item.getTemplateId());
                    break;
                case 2:
                    mpNotifyConfig.setVideoPreExpireTemplateId(item.getTemplateId());
                    break;
            }
        });
        redisTemplate.opsForValue().set(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId), JacksonUtil.toJSONString(mpNotifyConfig));
        return mpNotifyConfig;
    }

    public String getVideoGeneratedTemplateId(Long scenicId) {
        ScenicMpNotifyVO scenicMpNotifyConfig = getScenicMpNotifyConfig(scenicId);
        if (scenicMpNotifyConfig != null) {
            return scenicMpNotifyConfig.getVideoGeneratedTemplateId();
        }
        return null;
    }

    public String getVideoDownloadTemplateId(Long scenicId) {
        ScenicMpNotifyVO scenicMpNotifyConfig = getScenicMpNotifyConfig(scenicId);
        if (scenicMpNotifyConfig != null) {
            return scenicMpNotifyConfig.getVideoDownloadTemplateId();
        }
        return null;
    }

    public String getVideoPreExpireTemplateId(Long scenicId) {
        ScenicMpNotifyVO scenicMpNotifyConfig = getScenicMpNotifyConfig(scenicId);
        if (scenicMpNotifyConfig != null) {
            return scenicMpNotifyConfig.getVideoPreExpireTemplateId();
        }
        return null;
    }

    public List<ScenicV2DTO> list(ScenicReqQuery scenicReqQuery) {
        try {
            // 将 ScenicReqQuery 参数转换为 zt-scenic 服务需要的参数
            Integer page = scenicReqQuery.getPageNum();
            Integer pageSize = scenicReqQuery.getPageSize();
            Integer status = null;
            if (scenicReqQuery.getStatus() != null) {
                status = Integer.valueOf(scenicReqQuery.getStatus());
            }
            String name = scenicReqQuery.getName();
            
            // 调用 zt-scenic 服务的 list 方法
            ScenicV2ListResponse response = scenicIntegrationService.listScenics(page, pageSize, status, name);
            
            // 将 ScenicV2DTO 列表转换为 ScenicEntity 列表
            if (response != null && response.getList() != null) {
                return response.getList();
            }
            return new java.util.ArrayList<>();
        } catch (Exception e) {
            // 如果调用失败，返回空列表
            return new java.util.ArrayList<>();
        }
    }

    public void clearCache(Long scenicId) {
        redisTemplate.delete(String.format(SCENIC_CACHE_KEY, scenicId));
        redisTemplate.delete(String.format(SCENIC_BASIC_CACHE_KEY, scenicId));
        redisTemplate.delete(String.format(SCENIC_FULL_CACHE_KEY, scenicId));
        redisTemplate.delete(String.format(SCENIC_CONFIG_CACHE_KEY, scenicId));
        redisTemplate.delete(String.format(SCENIC_MP_CACHE_KEY, scenicId));
        redisTemplate.delete(String.format(SCENIC_MP_NOTIFY_CACHE_KEY, scenicId));
    }
    
    private ScenicEntity convertToScenicEntity(ScenicV2DTO dto) {
        if (dto == null) {
            return null;
        }
        ScenicEntity entity = new ScenicEntity();
        entity.setId(Long.parseLong(dto.getId()));
        entity.setName(dto.getName());
        entity.setMpId(dto.getMpId());
        entity.setStatus(dto.getStatus().toString());
        return entity;
    }

    private ScenicEntity convertToScenicEntity(ScenicV2WithConfigDTO dto) {
        if (dto == null) {
            return null;
        }
        ScenicEntity entity = new ScenicEntity();
        entity.setId(Long.parseLong(dto.getId()));
        entity.setName(dto.getName());
        entity.setMpId(dto.getMpId());
        entity.setStatus(dto.getStatus().toString());
        if (dto.getConfig() != null) {
            entity.setAddress(ConfigValueUtil.getStringValue(dto.getConfig(), "address"));
            entity.setArea(ConfigValueUtil.getStringValue(dto.getConfig(), "area"));
            entity.setCity(ConfigValueUtil.getStringValue(dto.getConfig(), "city"));
            entity.setProvince(ConfigValueUtil.getStringValue(dto.getConfig(), "province"));
            entity.setLatitude(ConfigValueUtil.getBigDecimalValue(dto.getConfig(), "latitude"));
            entity.setLongitude(ConfigValueUtil.getBigDecimalValue(dto.getConfig(), "longitude"));
            entity.setRadius(ConfigValueUtil.getBigDecimalValue(dto.getConfig(), "radius"));
            entity.setPhone(ConfigValueUtil.getStringValue(dto.getConfig(), "phone"));
            entity.setLogoUrl(ConfigValueUtil.getStringValue(dto.getConfig(), "logoUrl"));
            entity.setCoverUrl(ConfigValueUtil.getStringValue(dto.getConfig(), "coverUrl"));
            entity.setKfCodeUrl(ConfigValueUtil.getStringValue(dto.getConfig(), "kfCodeUrl"));
        }
        return entity;
    }

    private ScenicConfigEntity convertToScenicConfigEntity(ScenicV2WithConfigDTO dto, Long scenicId) {
        if (dto == null || dto.getConfig() == null) {
            return null;
        }
        
        ScenicConfigEntity entity = new ScenicConfigEntity();
        entity.setScenicId(scenicId);
        
        java.util.Map<String, Object> config = dto.getConfig();
        
        entity.setBookRoutine(ConfigValueUtil.getIntValue(config, "bookRoutine"));
        entity.setForceFinishTime(ConfigValueUtil.getIntValue(config, "forceFinishTime"));
        entity.setTourTime(ConfigValueUtil.getIntValue(config, "tourTime"));
        entity.setSampleStoreDay(ConfigValueUtil.getIntValue(config, "sampleStoreDay"));
        entity.setFaceStoreDay(ConfigValueUtil.getIntValue(config, "faceStoreDay"));
        entity.setVideoStoreDay(ConfigValueUtil.getIntValue(config, "videoStoreDay"));
        entity.setAllFree(ConfigValueUtil.getBooleanValue(config, "allFree"));
        entity.setDisableSourceVideo(ConfigValueUtil.getBooleanValue(config, "disableSourceVideo"));
        entity.setDisableSourceImage(ConfigValueUtil.getBooleanValue(config, "disableSourceImage"));
        entity.setTemplateNewVideoType(ConfigValueUtil.getIntValue(config, "templateNewVideoType"));
        entity.setAntiScreenRecordType(ConfigValueUtil.getIntValue(config, "antiScreenRecordType"));
        entity.setVideoSourceStoreDay(ConfigValueUtil.getIntValue(config, "videoSourceStoreDay"));
        entity.setImageSourceStoreDay(ConfigValueUtil.getIntValue(config, "imageSourceStoreDay"));
        entity.setUserSourceExpireDay(ConfigValueUtil.getIntValue(config, "userSourceExpireDay"));
        entity.setFaceDetectHelperThreshold(ConfigValueUtil.getIntValue(config, "faceDetectHelperThreshold"));
        entity.setPhotoFreeNum(ConfigValueUtil.getIntValue(config, "photoFreeNum"));
        entity.setVideoFreeNum(ConfigValueUtil.getIntValue(config, "videoFreeNum"));
        entity.setVoucherEnable(ConfigValueUtil.getBooleanValue(config, "voucherEnable"));
        
        entity.setFaceScoreThreshold(ConfigValueUtil.getFloatValue(config, "faceScoreThreshold"));
        entity.setBrokerDirectRate(ConfigValueUtil.getBigDecimalValue(config, "brokerDirectRate"));
        
        entity.setWatermarkType(ConfigValueUtil.getStringValue(config, "watermarkType"));
        entity.setWatermarkScenicText(ConfigValueUtil.getStringValue(config, "watermarkScenicText"));
        entity.setWatermarkDtFormat(ConfigValueUtil.getStringValue(config, "watermarkDtFormat"));
        entity.setImageSourcePackHint(ConfigValueUtil.getStringValue(config, "imageSourcePackHint"));
        entity.setVideoSourcePackHint(ConfigValueUtil.getStringValue(config, "videoSourcePackHint"));
        entity.setExtraNotificationTime(ConfigValueUtil.getStringValue(config, "extraNotificationTime"));
        
        entity.setStoreType(ConfigValueUtil.getEnumValue(config, "storeType", StorageType.class));
        entity.setStoreConfigJson(ConfigValueUtil.getStringValue(config, "storeConfigJson"));
        entity.setTmpStoreType(ConfigValueUtil.getEnumValue(config, "tmpStoreType", StorageType.class));
        entity.setTmpStoreConfigJson(ConfigValueUtil.getStringValue(config, "tmpStoreConfigJson"));
        entity.setLocalStoreType(ConfigValueUtil.getEnumValue(config, "localStoreType", StorageType.class));
        entity.setLocalStoreConfigJson(ConfigValueUtil.getStringValue(config, "localStoreConfigJson"));
        
        entity.setFaceType(ConfigValueUtil.getEnumValue(config, "faceType", FaceBodyAdapterType.class));
        entity.setFaceConfigJson(ConfigValueUtil.getStringValue(config, "faceConfigJson"));
        
        entity.setPayType(ConfigValueUtil.getEnumValue(config, "payType", PayAdapterType.class));
        entity.setPayConfigJson(ConfigValueUtil.getStringValue(config, "payConfigJson"));
        
        return entity;
    }

}
