import { Request, Response } from 'express';
import EmployeeDatabaseService from '../services/db/employeeList';
import PasswordMgmt from '../utils/security/passwordMgmt';
import {
    EmployeeCreationInput,
    EmployeeDbInsert,
    EmployeeUpdateInput,
    Id,
} from '../declarations/validations';
import SecurityUtil from '../utils/security/securityUtil';
import { Role } from '../declarations/roles';

export class EmployeeController {
    public employeeListService = new EmployeeDatabaseService();

    async createEmployee(req: Request, res: Response) {
        const result = await EmployeeCreationInput.safeParseAsync({
            username: req.body.mail,
            ...req.body,
        });
        if (!result.success) {
            res.status(400).send({ error: 'Invalid input' });
            return;
        }

        const { password } = result.data;

        const passwordHash = await PasswordMgmt.generatePasswordHash(password);

        const employee = EmployeeDbInsert.parse({
            passwordHash,
            ...result.data,
        });

        this.employeeListService.insertEmployee(employee).then(() => {
            res.send({
                success: `Employee ${employee.firstname} ${employee.lastname} successfully registered`,
            });
        });
    }

    getEmployee(req: Request, res: Response) {
        const idInput = parseInt(req.params.id, 10);

        const result = Id.safeParse(idInput);

        if (!result.success) {
            res.status(400).send({ error: 'Invalid identifier' });
            return;
        }

        const id = result.data;
        const currentRole = SecurityUtil.currentRole(req);

        switch (currentRole) {
            case Role.Employee:
                this.employeeListService
                    .findEmployeeById(id)
                    .then((employee) => {
                        res.send({ employee });
                    });
                break;

            default:
                res.sendStatus(403);
        }
    }

    updateEmployee(req: Request, res: Response) {
        const idInput = parseInt(req.params.id, 10);

        const result = EmployeeUpdateInput.safeParse({
            id: idInput,
            ...req.body,
        });
        if (!result.success) {
            res.status(400).send({ error: 'Invalid input' });
            return;
        }

        const employee = {
            ...result.data,
        };

        const currentRole = SecurityUtil.currentRole(req);
        switch (currentRole) {
            case Role.Employee:
                this.employeeListService
                    .updateEmployee(employee)
                    .then((updatedEmployee) => res.send({ updatedEmployee }));
                break;

            default:
                res.sendStatus(403);
        }
    }

    getEmployees(req: Request, res: Response) {
        this.employeeListService.findAllEmployees().then((employees) => {
            res.send({ success: 'Employees successfully fetched.', employees });
        });
    }
}

export const employeeController = new EmployeeController();
