const datetime = require("../../config/datetime");
const { AppEventType, AppEvent } = require("../event/my.event");
const reponceTitle = require("../helpers/replaceTitle");
const Answare = require("../model/Answare");
const Betting = require("../model/Betting");
const Match = require("../model/Match");
const Quartion = require("../model/Quartion");
const User = require("../model/User");
const Controller = require("./Controller");
module.exports = new class BetController extends Controller {
    call = () => {
        AppEvent.emit(AppEventType.call, "");
    }
    request = async (req, res, next) => {
        try {
            const ans_id = req.params.ans_id;
            const taka = req.body.taka;
            const a_data = await Answare.find(ans_id);
            const [setting, q_data] = await Promise.all([
                this.setting(),
                Quartion.find(a_data.quertion_id)
            ]);


            const m_data = await Match.find(q_data.match_id);
            const user = req.user;
            // extra chcek
            if (user.is_block == "yes") return next("Your accout is block !");
            if (setting.is_active_bet == "no") return next("Some time bett off in application !");
            // check valid taka
            if (!Number(taka)) return next("Invalid amout");
            if (parseFloat(user.taka) < parseFloat(taka)) next("Check your acount !");
            const usetaka = parseFloat(user.taka) - parseFloat(taka);
            if (usetaka < this.min_taka) return next(`sorry your use taka ${this.getTaka(parseFloat(user.taka) - this.min_taka)}`)

            if (a_data.is_lock == "on" || a_data.is_show == "on") return next("betting feild!");
            if (q_data.is_lock == "on" || q_data.is_show == "off") return next("betting feild!");
            if (m_data.is_lock == "on" || m_data.is_show == "off") return next("betting feild!");


            const retunAmount = this.getTaka(parseFloat(taka) * parseFloat(a_data.ret));

            await new Promise(resolve => setTimeout(resolve, Number(setting.bettime) || 1000));
            // parmition check
            if (parseFloat(setting.minbetret) > parseFloat(a_data.ret)) return next("min bet ret " + setting.minbetret)
            if (parseFloat(setting.maxbet) > parseFloat(a_data.taka)) return next("max bet amount " + setting.maxbet)



            const m_title = `${m_data.tream_a} vs ${m_data.tream_b}`;
            const q_title = reponceTitle(q_data.title, m_data.tream_a, m_data.tream_b, q_data.runs, q_data.rets, q_data.overs);;
            const a_title = reponceTitle(a_data.title, m_data.tream_a, m_data.tream_b, q_data.runs, q_data.rets, q_data.overs);;
            const payload = {
                match_title: m_title,
                queartion_title: q_title,
                answare_title: a_title,
                ret: a_data.ret,
                taka: this.getTaka(taka),
                return_taka: retunAmount,
                match_id: m_data.id,
                queartion_id: q_data.id,
                answare_id: a_data.id,
                icon: m_data.icon,
                user_id: user.id,
                betting_time: datetime.time() + " " + datetime.today(),
                sport_name: m_data.sport_name,
                macth_start_date: m_data.start_time,
                league: m_data.league_name
            }
            await this.cutTakaFromUser(user.id, taka, this.transectionType.bet, "bet");
            await Betting.add(payload)
            // commition
            const [sponser, clubholder] = await Promise.all([
                User.where("id", user.sponcer_by_id).first(),
                User.where("id", user.club_by_id).first()
            ])
            const taskofcommiion = [];
            if (sponser) {
                if (sponser.id != user.id && sponser['is_active'] == "1") {
                    const commiton = setting.sp_comming;
                    const commiton_taka = this.getTaka((parseFloat(taka) * parseFloat(commiton)) / 100);
                    taskofcommiion.push(this.addTakaToUser(sponser.id, commiton_taka, this.transectionType.responsercomming, "sp commition"));
                }
            }
            if (clubholder) {
                // clubholder['club_comminion'] || setting.club_comming;
                if (clubholder.id != user.id && clubholder['is_active'] == "1") {
                    const commiton = setting.club_comming;
                    const commiton_taka = this.getTaka((parseFloat(taka) * parseFloat(commiton)) / 100);
                    taskofcommiion.push(this.addTakaToUser(clubholder.id, commiton_taka, this.transectionType.club_commintion, "club commition"));
                }
            }
            await Promise.all(taskofcommiion);
            this.call();
            return res.success("betting successfull");
        } catch (error) {
            return next(error.toString());
        }
    }
    better = async (req, res, next) => {
        try {
            const id = req.params.id;
            const betters = await Betting
                .where("queartion_id", id)
                .join("users", "bets.user_id", "users.id")
                .leftJoin("admins", "bets.resulder_id", "admins.id")
                .select([
                    "bets.*",
                    "users.name as user_name",
                    "admins.name as resulder_name",
                ])
            if (betters.length == 0) return next("data not found");
            const data = betters[0];
            const match_data = await Match.find(data.match_id);
            return res.success("succsse", { match: data, better: betters, match_data });
        } catch (error) {
            return next(error.toString());
        }
    }
    win = async (req, res, next) => {
        try {
            const losspayload = {
                status: Betting.type.win,
                resulder_id: req.user.id,
                resuld_time: `${datetime.time()} ${datetime.today()}`
            }
            const { ids } = req.body;
            await Promise.all(
                ids.map(async (id) => {
                    const bet = await Betting
                        .where("id", id)
                        .andWhere("status", "=", "pending")
                        .andWhere("status", "!=", "retrun")
                        .first();
                    if (bet) {
                        await Betting.update(id, () => losspayload);
                        await this.addTakaToUser(
                            bet.user_id,
                            bet.return_taka,
                            this.transectionType.bet,
                            "bet win"
                        )
                    }

                })
            );
            return res.success("successfull");
        } catch (error) {
            return next(error.toString());
        }
    }
    loss = async (req, res, next) => {
        try {
            const losspayload = {
                status: Betting.type.loss,
                resulder_id: req.user.id,
                resuld_time: `${datetime.time()} ${datetime.today()}`
            }
            const { ids } = req.body;
            await Promise.all(
                ids.map(async (id) => {
                    await Betting
                        .where("id", id)
                        .andWhere("status", "=", "pending")
                        .update(losspayload);
                })
            );
            return res.success("successfull");
        } catch (error) {
            return next(error.toString());
        }
    }
    reset = async (req, res, next) => {
        try {
            const { ids } = req.body;
            await Promise.all(
                ids.map(async (id) => {
                    const bet = await Betting
                        .where("id", id)
                        .andWhere("status", "!=", "pending")
                        .andWhere("status", "!=", "retrun")
                        .first();
                    if (bet) {
                        const losspayload = {
                            status: Betting.type.pending,
                            resulder_id: "",
                            resuld_time: ``
                        }
                        await Betting.update(id, v => losspayload);
                        if (bet.status == "win") {
                            await this.cutTakaFromUser(
                                bet.user_id,
                                bet.retrun_taka,
                                this.transectionType.bet,
                                "bet reset"
                            )
                        }
                    }
                })
            );

            return res.success("successfull");
        } catch (error) {
            return next(error.toString());
        }
    }
    retrun = async (req, res, next) => {
        try {
            const { ids, parsent } = req.body;
            if (!Number(parsent)) return next("Invalid %");
            const losspayload = {
                status: Betting.type.return,
                resulder_id: req.user.id,
                retrun_parsent: parsent,
                resuld_time: `${datetime.time()} ${datetime.today()}`
            }
            await Promise.all(
                ids.map(async (id) => {
                    const bet = await Betting.where("id", id).andWhere("status", "=", "pending").first();
                    if (bet) {
                        const retrun_taka = ((parseFloat(bet.taka) * parseFloat(parsent)) / 100).toFixed(2);
                        await Betting.update(id, () => losspayload)
                        await this.addTakaToUser(bet.user_id, this.getTaka(retrun_taka), this.transectionType.bet, `bet cansel back ${parsent}%`)
                    }
                })
            );
            return res.success("successfull");
        } catch (error) {
            return next(error.toString());
        }
    }
    winloss = async (req, res, next) => {
        try {
            const allowType = ["win", "loss"];
            const { id, type } = req.body;
            if (!allowType.includes(type)) return next("type not allow");
            const admin = req.user;
            const bets = await Betting.where("answare_id", id);
            if (bets.length == 0) next("bet not found");
            // loss
            const losspayload = {
                status: Betting.type.loss,
                resulder_id: admin.id,
                resuld_time: `${datetime.time()} ${datetime.today()}`
            }
            await Betting.where("answare_id", "!=", id).andWhere("status", "pending").update(losspayload);
            await Betting.where("answare_id", id).andWhere("status", "pending").update({ ...losspayload, status: "win" });
            await Promise.all(
                bets.map(async bet => {
                    const better = await User.where("id", bet.user_id).first();
                    if (!better) return;
                    await Promise.all([
                        this.addTakaToUser(
                            bet.user_id,
                            bet.return_taka,
                            this.transectionType.bet,
                            "bet win"
                        )
                    ]);
                })
            );

            this.call();
            return res.success(type + " successfull")
        } catch (error) {
            return next(error.toString());
        }
    }
}
