import { toDateTime } from "@app/shared/utils/time";
import pool from "../../db";
import { LOARequest, LOAType } from '@app/shared/types/loa'
import { PagedData } from '@app/shared/types/pagination'

export async function getLoaTypes(): Promise<LOAType[]> {
    return await pool.query('SELECT * FROM leave_of_absences_types;');
}

export async function getAllLOA(page = 1, pageSize = 10): Promise<PagedData<LOARequest>> {
    const offset = (page - 1) * pageSize;

    const sql = `
        SELECT loa.*, members.name, t.name AS type_name
        FROM leave_of_absences AS loa
        LEFT JOIN members ON loa.member_id = members.id
        LEFT JOIN leave_of_absences_types AS t ON loa.type_id = t.id
        ORDER BY
            CASE
                WHEN loa.closed IS NULL 
                     AND NOW() > COALESCE(loa.extended_till, loa.end_date) THEN 1
                WHEN loa.closed IS NULL
                     AND NOW() BETWEEN loa.start_date AND COALESCE(loa.extended_till, loa.end_date) THEN 2
                WHEN loa.closed IS NULL AND NOW() < loa.start_date THEN 3
                WHEN loa.closed IS NOT NULL THEN 4
            END,
            loa.start_date DESC
        LIMIT ? OFFSET ?;
    `;
    let loaList: LOARequest[] = await pool.query(sql, [pageSize, offset]) as LOARequest[];

    let loaCount = Number((await pool.query(`SELECT COUNT(*) as count FROM leave_of_absences;`))[0].count);
    let pageCount = loaCount / pageSize;

    let output: PagedData<LOARequest> = { data: loaList, pagination: { page: page, pageSize: pageSize, total: loaCount, totalPages: pageCount } }
    return output;
}

export async function getUserLOA(userId: number, page = 1, pageSize = 10): Promise<PagedData<LOARequest>> {

    const offset = (page - 1) * pageSize;

    const result: LOARequest[] = await pool.query(`
        SELECT loa.*, members.name, t.name AS type_name
            FROM leave_of_absences AS loa
            LEFT JOIN members ON loa.member_id = members.id
            LEFT JOIN leave_of_absences_types AS t ON loa.type_id = t.id
            WHERE member_id = ?         
            ORDER BY
                CASE
                    WHEN loa.closed IS NULL 
                        AND NOW() > COALESCE(loa.extended_till, loa.end_date) THEN 1
                    WHEN loa.closed IS NULL
                        AND NOW() BETWEEN loa.start_date AND COALESCE(loa.extended_till, loa.end_date) THEN 2
                    WHEN loa.closed IS NULL AND NOW() < loa.start_date THEN 3
                    WHEN loa.closed IS NOT NULL THEN 4
                END,
                loa.start_date DESC
                LIMIT ? OFFSET ?;`, [userId, pageSize, offset])

    let loaCount = Number((await pool.query(`SELECT COUNT(*) as count FROM leave_of_absences WHERE member_id = ?;`, [userId]))[0].count);
    let pageCount = loaCount / pageSize;
    let output: PagedData<LOARequest> = { data: result, pagination: { page: page, pageSize: pageSize, total: loaCount, totalPages: pageCount } }
    return output;
}

export async function getUserActiveLOA(userId: number): Promise<LOARequest[]> {
    const sql = `SELECT *
            FROM leave_of_absences
            WHERE member_id = ?
            AND closed IS NULL
            AND UTC_TIMESTAMP() BETWEEN start_date AND end_date;`
    const LOAData = await pool.query(sql, [userId]);
    return LOAData;
}

export async function createNewLOA(data: LOARequest) {
    const sql = `INSERT INTO leave_of_absences 
                (member_id, filed_date, start_date, end_date, type_id, reason) 
             VALUES (?, ?, ?, ?, ?, ?)`;
    await pool.query(sql, [data.member_id, toDateTime(data.filed_date), toDateTime(data.start_date), toDateTime(data.end_date), data.type_id, data.reason])
    return;
}

export async function closeLOA(id: number, closer: number) {
    const sql = `UPDATE leave_of_absences
                SET closed = 1,
                closed_by = ?,
                ended_at = NOW()
                WHERE leave_of_absences.id = ?`;
    let out = await pool.query(sql, [closer, id]);
    return out;
}

export async function getLOAbyID(id: number): Promise<LOARequest> {
    let res = await pool.query(`SELECT * FROM leave_of_absences WHERE id = ?`, [id]);
    if (res.length != 1)
        throw new Error(`LOA with id ${id} not found`);
    return res[0];
}

export async function setLOAExtension(id: number, extendTo: Date) {
    let res = await pool.query(`UPDATE leave_of_absences
                                    SET extended_till = ?
                                    WHERE leave_of_absences.id = ? `, [toDateTime(extendTo), id]);
    if (res.affectedRows != 1)
        throw new Error(`Could not extend LOA`);
    return res[0];
}