const express = require('express');
const r = express.Router();
const ur = express.Router();

import { MemberState } from '@app/shared/types/member';
import pool from '../db';
import { requireLogin, requireMemberState, requireRole } from '../middleware/auth';
import { assignUserGroup, createGroup, getAllRoles, getRole, getUsersWithRole } from '../services/db/rolesService';
import { Request, Response } from 'express';
import { logger } from '../services/logging/logger';

r.use(requireLogin)
ur.use(requireLogin)

//manually assign a member to a group
ur.post('/', [requireMemberState(MemberState.Member), requireRole("17th Administrator")], async (req: Request, res) => {
    const body = req.body;

    try {

        await assignUserGroup(body.member_id, body.role_id);

        logger.info('app', 'User assigned role', { user: body.member_id, role: body.role_id, assigner: req.user.id })
        res.sendStatus(201);
    } catch (error) {
        if (error?.code === 'ER_DUP_ENTRY') {
            return res.status(400).json({
                error: 'Member already has this role',
            });
        }

        logger.error(
            'app',
            'Failed to assign role',
            {
                user: body.member_id,
                role: body.role_id,
                assigner: req.user.id,
                error: error instanceof Error ? error.message : String(error),
                stack: error instanceof Error ? error.stack : undefined,
            }
        );
        res.status(500).json({ error: 'Failed to add to group' });
    }
});

//manually remove member from group
ur.delete('/', [requireMemberState(MemberState.Member), requireRole("17th Administrator")], async (req: Request, res: Response) => {
    const body = req.body;

    try {

        const sql = 'DELETE FROM members_roles WHERE member_id = ? AND role_id = ?'
        await pool.query(sql, [body.member_id, body.role_id])

        logger.info('app', 'User removed role', { user: body.member_id, role: body.role_id, assigner: req.user.id })

        res.sendStatus(200);
    }
    catch (error) {
        logger.error(
            'app',
            'Failed to remove role',
            {
                user: body.member_id,
                role: body.role_id,
                assigner: req.user.id,
                error: error instanceof Error ? error.message : String(error),
                stack: error instanceof Error ? error.stack : undefined,
            }
        );
        res.status(500).json({ error: 'Failed to remove from group' });
    }
})

//get all roles
r.get('/', [requireMemberState(MemberState.Member)], async (req, res) => {
    try {
        const roles = await getAllRoles();
        
        res.status(200).json(roles);
    } catch (error) {
        logger.error(
            'app',
            'Failed to get all roles',
            {
                error: error instanceof Error ? error.message : String(error),
                stack: error instanceof Error ? error.stack : undefined,
            }
        );
        res.sendStatus(500);
    }
});

r.get('/:id/members', [requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        const members = await getUsersWithRole(Number(req.params.id));
        res.status(200).json(members);
    } catch (error) {
        logger.error(
            'app',
            'Failed to get role members',
            {
                role: req.params.id,
                error: error instanceof Error ? error.message : String(error),
                stack: error instanceof Error ? error.stack : undefined,
            }
        );
        res.sendStatus(500);
    }
})


r.get('/:id', [requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        const role = await getRole(Number(req.params.id));
        res.status(200).json(role);
    } catch (error) {
        logger.error(
            'app',
            'Failed to get role members',
            {
                role: req.params.id,
                error: error instanceof Error ? error.message : String(error),
                stack: error instanceof Error ? error.stack : undefined,
            }
        );
        res.sendStatus(500);
    }
})



//create a new role
r.post('/', [requireMemberState(MemberState.Member), requireRole("dev")], async (req, res) => {
    try {
        const { name, color, description } = req.body;
        if (!name || !color) {
            return res.status(400).json({ error: 'Name and color are required' });
        }

        const hexColorRegex = /^#([0-9A-Fa-f]{6})$/;
        if (!hexColorRegex.test(color)) {
            return res.status(400).json({ error: 'Color must be a valid hex color (#ffffff)' });
        }

        await createGroup(name, color, description);

        res.sendStatus(201);
    } catch (err) {
        console.error('Insert failed:', err);
        res.status(500).json({ error: 'Failed to create role' });
    }
})

r.delete('/:id', [requireMemberState(MemberState.Member), requireRole("dev")], async (req, res) => {
    try {
        const id = req.params.id;

        const sql = 'DELETE FROM roles WHERE id = ?';
        const res = await pool.query(sql, [id]);
        res.sendStatus(200);
    } catch (error) {
        console.error(error);
        res.sendStatus(500);
    }
})

export const roles = r;
export const memberRoles = ur;
