import { PrismaClient } from '@prisma/client';

import {
    CustomerDbInsertType,
    CustomerUpdateInputType,
    IdType,
} from '../../declarations/validations';

export interface ICustomerListService {}

export default class CustomerDatabaseService implements ICustomerListService {
    private prisma = new PrismaClient();

    async insertCustomer(customer: CustomerDbInsertType) {
        const {
            username,
            passwordHash,
            mail,
            ...customerProperties
        } = customer;

        return this.prisma.profile
            .create({
                data: {
                    ...customerProperties,
                    mail,
                    user: {
                        create: {
                            username,
                            passwordHash,
                            mail,
                            roles: {
                                connect: [{ id: 1 }], // TODO dynamic by seed
                            },
                        },
                    },
                },
            })
            .catch((e) => {
                throw e;
            })
            .finally(async () => {
                await this.prisma.$disconnect();
            });
    }

    async findCustomerById(customerId: IdType) {
        return this.prisma.profile
            .findFirst({
                where: {
                    id: customerId,
                    user: {
                        roles: {
                            some: {
                                name: 'customer', // TODO enum
                            },
                        },
                    },
                },
                include: {
                    projects: {
                        select: {
                            id: true,
                            project: {
                                select: {
                                    id: true,
                                    name: true,
                                    description: true,
                                    advisor: {
                                        select: {
                                            firstname: true,
                                            lastname: true,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            })
            .catch((e) => {
                throw e;
            })
            .finally(async () => {
                await this.prisma.$disconnect();
            });
    }

    async findAllCustomers() {
        return this.prisma.profile // TODO additional filter role customers required
            .findMany({
                where: {
                    user: {
                        roles: {
                            some: {
                                name: 'customer', // TODO enum
                            },
                        },
                    },
                },
                orderBy: [
                    {
                        firstname: 'asc',
                    },
                    {
                        lastname: 'asc',
                    },
                ],
            })
            .catch((e) => {
                throw e;
            })
            .finally(async () => {
                await this.prisma.$disconnect();
            });
    }

    async updateCustomer(customer: CustomerUpdateInputType) {
        const { id, ...updatedObject } = customer;
        return this.prisma.profile
            .update({
                where: {
                    id,
                },
                data: {
                    ...updatedObject,
                },
            })
            .catch((e) => {
                throw e;
            })
            .finally(async () => {
                await this.prisma.$disconnect();
            });
    }
}
