package com.fshark.overseas.advert.processor;


import com.fshark.overseas.advert.entity.GameAccount;
import com.fshark.overseas.advert.entity.dao.GameAccountDao;
import com.fshark.overseas.advert.modle.AppsFlyerEvent;
import com.fshark.overseas.advert.modle.AppsflyerPurchase;
import com.fshark.overseas.advert.modle.EventTypeEnum;
import com.fshark.overseas.advert.modle.metrics.EventMetrics;
import com.fshark.overseas.advert.util.*;
import com.google.gson.Gson;
import org.apache.flink.api.common.functions.RichFlatMapFunction;
import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.util.Collector;

import java.time.LocalDateTime;
import java.util.Optional;

public class EventMectrisProcessor extends RichFlatMapFunction<AppsFlyerEvent, EventMetrics> {


    private AppConfig appConfig;

    private JdbiContext jdbiContext;

    private GameAccountDao gameAccountDao;

    private transient ValueState<Long> userTime;


    public EventMectrisProcessor(AppConfig appConfig) {
        this.appConfig = appConfig;
    }

    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        jdbiContext = DatabaseUtils.getGenJdbiClient(appConfig.getDbHost(), appConfig.getDbUser(), appConfig.getDbPassword());
        gameAccountDao = jdbiContext.getJdbi().onDemand(GameAccountDao.class);
        ValueStateDescriptor<Long> descriptor =
                new ValueStateDescriptor<>(
                        "user_time", // the state name
                        TypeInformation.of(new TypeHint<Long>() {}), // type information
                        null); // default value of the state, if nothing was set
        userTime = getRuntimeContext().getState(descriptor);

    }

    @Override
    public void flatMap(AppsFlyerEvent value, Collector<EventMetrics> out) throws Exception {
        if (value == null || value.getEvent_time() == null) {
            return;
        }
        if (EventTypeEnum.PURCHASE.getName().equals(value.getEvent())) {
            try {
                AppsflyerPurchase appsflyerPurchase = new Gson().fromJson(value.getEvent_value(), AppsflyerPurchase.class);
                if (appsflyerPurchase == null || appsflyerPurchase.getServerid() == null) {  //不是我们上报的格式
                    return;
                }
                if ("ios".equals(value.getPlatform().toLowerCase())) {
                    String bundleId = appsflyerPurchase.getBundle_id();
                    value.setGame_id(bundleId == null ? value.getGame_id() : bundleId);
                }
            } catch (Exception e) {
                return;
            }
        }
        EventMetrics metrics = new EventMetrics();
        metrics.setTimeZone(value.getTime_zone());
        metrics.setRegion(value.getRegion());
        metrics.setPlatform(value.getPlatform());
        metrics.setGameId(value.getGame_id());
        metrics.setCampaignId(value.getCampaign_id());
        metrics.setEvent_name(value.getEvent());
        metrics.setMediaSource(value.getMedia_source());
        Long date = userTime.value();
        if (date == null){
            Optional<GameAccount> account = gameAccountDao.findByPrimary(value, Constants.TYPE_ACTIVIYION);
            if (account.isPresent()) {
                GameAccount gameAccount = account.get();
                metrics.setDataDate(Long.valueOf(DateUtils.formatAsYMD(gameAccount.getEvent_time())));
                userTime.update(metrics.getDataDate());
            } else if (EventTypeEnum.ACTIVATION.getName().equals(value.getEvent())) {
                metrics.setDataDate(Long.valueOf(DateUtils.formatAsYMD(value.getEvent_time())));
                userTime.update(metrics.getDataDate());
            } else {
                Optional<GameAccount> byAccountPrimary = gameAccountDao.findByPrimary(value, Constants.TYPE_REGISTER);
                if (byAccountPrimary.isPresent()) {
                    GameAccount registerAccount = byAccountPrimary.get();
                    if (null != registerAccount.getEvent_time()) {
                        metrics.setDataDate(Long.valueOf(DateUtils.formatAsYMD(registerAccount.getEvent_time())));
                        userTime.update(metrics.getDataDate());
                    }
                }
            }
        } else {
            metrics.setDataDate(date);
        }
        metrics.setEvent_date(Long.valueOf(DateUtils.formatAsYMD(value.getEvent_time())));
        metrics.setTimes(1L);
        out.collect(metrics);
    }

    @Override
    public void close() throws Exception {
        super.close();
        if (jdbiContext != null) {
            jdbiContext.getDataSource().close();
        }

    }
}
