package com.yutou.biliapi.databases;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.util.DateUtils;
import com.yutou.biliapi.bean.live.*;
import com.yutou.biliapi.bean.live.database.*;
import com.yutou.biliapi.bean.websocket.live.*;
import com.yutou.bilibili.Tools.DateFormatUtils;
import com.yutou.common.databases.AbsDatabasesBean;
import com.yutou.common.databases.SQLiteManager;
import com.yutou.common.okhttp.HttpDownloadUtils;
import com.yutou.common.utils.Log;
import lombok.Getter;
import org.apache.poi.ss.usermodel.DataFormat;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import static com.alibaba.fastjson2.util.DateUtils.DateTimeFormatPattern.DATE_FORMAT_10_DASH;

public class BiliLiveDatabase extends SQLiteManager {
    LiveRoomConfig config;
    String fileName;
    File rootPath;

    public BiliLiveDatabase(LiveRoomConfig roomConfig, String path) {
        this.config = roomConfig;
        rootPath = new File(path).getParentFile();
        fileName = path + File.separator + "live.db";
        init();
    }

    public BiliLiveDatabase(LiveRoomConfig roomConfig) {
        rootPath = new File(roomConfig.getRootPath() + File.separator + roomConfig.getAnchorName());
        config = roomConfig;
        if (!rootPath.exists()) {
            rootPath.mkdirs();
        }
        fileName = rootPath.getAbsolutePath() + File.separator + "live.db";
        init();
    }

    @Override
    public void init() {
        super.init();
        if (config.getRoomInfo() != null) {
            HttpDownloadUtils.download(new HttpDownloadUtils.Builder().setUrl(config.getRoomInfo().getUserCover())
                    .setPath(rootPath.getAbsolutePath())
                    .setFileName("poster.jpg"));
        }
    }

    @Override
    public String getFileName() {
        return fileName;
    }

    @Override
    protected List<AbsDatabasesBean> getDataBean() {
        return List.of(
                new LiveInfoDatabaseBean(),
                new LiveDanmuDatabaseBean(),
                new LiveGiftDatabaseBean(),
                new LiveInteractWordDatabaseBean(),
                new LiveSuperChatDatabaseBean(),
                new LiveSourceDatabaseBean(),
                new LiveVideoDatabaseBean(),
                new LiveGuardBuyBean()
        );
    }

    @Override
    public void close() {
        super.close();
    }

    public void addLiveInfo(LiveVideoDatabaseBean info) {
        createInfo(info);
    }

    public List<LiveVideoDatabaseBean> getLiveInfos() {
        return get(new LiveVideoDatabaseBean().getTableName(), LiveVideoDatabaseBean.class);
    }

    private void addData(WSData bean) {
        addData(bean, null);
    }

    private void addData(WSData bean, Long saveTime) {
        AbsDatabasesBean data = null;
        if (bean instanceof WSDanmuData) {
            data = new LiveDanmuDatabaseBean((WSDanmuData) bean);
        } else if (bean instanceof WSInteractWord) {
            data = new LiveInteractWordDatabaseBean((WSInteractWord) bean);
        } else if (bean instanceof WSSendGift) {
            data = new LiveGiftDatabaseBean((WSSendGift) bean);
        } else if (bean instanceof WSSuperChatMessage) {
            data = new LiveSuperChatDatabaseBean((WSSuperChatMessage) bean);
        } else if (bean instanceof WSGuardBuy) {
            data = new LiveGuardBuyBean((WSGuardBuy) bean);
        }
        if (saveTime != null && data != null) {
            data.setSql_time(new Date(saveTime));
        }
        if (data != null) {
            add(data);
        }
    }

    public void addSource(WSData bean) {
//        Log.i("BiliLiveDatabase.addSource", config.getRoomId());
        add(new LiveSourceDatabaseBean(bean));
        addData(bean);
    }

    public JSONObject getGiftInfo(long startTimeLong, long endTimeLong) {
        String giftSql = "WITH filtered_gifts AS (" +
                "SELECT " +
                "`gift_name`," +
                "`icon`, " +
                "SUM(`gift_num`) AS `total_gift_num`," +
                "CASE " +
                "WHEN `coin_type` = 'silver' THEN 0 " +
                "ELSE SUM(`price` * `gift_num`) " +
                "END AS `total_price`" +
                "FROM " +
                "`gift` " +
                "WHERE " +
                "`sql_time` >= '" + startTimeLong + "' " +
                "AND `sql_time` <= '" + endTimeLong + "' " +
                "GROUP BY " +
                "`gift_name`, `coin_type`" +
                ")" +
                "SELECT " +
                "`gift_name`," +
                "`icon`," +
                "SUM(`total_gift_num`) AS `total_gift_num`," +
                "SUM(`total_price`) AS `total_price`" +
                "FROM " +
                "filtered_gifts " +
                "GROUP BY " +
                "`gift_name`, `icon`;";
        String guardSql = "SELECT `gift_name`, SUM(`num`) AS `total_num`,SUM(`price`*`num`) as `total_price`" +
                "FROM `guardBuy` where `sql_time` >= '" + startTimeLong + "' and `sql_time` <= '" + endTimeLong + "'" +
                "GROUP BY `gift_name`;";
        String superChatSql = "SELECT SUM(`price`*100) as `total_price`, count(`price`) as `total_count`" +
                "FROM `superChat` where `sql_time` >= '" + startTimeLong + "' and `sql_time` <= '" + endTimeLong + "';";
        JSONObject json = new JSONObject();
        JSONArray giftInfo = get(giftSql);
        JSONArray guardInfo = get(guardSql);
        JSONArray superChatInfo = get(superChatSql);
        json.put("giftInfo", giftInfo);
        json.put("guardInfo", guardInfo);
        if (!superChatInfo.isEmpty()) {
            json.put("superChatInfo", superChatInfo.getFirst());
        } else {
            json.put("superChatInfo", new JSONObject());
        }
        json.put("price", getGiftPrice(giftInfo) + getGiftPrice(guardInfo) + getGiftPrice(superChatInfo));

        return json;
    }

    private long getGiftPrice(JSONArray array) {
        long price = 0;
        for (Object o : array) {
            JSONObject item = (JSONObject) o;
            price += item.getLongValue("total_price");
        }
        return price;
    }

    private void createInfo(LiveVideoDatabaseBean bean) {
        if (get(bean.getTableName(), " `sql_time` = '" + bean.getSql_time().getTime() + "'", LiveVideoDatabaseBean.class).isEmpty()) {
            add(bean);
        } else {
            update(bean);
        }
    }

    public <T extends AbsDatabasesBean> List<T> getOfTime(Long startTime, Long endTime, Class<T> clazz) {
        String tableName = null;
        StringBuilder sb = new StringBuilder();
        String where = null;
        if (startTime != null) {
            sb.append(" `sql_time` >= ").append("\"").append(startTime).append("\"");
        }
        if (endTime != null) {
            if (!sb.isEmpty()) {
                sb.append(" and ");
            }
            sb.append(" `sql_time` <= ").append("\"").append(endTime).append("\"");
        }
        if (!sb.isEmpty()) {
            where = sb.toString();
        }
        for (AbsDatabasesBean bean : getDataBean()) {
            if (bean.getClass() == clazz) {
                tableName = bean.getTableName();
                break;
            }
        }
        return super.get(tableName, where, clazz);
    }

    public LiveVideoDatabaseBean getVideo(String videoId) {
        for (LiveVideoDatabaseBean info : getLiveInfos()) {
            System.out.println(videoId + "   " + info.getSql_time().getTime());
            if (videoId.trim().equals(String.valueOf(info.getSql_time().getTime()))) {
                return info;
            }
        }
        return null;
    }

    public void resetSQL() {
        List<AbsDatabasesBean> list = List.of(
                new LiveInfoDatabaseBean(),
                new LiveDanmuDatabaseBean(),
                new LiveGiftDatabaseBean(),
                new LiveGuardBuyBean(),
                new LiveInteractWordDatabaseBean(),
                new LiveSuperChatDatabaseBean()
        );
        for (AbsDatabasesBean item : list) {
            clearTable(item.getTableName());
        }
        recreateSql(list);
    }

    public void resetData() {
        List<LiveSourceDatabaseBean> list = get(new LiveSourceDatabaseBean().getTableName(), LiveSourceDatabaseBean.class);
        for (LiveSourceDatabaseBean item : list) {
            WSData data = WSData.parse(JSONObject.parseObject(item.getJson()));
            addData(data, item.getSql_time().getTime());
        }
    }

    public static void main(String[] args) {
        BiliLiveDatabase biliLiveDatabase = new BiliLiveDatabase(LiveRoomConfig.buildConfig("7688602"));
        biliLiveDatabase.resetSQL();
        biliLiveDatabase.resetData();

    }
}
