const GuildM = require('../models/guilds');
const STRIKES = require('../models/strikes');
const roleRulesM = require('../models/autoRoleRule');
const feedsM = require('../models/feeds');
const xmlparser = require('xml-js');
const {DiscordAPI, getRules, confirmArgsForYTFeed} = require('../lib')
exports.home = async (req,res)=>
{
    res.render('home.ejs');
}

exports.redirect = async (req, res)=>
{
    res.render('redirect.ejs');
}

exports.dashboard = (bot)=>
{
    return async (req, res)=>
    {
    
        const userPlaceholder =
        {
            id:'',
            username:'placeholder',
            avatar:'',
        }
        if(!req.headers.cookie) return res.render('dashboard.ejs', {user:userPlaceholder, guilds:{}});
        const connector = new DiscordAPI(req.headers.cookie, bot);
        const user =  await connector.getUser();
        const guilds = await connector.getGuildsFull();
        
        res.render('dashboard.ejs',{user, guilds});
    
    }
}
exports.getModerator = (bot)=>
{
    return async (req,res)=>
    {
        const modId = {moderatorid} = req.params;
        const user =  await bot.users.cache.get('1203446477024927764');
        res.render('user.ejs', {user})
    }
}
exports.guilds = (bot)=>
{
    return  async (req, res) =>
    {
        try {
            const connector = new DiscordAPI(req.headers.cookie, bot);
            const userGuilds = await connector.getUserGuilds();
            const guilds = await connector.getGuildsFull(userGuilds);
            res.render('guilds.ejs', { guilds });
        } catch (err) {
            console.error(err);
            res.status(500).send('Internal Server Error');
        }
    }
}


exports.gDash = (bot)=>
{
           
    return async (req, res)=>
    {
        const userid = await new DiscordAPI(req.headers.cookie, bot).getUserId();
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.id);
        res.render('guildPopup.ejs', {guild, userid})
    }
}
exports.guildUpdate = (bot)=>
{
    return async (req, res)=>
    {
        /**
         * ! /gdash/:id/:setting?'
         */
        const original = await GuildM.find({gID:req.params.id}).then(guild=>{return guild[0]});
        var aux = {}
        aux[req.params.setting] = !original[req.params.setting]
        const updated = await GuildM.findOneAndUpdate({gID:req.params.id}, aux)
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.id);
        res.render('guildPopup.ejs', {guild})
    }
}

exports.rDash = (bot)=>
{
    //! /rolerulesdash/:id -> Discord Guild Id (GuildId) 
    return async (req, res)=>
    {
        const roles = await getRules(req.params.id);
        res.render('roleRules.ejs', {roles, id:req.params.id});
    }
}
exports.roleChange = (bot)=>
{
    //! '/roleChange/:id/:guildid'        
    return async (req, res)=>
    {
        const role = await getRules(req.params.id);
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        res.render('rolePopup.ejs', {role, id:req.params.id, guild});
    }
}
exports.saveRoleChange = (bot)=>
{
    //! '/rolechange      
    return async (req, res)=>
    {
        const body = req.body;
        if(!body.roleid || !body.emojiid || !body.messageid || !body.guildid) return  res.status(400).send('Bad Request');
        const extra = await getRoleName(req.body, bot)
        if(extra.error) return res.status(400).send(`Bad Request - ${extra.error}`)
        var rule = 
        {
            gID:body.guildid,
            mID:body.messageid,
            roleID:body.roleid,
            roleEmoji:body.emojiid,
            roleName:extra.roleName,
        }
        const updatedRule = await roleRulesM.findOneAndUpdate({_id:req.params.id}, rule); 
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        res.render('rolePopup.ejs', {role:updatedRule, id:body.id, guild});
    }
    
  
}
exports.deleteRole = async (req, res)=>
{
    const deleted = await roleRulesM.findOneAndDelete({_id:req.params.id});
    const roles = await getRules(req.params.guildid);
    res.render('roleRules.ejs', {roles, id:req.params.guildid});
}

exports.newRoleRule = (bot)=>
{
    //! '/newrolerule/:guildid'

    return async (req, res)=>
    {
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildData(req.params.guildid);
        const role = 'N/A';
        res.render('rolePopup.ejs', {guild, role,id:req.params.guildid})
    }
}
exports.newRule = (bot)=>
{
    return async (req, res)=>
    {
        const body = req.body;
        if(!body.roleid || !body.emojiid || !body.messageid || !body.guildid) return  res.status(400).send('Bad Request');
        const extra = await getRoleName(req.body, bot)
        if(extra.error) return res.status(400).send(`Bad Request - ${extra.error}`)
        var rule = 
        {
            gID:body.guildid,
            mID:body.messageid,
            roleID:body.roleid,
            roleEmoji:body.emojiid,
            roleName:extra.roleName,
        }
        const newRule = await roleRulesM.create(rule); //Might need it later, not sure what for tho.
        const roles = await getRules(body.guildid);
        /**
         * exports.rDash = (bot)=>
            {
                //! /rolerulesdash/:id -> Discord Guild Id (GuildId) 
                return async (req, res)=>
                {
                    const roles = await getRules(req.params.id);
                    res.render('roleRules.ejs', {roles, id:req.params.id});
                }
            }
        */
        res.render('roleRules.ejs', {roles, id:body.guildid});
    }
}
async  function getRoleName(args, bot)
{
    var mID = args.messageid;
    var roleID = args.roleid;
    var roleEmoji = args.emojiid;
    var gID = args.guildid;
    var roleName;
    const guild = bot.guilds.cache.get(gID);
    var m = await (async ()=>
    {
        for(const [id, channel] of bot.channels.cache)
        {
            if(channel.type == 0)
            {
                try {
                    const exists = await bot.channels.cache.get(id).messages.fetch(mID);
                    if(exists) return m = true;
                } catch (error) {}
            }
        }
    })();
    const r = guild.roles.cache.get(roleID);
    const e =  guild.emojis.cache.get(roleEmoji);
    if(!m || !r || !e) return m?(r?(e?false:{error:'Emoji ID'}):{error:'Role ID'}):{error:'Message ID'}
    roleName = r.name;
    return {roleName}
}


exports.fDash = (bot)=>
{
    //! /feedsdash/:guildid'
    return async (req, res)=>
    {
        const preFeeds = await feedsM.find({gID:req.params.guildid}).then(feeds=>{return feeds});
        var feeds = [];
        await Promise.all(preFeeds.map(async (feed) => {
            feed['channelName'] = await getChannelName(feed.YTChannelId);
            feeds.push(feed);
        }));
        feeds.sort((a, b) => {
            return a.channelName.localeCompare(b.channelName);
        });
        res.render('feeds.ejs', {feeds, id:req.params.guildid});
    }
}
async function getChannelName(channelID)
{
    return await fetch('https://www.youtube.com/feeds/videos.xml?channel_id='+channelID,
    {
        method: "GET",
        mode: "cors", 
    })
    .then(response=>
        {
            if(response.ok) return response.text();
        })
    .then(data=>
        {
            data = xmlparser.xml2json(data,
                {
                    compact: true,
                    space: 4
                });
                data = JSON.parse(data);
            return data.feed.author.name._text
        })
    .catch(error=>
        {
            return error;
        });
}
exports.feedChange = (bot)=>
{
    //! /feedChange/:id/:guildid?
    return async (req, res)=>
    {
        var feed = await feedsM.find({_id:req.params.id}).then(feed=>{return feed[0]});
        feed.channelName = await getChannelName(feed.YTChannelId);
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        res.render('feedPopup.ejs', {feed, id:req.params.id, guild});
    }
    
}
exports.addFeed = (bot)=>
{
    //! /feedChange/:guildid?
    return async (req, res)=>
    {
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        res.render('feedPopup.ejs', {feed:null, id:req.params.id, guild});
    }
    
}
exports.saveNewFeed = (bot)=>
{
    //! /feedChange/:guildid?
    return async (req, res)=>
    {
        const {DCchannelID, ytchannel, costummessage} = req.body
        const {guildid} = req.params;
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        var feed = {
            ChannelId: '',
            YTChannelId: '',
            CostumMessage:'',
            gID:guildid
        };
        if(!costummessage && !ytchannel && !DCchannelID) return res.status(400).send('Bad Request');
        const validated = await confirmArgsForYTFeed([guildid, DCchannelID, ytchannel],bot);
        if(validated.error) return  res.status(400).send('Bad Request');
        feed.ChannelId=validated.channelId;
        feed.YTChannelId = validated.YTChannelId;
        feed.CostumMessage = costummessage;
        const newFeed = await feedsM.create(feed).then(f=>{return f}).catch(err=>{console.log(err)});
        newFeed.channelName = validated.channelName;
        res.render('feedPopup.ejs', {feed:newFeed, id:req.params.id, guild});
    }
    
}

exports.deleteFeed = (bot)=>
{
    //! /feedChange/:id/:guildid?
    return async (req, res)=>
    {
        const deleted = await feedsM.findByIdAndDelete(req.params.id).then(deleted => {return deleted}).catch(err=>console.log(err));
        const preFeeds = await feedsM.find({gID:req.params.guildid}).then(feeds=>{return feeds});
        var feeds = [];
        await Promise.all(preFeeds.map(async (feed) => {
            feed['channelName'] = await getChannelName(feed.YTChannelId);
            feeds.push(feed);
        }));
        feeds.sort((a, b) => {
            return a.channelName.localeCompare(b.channelName);
        });
        res.render('feeds.ejs', {feeds, id:req.params.guildid});
    }
    
}
exports.updateFeed = (bot)=>
{
    //! /feedChange/:id/:guildid?
    return async (req, res)=>
    {
        const {DCchannelID, ytchannel, costummessage} = req.body
        const {guildid} = req.params;
        const guild = await new DiscordAPI(req.headers.cookie, bot).getSpecificGuildDataForDash(req.params.guildid);
        var feed = {
            ChannelId: '',
            YTChannelId: '',
            CostumMessage:'',
            gID:guildid
        };
        if(!costummessage && !ytchannel && !DCchannelID) return res.status(400).send('Bad Request');
        const validated = await confirmArgsForYTFeed([guildid, DCchannelID, ytchannel],bot);
        if(validated.error) return  res.status(400).send('Bad Request');
        feed.ChannelId=validated.channelId;
        feed.YTChannelId = validated.YTChannelId;
        feed.CostumMessage = costummessage;
        const newFeed = await feedsM.findOneAndUpdate({_id:req.params.id}, feed).then(f =>{return f}).catch(err=>{console.log(err)});
        res.render('feedPopup.ejs', {feed:newFeed, id:req.params.id, guild});
    }
    
}


exports.strikeDashboard = (bot)=>
{
    return async (req, res)=>
    {
        // const user = bot.users.cache.get(req.params.userid)
        const guild = bot.guilds.cache.get(req.params.id);
        const strikeList = await STRIKES.find({guildID:req.params.id})
        const moderator = req.params.userid;
        var strikes = [];
        await Promise.all(strikeList.map(async (strike) => {
            var aux = {...strike._doc }
            if(strike.validated) 
            {
                if(strike.validatedBy)
                {
                    const user = bot.users.cache.get(strike.validatedBy);
                    const moderator = {
                        username:user.username,
                        avatar:user.avatar,
                        id:user.id
                    };
                    aux = {...aux, moderator};
                }
            }
            strikes.push(aux);
        }));
        // console.log(strikes)
        res.render('strikesDashboard.ejs', {strikes, guild, moderator})
    }
}
exports.updateStrikes = (bot)=>
{
    return async (req,res)=>
    {
        const moderator = req.params.userid;
        const strike = await STRIKES.findByIdAndUpdate(req.params.strikeid, {validated:true, validatedBy:moderator});
        const strikes  = await STRIKES.find({guildID:req.params.id})
        res.render('strikelist.ejs', {strikes, moderator})
    }
}
exports.deleteStrikes = (bot)=>
{
    return async (req,res)=>
    {
        await STRIKES.findByIdAndDelete(req.params.strikeid);
        const strikes  = await STRIKES.find({guildID:req.params.id})
        const moderator = req.params.userid;
        res.render('strikelist.ejs', {strikes, moderator})
    }
}