package com.backendsys.utils;

import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
import com.backendsys.modules.common.config.security.utils.TokenUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.lang.reflect.Field;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@SuppressWarnings({"rawtypes", "unchecked"})
@Component
public class LanguageUtil {

    @Autowired
    private HttpRequestUtil httpRequestUtil;

    @Value("${DEFAULT_LANGUAGE}")
    private String DEFAULT_LANGUAGE;

    /**
     * 1.通过 headers: { lang } 获取语言
     * 2.通过 cookies: { lang } 获取语言
     */
    public String getLang() {
        HttpServletRequest request = httpRequestUtil.getRequest();
        // [Header] 从头部信息来的 Lang
        String lang = request.getHeader("lang");
        if (lang == null || lang.isEmpty()) {
            // [Cookie] 从Cookie信息来的 Lang
            lang = getCookieValue(request, "lang");
            if (lang == null || lang.isEmpty()) {
                lang = DEFAULT_LANGUAGE;
            }
        }
        return lang;
    }

    // 通过Cookie名称获取Cookie的值
    private String getCookieValue(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (name.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }

    /**
     *  完整示例：
        Map<String, Object> fieldPrimary = Collections.singletonMap("article_id", cmsArticleDTO.getArticle_id());
        cmsArticleMapper.insertArticleTranslations(languageUtil.getTranslationsField(fieldPrimary, cmsArticleDTO, CmsArticleTranslationsDTO.class));
     * 
     *  使用说明 ：getTranslationsField([fieldPrimary], [class], [transitions.class]) 
     * 
     * - [fieldPrimary] 获得主键的键与值 { article_id: 1 } (Map类型)
     *      Map<String, Object> fieldPrimary = Collections.singletonMap("article_id", cmsArticleDTO.getArticle_id());
     * - [class] 获得 载体 的实体类对象 (默认对应实体类对象的 translations 字段)
     *      cmsArticleDTO
     * - [translations.class] 获得 翻译表 对应的实体类 (Class)
     *      CmsArticleTranslationsDTO.class
     */
    public <T> List<Map<String, Object>> getTranslationsField(Map<String, Object> fieldPrimary, T dto, Class<?> cls) {

        List<Map<String, Object>> result = new ArrayList<>();
        try {
            List<String> fields = getFieldNames(cls);

            Field translationsField = dto.getClass().getDeclaredField("translations");
            translationsField.setAccessible(true); // 设置可访问私有字段
            
            List<Object> translations = (List<Object>) translationsField.get(dto);
            result = translations.stream().map(trans -> {
                Map<String, Object> translation = new HashMap<>();
                for (int i = 0; i < fields.size(); i++) {
                    try {
                        Field field = trans.getClass().getDeclaredField(fields.get(i));
                        // 默认情况下，Java 中的成员变量和方法是私有的，即不能直接访问。
                        // 通过调用 setAccessible(true)，我们可以绕过访问修饰符的限制来访问那些通常不可访问的成员。
                        field.setAccessible(true);
                        // 判断 [键] 字段名匹配时，设置 [键值]
                        String fieldPrimaryKey = fieldPrimary.keySet().iterator().next();
                        if (fields.get(i).equals(fieldPrimaryKey)) {
                            translation.put(fields.get(i), fieldPrimary.get(fieldPrimaryKey));
                        } else {
                            translation.put(fields.get(i), field.get(trans));
                        }
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                return translation;
            }).collect(Collectors.toList());
            
            return result;

        } catch (NoSuchFieldException e) {
            // 处理字段不存在的情况
            e.printStackTrace();
            return result;
        } catch (IllegalAccessException e) {
            // 处理无法访问字段的异常
            e.printStackTrace();
            return result;
        }
    }
    // public <T> List<Map<String, Object>> getTranslationsField(Map<String, Object> fieldPrimary, List<T> translations, Class<?> cls) {
    //     List<String> fields = getFieldNames(cls);
    //     return translations.stream().map(trans -> {
    //         Map<String, Object> translation = new HashMap<>();
    //         for (int i = 0; i < fields.size(); i++) {
    //             try {
    //                 Field field = trans.getClass().getDeclaredField(fields.get(i));
    //                 // 默认情况下，Java 中的成员变量和方法是私有的，即不能直接访问。
    //                 // 通过调用 setAccessible(true)，我们可以绕过访问修饰符的限制来访问那些通常不可访问的成员。
    //                 field.setAccessible(true);
    //                 // 判断 [键] 字段名匹配时，设置 [键值]
    //                 String fieldPrimaryKey = fieldPrimary.keySet().iterator().next();
    //                 if (fields.get(i).equals(fieldPrimaryKey)) {
    //                     translation.put(fields.get(i), fieldPrimary.get(fieldPrimaryKey));
    //                 } else {
    //                     translation.put(fields.get(i), field.get(trans));
    //                 }
    //             } catch (NoSuchFieldException | IllegalAccessException e) {
    //                 e.printStackTrace();
    //             }
    //         }
    //         return translation;
    //     }).collect(Collectors.toList());
    // }

    /**
     * 获得实体类的字段名集合
     * List<String> fields = languageUtil.getFieldNames(CmsArticleTranslationsDTO.class);
     */
    public List<String> getFieldNames(Class<?> cls) {
        List<String> fieldNames = new ArrayList<>();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            fieldNames.add(field.getName());
        }
        return fieldNames;
    }

}
