import { Request, Response } from 'express';
import ProjectDatabaseService from '../services/db/projectList';
import {
    ProjectCreationInput,
    ProjectDbInsert,
    Id,
    ProjectUpdateInput,
} from '../declarations/validations';
import SecurityUtil from '../utils/security/securityUtil';
import { Role } from '../declarations/roles';

export class ProjectController {
    private projectListService = new ProjectDatabaseService();

    createProject(req: Request, res: Response) {
        if (req.body.price) {
            req.body.price = parseInt(req.body.price, 10);
        }

        if (req.body.advisorId) {
            req.body.advisorId = parseInt(req.body.advisorId, 10);
        }

        req.body.customerId = parseInt(req.body.customerId, 10);

        const result = ProjectCreationInput.safeParse({
            ...req.body,
        });

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

        const user = SecurityUtil.currentUser(req);

        const project = ProjectDbInsert.parse({
            creatorId: user?.profileId,
            ...result.data,
        });

        this.projectListService
            .insertProject(project)
            .then((createdProject) => {
                res.send({ success: 'Created.', project: createdProject });
            });
    }

    async getProject(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 currentUser = SecurityUtil.currentUser(req);
        switch (currentUser?.role) {
            case Role.Customer:
                this.projectListService
                    .findProjectByIdAndParticipation(id, currentUser?.profileId)
                    .then((project) => {
                        if (!project) {
                            res.status(400).send({
                                error: `No project found with id ${id} or not participants`,
                            });
                            return;
                        }

                        res.send({ project });
                    });
                break;

            case Role.Employee:
                this.projectListService
                    .findProjectById(id)
                    .then((project) => res.send({ project }));
                break;

            default:
                res.sendStatus(403);
        }
    }

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

        if (req.body.price) {
            req.body.price = parseInt(req.body.price, 10);
        }

        if (req.body.advisorId) {
            req.body.advisorId = parseInt(req.body.advisorId, 10);
        }

        if (req.body.customerId) {
            req.body.customerId = parseInt(req.body.customerId, 10);
        }

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

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

        const currentUser = SecurityUtil.currentUser(req);
        switch (currentUser?.role) {
            case Role.Employee:
                this.projectListService
                    .updateProject(project)
                    .then((updatedProject) =>
                        res.send({ project: updatedProject })
                    );
                break;

            default:
                res.sendStatus(403);
        }

        //updateJobInformation( // TODO update customer
        //    jobId,
        //    employeeId,
        //    name,
        //    description,
        //    price,
        //    customerId,
        //    advisorId
        //);

        //if (status) {
        //    findCurrentJobStatus(jobId).then((jobStatus) => {
        //        if (jobStatus && status !== jobStatus.status)
        //            updateJobStatus(jobId, employeeId, status);
        //    });
        //}
        //
        //if (video) {
        //}
    }

    removeProject(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;

        this.projectListService
            .deleteProject(id)
            .then((deletedProject) => res.send({ project: deletedProject }))
            .catch(() => {
                res.sendStatus(500);
            });
    }

    async getProjects(req: Request, res: Response) {
        const currentUser = SecurityUtil.currentUser(req);
        switch (currentUser?.role) {
            case Role.Customer:
                // eslint-disable-next-line no-case-declarations
                const projects = await this.projectListService.findAllProjectsByProfileId(
                    currentUser?.profileId
                );
                if (!projects) {
                    res.status(403).send({ error: 'Not involved' });
                    return;
                }
                res.send({ projects });

                break;
            case Role.Employee:
                this.projectListService.findAllProjects().then((projects) => {
                    res.send(projects);
                });
                break;

            default:
                res.sendStatus(403);
        }
    }
}

export const projectController = new ProjectController();
