package com.aliyun.odps.spark.examples.myUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.odps.Column;
import com.aliyun.odps.data.Record;
import com.google.gson.Gson;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

public class ConvertUtils {
    public static JSONObject getFeature(Map<String, String> record, List<Map<String, String>> videoSeq, int scale) {
        Map<String, Double> featMap = new HashMap<>();

        // origin info
        String ts = record.get("ts");
        long currentMs = Long.parseLong(ts) * 1000;
        String vid = record.get("vid");
        Map<String, String> headInfo = getRecordCol(record, "v2_feature");
        Map<String, String> rankInfo = getRecordCol(record, "v1_feature");
        Map<String, Map<String, String>> userOriginInfo = getUserOriginInfo(record);
        Map<String, Map<String, Map<String, String>>> videoOriginInfo = getVideoOriginInfo(record);

        // parse info
        Map<String, String> c9Map = userOriginInfo.get("alg_recsys_feature_user_share_return_stat");
        UserShareReturnProfile userProfile = JSON.parseObject(toJson(c9Map), UserShareReturnProfile.class);
        Map<String, Map<String, String>> historyVideoMap = list2Map(videoSeq);

        Map<String, Map<String, String[]>> c7Map = FeatureTransform.parseUCFScore(userOriginInfo.get("alg_mid_feature_sharecf"));
        Map<String, Map<String, String[]>> c8Map = FeatureTransform.parseUCFScore(userOriginInfo.get("alg_mid_feature_returncf"));

        // context feature
        FeatureTransform.getContextFeature(currentMs, featMap);

        // head video feature
        FeatureTransform.getVideoBaseFeature("h", currentMs, headInfo, featMap);

        // user feature
        FeatureTransform.getUserFeature(userOriginInfo, featMap);
        FeatureTransform.getUserProfileFeature(userProfile, record, featMap);

        // user & video feature
        FeatureTransform.getUserTagsCrossVideoFeature("c5", rankInfo, userOriginInfo.get("alg_mid_feature_return_tags"), featMap);
        FeatureTransform.getUserTagsCrossVideoFeature("c6", rankInfo, userOriginInfo.get("alg_mid_feature_share_tags"), featMap);
        FeatureTransform.getUserCFFeature("c7", vid, c7Map, featMap);
        FeatureTransform.getUserCFFeature("c8", vid, c8Map, featMap);

        // rank video feature
        FeatureTransform.getVideoBaseFeature("r", currentMs, rankInfo, featMap);
        FeatureTransform.getVideoFeature(vid, videoOriginInfo, featMap);

        // head&rank cross feature
        FeatureTransform.getHeadRankVideoCrossFeature(headInfo, rankInfo, featMap);

        // user profile & rank cross
        FeatureTransform.getProfileVideoCrossFeature(currentMs, userProfile, rankInfo, historyVideoMap, featMap);

        return filterAndTruncate(featMap, scale);
    }

    private static Map<String, Map<String, String>> getUserOriginInfo(Map<String, String> record) {
        Map<String, Map<String, String>> map = new HashMap<>();
        map.put("mid_global_feature_20250212", getRecordCol(record, "c1_feature"));
        map.put("mid_u2u_friend_index_feature_20250212", getRecordCol(record, "c4_feature"));
        map.put("alg_mid_feature_return_tags", getRecordCol(record, "c5_feature"));
        map.put("alg_mid_feature_share_tags", getRecordCol(record, "c6_feature"));
        map.put("alg_mid_feature_sharecf", getRecordCol(record, "c7_feature"));
        map.put("alg_mid_feature_returncf", getRecordCol(record, "c8_feature"));
        map.put("alg_recsys_feature_user_share_return_stat", getRecordCol(record, "c9_feature"));
        return map;
    }

    private static Map<String, Map<String, Map<String, String>>> getVideoOriginInfo(Map<String, String> record) {
        Map<String, Map<String, String>> map = new HashMap<>();
        map.put("alg_vid_global_feature_20250212", getRecordCol(record, "b1_feature"));
        map.put("alg_vid_recommend_exp_feature_20250212", getRecordCol(record, "b2_feature"));
        map.put("alg_vid_recommend_flowpool_exp_feature_20250212", getRecordCol(record, "b3_feature"));
        map.put("alg_vid_apptype_recommend_exp_feature_20250212", getRecordCol(record, "b4_feature"));
        map.put("alg_vid_province_recommend_exp_feature_20250212", getRecordCol(record, "b5_feature"));
        map.put("alg_vid_brand_recommend_exp_feature_20250212", getRecordCol(record, "b6_feature"));
        map.put("alg_vid_hotsencetype_recommend_exp_feature_20250212", getRecordCol(record, "b7_feature"));
        map.put("alg_merge_cate1_recommend_exp_feature_20250212", getRecordCol(record, "b8_feature"));
        map.put("alg_merge_cate2_recommend_exp_feature_20250212", getRecordCol(record, "b9_feature"));
        map.put("alg_channel_recommend_exp_feature_20250212", getRecordCol(record, "b10_feature"));
        map.put("alg_festive_recommend_exp_feature_20250212", getRecordCol(record, "b11_feature"));
        map.put("alg_vid_long_period_recommend_exp_feature_20250212", getRecordCol(record, "b12_feature"));
        map.put("alg_video_unionid_recommend_exp_feature_20250212", getRecordCol(record, "b13_feature"));
        map.put("scene_type_vid_cf_feature_20250212", getRecordCol(record, "d1_feature"));
        map.put("vid_click_cf_feature_20250212", getRecordCol(record, "d2_feature"));
        map.put("alg_recsys_feature_cf_i2i_v2", getRecordCol(record, "d3_feature"));
        // 特征
        map.put("mid_merge_cate1_feature_20250212", getRecordCol(record, "c2_feature"));
        map.put("mid_merge_cate2_feature_20250212", getRecordCol(record, "c3_feature"));

        Map<String, Map<String, Map<String, String>>> allMap = new HashMap<>();
        String vid = record.get("vid");
        allMap.put(vid, map);
        return allMap;
    }

    public static Set<String> getVidList(String data) {
        Set<String> vidList = new HashSet<>();
        if (null != data && !data.isEmpty()) {
            UserShareReturnProfile user = JSON.parseObject(data, UserShareReturnProfile.class);
            if (null != user) {
                for (List<UserSRBO> list : Arrays.asList(user.getM_s_s(), user.getM_r_s(), user.getL_s_s(), user.getL_r_s())) {
                    if (null != list) {
                        for (UserSRBO u : list) {
                            if (null != u) {
                                vidList.add(u.getId() + "");
                            }
                        }
                    }
                }
            }
        }
        return vidList;
    }

    public static Map<String, String> getRecordCol(Record record, String col) {
        Map<String, String> colMap = new HashMap<>();
        if (null != record && !record.isNull(col)) {
            try {
                JSONObject json = JSON.parseObject(record.getString(col));
                if (null != json) {
                    for (Map.Entry<String, Object> entry : json.entrySet()) {
                        Object obj = entry.getValue();
                        if (null != obj) {
                            colMap.put(entry.getKey(), obj.toString());
                        }
                    }
                }
            } catch (Exception ignored) {
            }
        }
        return colMap;
    }

    public static Map<String, String> getRecordCol(Map<String, String> record, String col) {
        Map<String, String> colMap = new HashMap<>();
        if (null != record && record.containsKey(col)) {
            try {
                JSONObject json = JSON.parseObject(record.get(col));
                if (null != json) {
                    for (Map.Entry<String, Object> entry : json.entrySet()) {
                        Object obj = entry.getValue();
                        if (null != obj) {
                            colMap.put(entry.getKey(), obj.toString());
                        }
                    }
                }
            } catch (Exception ignored) {
            }
        }
        return colMap;
    }

    public static Map<String, String> record2Map(Record record) {
        Map<String, String> map = new HashMap<>();
        if (null != record) {
            Column[] columns = record.getColumns();
            if (null != columns) {
                for (Column column : columns) {
                    String name = column.getName();
                    if (!record.isNull(name)) {
                        map.put(name, record.getString(name));
                    }
                }
            }
        }
        return map;
    }

    public static Map<String, Map<String, String>> list2Map(List<Map<String, String>> videSeq) {
        Map<String, Map<String, String>> map = new HashMap<>();
        if (null != videSeq && !videSeq.isEmpty()) {
            for (Map<String, String> video : videSeq) {
                if (null != video && !video.isEmpty()) {
                    String vid = video.get("vid");
                    if (null != vid && !vid.isEmpty()) {
                        map.put(video.get("vid"), video);
                    }
                }
            }
        }
        return map;
    }

    public static JSONObject filterAndTruncate(Map<String, Double> featMap, int scale) {
        JSONObject jsonObject = new JSONObject();
        for (Map.Entry<String, Double> entry : featMap.entrySet()) {
            double value = entry.getValue();
            if (value > 1E-8) {
                if (value == Math.floor(value)) {
                    jsonObject.put(entry.getKey(), entry.getValue());
                } else {
                    double newValue = new BigDecimal(value).setScale(scale, RoundingMode.HALF_UP).doubleValue();
                    jsonObject.put(entry.getKey(), newValue);
                }
            }
        }
        return jsonObject;
    }

    public static String toJson(Object obj) {
        if (obj == null) {
            return "";
        }
        try {
            return new Gson().toJson(obj);
        } catch (Exception e) {
            return "";
        }
    }
}
