import { Injectable } from "@nestjs/common";
import { Result } from "src/common/errors/result-error.factory";
import { PrismaMariaDbService } from "prisma/mariadb/prisma-mariadb.service";
import { TicketList } from "src/customer-support/tickets/dtos/ticket-list.dto";
import { sortOrders, sortTypes } from "src/customer-support/tickets/dtos/ticket.dto";
import { Prisma } from "prisma/mariadb/generated/prisma/client/mariadb/client";

export const TIMESTAMP_MINIMUM = 1672531200; // 1er janvier 2023

@Injectable()
export class GetTicketListService {
    constructor(private readonly prisma: PrismaMariaDbService) { }

    getListOfAllTicketByFilters = async (
        status: string[],
        offset: number = 0,
        limit: number = 25,
        sortOrder: string = 'last_update',
        sortType: 'DESC' | 'ASC' = 'DESC',
        email?: string
    ): Promise<Result<TicketList[], string>> => {

        try {
            const staff = await this.prisma.staff.findFirst({
                where: { email },
            });
            if (!staff) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }
            if (!sortOrders.includes(sortOrder) || !sortTypes.includes(sortType)) {
                return { success: false, error: 'INVALID_FILTER' }
            }

            const statusList = Prisma.join(status);

            const rawTicketList = await this.prisma.$queryRaw<TicketList[]>(
                Prisma.sql`
                SELECT 
                    t.id AS id,
                    t.status AS status, 
                    CONCAT(s.first_name,' ',s.last_name) AS assignTo, 
                    a.address1    AS deliveryAddress,
                    t.subject     AS subject,
                    d.name        AS department,
                    t.parent      AS parentTicketId,

                    CASE
                        WHEN t.due_date > 1672531200
                            THEN FROM_UNIXTIME(t.due_date, '%d/%m/%y')
                        ELSE NULL
                    END AS dueDate,

                    FROM_UNIXTIME(t.last_update, '%d/%m/%y') AS lastUpdate,

                    CASE
                        WHEN CAST(t.date_closed AS UNSIGNED) > 1672531200
                            THEN FROM_UNIXTIME(CAST(t.date_closed AS UNSIGNED), '%d/%m/%y')
                        ELSE NULL
                    END AS completedAt

                FROM staff s
                LEFT JOIN ticket t      ON t.assign_to  = s.id
                LEFT JOIN account a     ON t.account_id = a.id
                LEFT JOIN ticket_dept d ON t.dept_id    = d.id
                
                WHERE t.status IN (${statusList})
                ORDER BY ${Prisma.raw(sortOrder)} ${Prisma.raw(sortType)}
                    CASE 
                        WHEN t.status = 'open'    AND t.assign_to = 0            THEN 0
                        WHEN t.status = 'open'    AND t.assign_to = ${staff.id}  THEN 1
                        WHEN t.status = 'pending' AND t.assign_to = ${staff.id}  THEN 2
                        WHEN t.status = 'open'    AND t.assign_to != ${staff.id} THEN 3
                        WHEN t.status = 'pending' AND t.assign_to != ${staff.id} THEN 4
                        ELSE 5
                    END
                LIMIT ${limit} OFFSET ${offset}
            `);

            return { success: true, data: rawTicketList }
        } catch (error) {
            return { success: false, error: 'TICKET_LIST_NOT_FOUND, ' + error };
        }
    }

    getListOfTickets = async (
        email: string,
        offset: number = 0,
        limit: number = 25,
    ): Promise<Result<TicketList[], string>> => {

        try {
            const staff = await this.prisma.staff.findFirst({
                where: { email },
            });
            if (!staff) return { success: false, error: 'EMPLOYEE_NOT_FOUND' }

            const rawTicketList = await this.prisma.$queryRaw<TicketList[]>(
                Prisma.sql`
                SELECT 
                    t.id AS id,
                    t.status AS status, 
                    CONCAT(s.first_name,' ',s.last_name) AS assignTo, 
                    a.address1    AS deliveryAddress,
                    t.subject     AS subject,
                    d.name        AS department,
                    t.parent      AS parentTicketId,

                    CASE
                        WHEN t.due_date > 1672531200
                            THEN FROM_UNIXTIME(t.due_date, '%d/%m/%y')
                        ELSE NULL
                    END AS dueDate,

                    FROM_UNIXTIME(t.last_update, '%d/%m/%y') AS lastUpdate,

                    CASE
                        WHEN CAST(t.date_closed AS UNSIGNED) > 1672531200
                            THEN FROM_UNIXTIME(CAST(t.date_closed AS UNSIGNED), '%d/%m/%y')
                        ELSE NULL
                    END AS completedAt

                FROM staff s
                LEFT JOIN ticket t      ON t.assign_to  = s.id
                LEFT JOIN account a     ON t.account_id = a.id
                LEFT JOIN ticket_dept d ON t.dept_id    = d.i
                ORDER BY
                    CASE 
                        WHEN t.status = 'open'    AND t.assign_to = 0            THEN 0
                        WHEN t.status = 'open'    AND t.assign_to = ${staff.id}  THEN 1
                        WHEN t.status = 'pending' AND t.assign_to = ${staff.id}  THEN 2
                        WHEN t.status = 'open'    AND t.assign_to != ${staff.id} THEN 3
                        WHEN t.status = 'pending' AND t.assign_to != ${staff.id} THEN 4
                        ELSE 5
                    END
                LIMIT ${limit} OFFSET ${offset};
            `);

            return { success: true, data: rawTicketList }
        } catch (error) {
            return { success: false, error: 'TICKET_LIST_NOT_FOUND, ' + error };
        }
    }
}