import { Router } from 'express';
import SQL from 'sql-template-strings';
import avatar from '../avatar';
import {config as socialLoginConfig} from "../social";
import {buildDict, now, shuffle, sortByValue} from "../../src/helpers";
import locales from '../../src/locales';
import {decodeTime} from "ulid";

const router = Router();

router.get('/admin/list', async (req, res) => {
    const admins = await req.db.all(SQL`
        SELECT u.username, p.teamName, p.locale, u.id, u.email, u.avatarSource
        FROM users u
        LEFT JOIN profiles p ON p.userId = u.id
        WHERE p.teamName IS NOT NULL AND p.teamName != ''
        ORDER BY RANDOM()
    `);

    const adminsGroupped = buildDict(function*() {
        yield [req.config.locale, []];
        for (let [locale, , , published] of locales) {
            if (locale !== req.config.locale && published) {
                yield [locale, []];
            }
        }
        yield ['', []];
    });
    for (let admin of admins) {
        admin.avatar = await avatar(req.db, admin);
        delete admin.id;
        delete admin.email;

        if (adminsGroupped[admin.locale] !== undefined) {
            adminsGroupped[admin.locale].push(admin);
        } else {
            adminsGroupped[''].push(admin);
        }
    }

    return res.json(adminsGroupped);
});

router.get('/admin/list/footer', async (req, res) => {
    const fromDb = await req.db.all(SQL`
        SELECT u.username, p.footerName, p.footerAreas, p.locale
        FROM users u
        LEFT JOIN profiles p ON p.userId = u.id
        WHERE p.locale = ${req.config.locale}
          AND p.footerName IS NOT NULL AND p.footerName != ''
          AND p.footerAreas IS NOT NULL AND p.footerAreas != ''
    `);

    const fromConfig = req.config.contact.authors || [];

    return res.json(shuffle([...fromDb, ...fromConfig]));
});

router.get('/admin/users', async (req, res) => {
    if (!req.isGranted('users')) {
        return res.status(401).json({error: 'Unauthorised'});
    }

    const users = await req.db.all(SQL`
        SELECT u.id, u.username, u.email, u.roles, u.avatarSource, p.locale
        FROM users u
        LEFT JOIN profiles p ON p.userId = u.id
        ORDER BY u.id DESC
    `);

    const authenticators = await req.db.all(SQL`
        SELECT userId, type FROM authenticators
        WHERE type IN (`.append(Object.keys(socialLoginConfig).map(k => `'${k}'`).join(',')).append(SQL`)
        AND (validUntil IS NULL OR validUntil > ${now()})
    `));

    const groupedUsers = {};
    for (let user of users) {
        if (groupedUsers[user.id] === undefined) {
            groupedUsers[user.id] = {
                ...user,
                locale: undefined,
                profiles: user.locale ? [user.locale] : [],
                avatar: await avatar(req.db, user),
                socialConnections: [],
            }
        } else {
            groupedUsers[user.id].profiles.push(user.locale);
        }
    }

    for (let auth of authenticators) {
        groupedUsers[auth.userId].socialConnections.push(auth.type);
    }

    return res.json(groupedUsers);
});

const formatMonth = d => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;

const buildChart = (rows) => {
    const dates = rows.map(row => new Date(decodeTime(row.id)));

    const chart = {};

    let loop = dates[0];
    const end = dates[dates.length - 1];
    while(loop <= end){
        chart[formatMonth(loop)] = 0;
        loop = new Date(loop.setDate(loop.getDate() + 1));
    }
    chart[formatMonth(loop)] = 0;

    for (let date of dates) {
        chart[formatMonth(date)]++;
    }

    return chart;
}

router.get('/admin/stats', async (req, res) => {
    if (!req.isGranted('panel')) {
        return res.status(401).json({error: 'Unauthorised'});
    }

    const users = {
        overall: (await req.db.get(SQL`SELECT count(*) AS c FROM users`)).c,
        admins: (await req.db.get(SQL`SELECT count(*) AS c FROM users WHERE roles!=''`)).c,
        chart: buildChart(await req.db.all(SQL`SELECT id FROM users ORDER BY id`)),
    };

    const locales = {};
    for (let locale in req.locales) {
        if (!req.locales.hasOwnProperty(locale)) { continue; }
        if (!req.isGranted('panel', locale)) { continue; }
        const profiles = await req.db.all(SQL`SELECT pronouns, flags FROM profiles WHERE locale=${locale}`);
        const pronouns = {}
        const flags = {}
        for (let profile of profiles) {
            const pr = JSON.parse(profile.pronouns);
            for (let pronoun in pr) {
                if (!pr.hasOwnProperty(pronoun)) { continue; }

                if (pronoun.includes(',') || pr[pronoun] < 0) {
                    continue;
                }
                const p = pronoun.replace(/^.*:\/\//, '').replace(/^\//, '').toLowerCase().replace(/^[a-z]+\.[^/]+\//, '');
                if (pronouns[p] === undefined) {
                    pronouns[p] = 0;
                }
                pronouns[p] += pr[pronoun] === 1 ? 1 : 0.5;
            }

            const fl = JSON.parse(profile.flags);
            for (let flag of fl) {
                if (flags[flag] === undefined) {
                    flags[flag] = 0;
                }
                flags[flag] += 1;
            }
        }

        locales[locale] = {
            name: req.locales[locale].name,
            url: req.locales[locale].url,
            profiles: profiles.length,
            pronouns: sortByValue(pronouns, true),
            flags: sortByValue(flags, true),
            nouns: {
                approved: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=1 AND deleted=0`)).c,
                awaiting: (await req.db.get(SQL`SELECT count(*) AS c FROM nouns WHERE locale=${locale} AND approved=0 AND deleted=0`)).c,
            },
            chart: buildChart(await req.db.all(SQL`SELECT id FROM profiles WHERE locale=${locale} ORDER BY id`)),
        };
    }

    return res.json({ users, locales });
});

export default router;
