const crypto = require('crypto');
const db = require("../config/db");

class SheepService {
    getSheep(id, mode) {
        return new Promise((res, rej) => {
            const sql = `
                SELECT 
                    sheeps.*,
                    possibilities.can_add_sheeps,
                    possibilities.can_view_sheeps,
                    possibilities.can_manager_sheeps,
                    possibilities.can_add_territory,
                    possibilities.can_view_territory,
                    possibilities.can_manager_territory,
                    possibilities.can_joint_territory,
                    possibilities.can_add_stand,
                    possibilities.can_view_stand,
                    possibilities.can_manager_stand,
                    possibilities.can_add_schedule,
                    possibilities.can_view_schedule
                FROM 
                    sheeps
                LEFT JOIN 
                    possibilities ON possibilities.sheep_id = sheeps.id
                WHERE 
                    sheeps.id = ?
            `;

            db.get(sql, [id], (err, sheep) => {
                if (err) {
                    console.error(err.message);
                    return res(false);
                }
                if (!sheep) {
                    console.log({ error: "id not found" });
                    return res(false);
                }

                const fields = [
                    "can_add_sheeps",
                    "can_view_sheeps",
                    "can_manager_sheeps",
                    "can_add_territory",
                    "can_view_territory",
                    "can_manager_territory",
                    "can_joint_territory",
                    "can_add_stand",
                    "can_view_stand",
                    "can_manager_stand",
                    "can_add_schedule",
                    "can_view_schedule"
                ];

                const data = {
                    id: sheep.id,
                    group_id: sheep.group_id,
                    name: sheep.name,
                    icon: sheep.icon,
                    uuid: sheep.uuid,
                    uuid_manager: mode && mode === 2 ? sheep.uuid_manager : null,
                    mode: mode ? Number(sheep.mode) : 0,
                    mode_title: sheep.mode_title,
                    possibilities: {}
                };

                fields.forEach(f => {
                    data.possibilities[f] = false;
                });


                if (mode && (mode === 1 || mode === 2)) {
                    fields.forEach(f => {
                        data.possibilities[f] = !!sheep[f];
                    });
                }

                return res(data);
            });
        });
    }

    getList(mode) {
        return new Promise((res, rej) => {
            const sql = `
                SELECT 
                    sheeps.*,
                    possibilities.can_add_sheeps,
                    possibilities.can_view_sheeps,
                    possibilities.can_manager_sheeps,
                    possibilities.can_add_territory,
                    possibilities.can_view_territory,
                    possibilities.can_manager_territory,
                    possibilities.can_joint_territory,
                    possibilities.can_add_stand,
                    possibilities.can_view_stand,
                    possibilities.can_manager_stand,
                    possibilities.can_add_schedule,
                    possibilities.can_view_schedule
                FROM 
                    sheeps
                LEFT JOIN 
                    possibilities ON possibilities.sheep_id = sheeps.id
                ORDER BY 
                    sheeps.group_id
            `;

            db.all(sql, (err, rows) => {
                if (err) {
                    console.error(err.message);
                    return res(false);
                }

                const fields = [
                    "can_add_sheeps",
                    "can_view_sheeps",
                    "can_manager_sheeps",
                    "can_add_territory",
                    "can_view_territory",
                    "can_manager_territory",
                    "can_joint_territory",
                    "can_add_stand",
                    "can_view_stand",
                    "can_manager_stand",
                    "can_add_schedule",
                    "can_view_schedule"
                ];

                const result = rows.map(sheep => {
                    const data = {
                        id: sheep.id,
                        group_id: sheep.group_id,
                        name: sheep.name,
                        icon: sheep.icon,
                        uuid: sheep.uuid,
                        uuid_manager: (mode && mode == 2) ? sheep.uuid_manager : null,
                        mode: mode ? Number(sheep.mode) : 0,
                        mode_title: sheep.mode_title,
                        possibilities: {}
                    };

                    fields.forEach(f => {
                        data.possibilities[f] = false;
                    });

                    if (mode && (mode == 1 || mode == 2)) {
                        fields.forEach(f => {
                            data.possibilities[f] = !!sheep[f];
                        });
                    }

                    return data;
                });

                res(result);
            });
        });
    }

    getListStand(mode) {
        return new Promise((res, rej) => {
            const sql = `
                SELECT 
                    sheeps.*,
                    possibilities.can_add_sheeps,
                    possibilities.can_view_sheeps,
                    possibilities.can_manager_sheeps,
                    possibilities.can_add_territory,
                    possibilities.can_view_territory,
                    possibilities.can_manager_territory,
                    possibilities.can_joint_territory,
                    possibilities.can_add_stand,
                    possibilities.can_view_stand,
                    possibilities.can_manager_stand,
                    possibilities.can_add_schedule,
                    possibilities.can_view_schedule
                FROM 
                    sheeps
                LEFT JOIN 
                    possibilities ON possibilities.sheep_id = sheeps.id
                WHERE 
                    possibilities.can_view_stand = '1'
                ORDER BY 
                    sheeps.group_id;
            `;

            db.all(sql, (err, rows) => {
                if (err) {
                    console.error(err.message);
                    return res(false);
                }

                const fields = [
                    "can_add_sheeps",
                    "can_view_sheeps",
                    "can_manager_sheeps",
                    "can_add_territory",
                    "can_view_territory",
                    "can_manager_territory",
                    "can_joint_territory",
                    "can_add_stand",
                    "can_view_stand",
                    "can_manager_stand",
                    "can_add_schedule",
                    "can_view_schedule"
                ];

                const result = rows.map(sheep => {
                    const data = {
                        id: sheep.id,
                        group_id: sheep.group_id,
                        name: sheep.name,
                        icon: sheep.icon,
                        uuid: (mode && mode == 2) ? sheep.uuid : null,
                        uuid_manager: (mode && mode == 2) ? sheep.uuid_manager : null,
                        mode: mode ? Number(sheep.mode) : 0,
                        mode_title: sheep.mode_title,
                        possibilities: {}
                    };

                    fields.forEach(f => {
                        data.possibilities[f] = false;
                    });

                    if (mode && (mode == 1 || mode == 2)) {
                        fields.forEach(f => {
                            data.possibilities[f] = !!sheep[f];
                        });
                    }

                    return data;
                });

                res(result);
            });
        });
    }

    createSheep(data) {
        const stmt1 = db.prepare('INSERT INTO sheeps(name, group_id, uuid) VALUES (?, ?, ?)');
        const stmt2 = db.prepare('INSERT INTO possibilities(can_view_territory, sheep_id) VALUES (?, ?)');

        return new Promise((res, rej) => {
            db.serialize(() => {
                let uuid = crypto.randomUUID();

                stmt1.run([
                    data.name,
                    Number(data.group_id),
                    uuid
                ], function (err) {
                    if (err) return rej(err);

                    const newSheepId = this.lastID;

                    stmt2.run([
                        1,
                        newSheepId
                    ], (err2) => {
                        if (err2) return rej(err2);
                        res({ status: "ok", id: newSheepId, uuid: uuid });
                    });
                });
            });
        });
    }

    updateSheep(data, mode) {
        if (mode == 2) {
            const stmt1 = db.prepare(`
                UPDATE 
                    sheeps 
                SET 
                    name = ?, 
                    group_id = ?, 
                    mode = ?, 
                    mode_title = ?,
                    uuid_manager = ?
                WHERE 
                    uuid = ?
            `);

            const stmt2 = db.prepare(`
                UPDATE 
                    possibilities 
                SET 
                    can_add_sheeps = ?, 
                    can_view_sheeps = ?,
                    can_manager_sheeps = ?,
                    can_add_territory = ?, 
                    can_view_territory = ?, 
                    can_manager_territory = ?,
                    can_joint_territory = ?,
                    can_add_stand = ?, 
                    can_view_stand = ?, 
                    can_manager_stand = ?, 
                    can_add_schedule = ?, 
                    can_view_schedule = ?
                WHERE 
                    sheep_id = (SELECT id FROM sheeps WHERE uuid = ? LIMIT 1)
            `);

            return new Promise((res, rej) => {
                db.serialize(() => {
                    let uuid_manager = crypto.randomUUID();

                    stmt1.run([
                        data.name,
                        Number(data.group_id),
                        Number(data.mode),
                        data.mode_title,
                        Number(data.mode) == 0 ? null : (data.uuid_manager ? data.uuid_manager : uuid_manager),
                        data.uuid
                    ], (err) => {
                        if (err) return rej(err);

                        stmt2.run([
                            data.possibilities.can_add_sheeps,
                            data.possibilities.can_view_sheeps,
                            data.possibilities.can_manager_sheeps,
                            data.possibilities.can_add_territory,
                            data.possibilities.can_view_territory,
                            data.possibilities.can_manager_territory,
                            data.possibilities.can_joint_territory,
                            data.possibilities.can_add_stand,
                            data.possibilities.can_view_stand,
                            data.possibilities.can_manager_stand,
                            data.possibilities.can_add_schedule,
                            data.possibilities.can_view_schedule,
                            data.uuid
                        ], (err2) => {
                            if (err2) return rej(err2);
                            res({ status: "ok", id: data.id });
                        });
                    });
                });
            });
        } else if(mode == 1){
            const stmt1 = db.prepare(`
                UPDATE 
                    sheeps 
                SET 
                    name = ?, 
                    group_id = ?
                WHERE 
                    uuid = ?
            `);

            const stmt2 = db.prepare(`
                UPDATE 
                    possibilities 
                SET 
                    can_view_territory = ?, 
                    can_view_stand = ?, 
                    can_view_schedule = ?
                WHERE 
                    sheep_id = (SELECT id FROM sheeps WHERE uuid = ? LIMIT 1)
            `);

            return new Promise((res, rej) => {
                db.serialize(() => {
                    stmt1.run([
                        data.name,
                        Number(data.group_id),
                        data.uuid
                    ], (err) => {
                        if (err) return rej(err);

                        stmt2.run([
                            data.possibilities.can_view_territory,
                            data.possibilities.can_view_stand,
                            data.possibilities.can_view_schedule,
                            data.uuid
                        ], (err2) => {
                            if (err2) return rej(err2);
                            res({ status: "ok", id: data.id });
                        });
                    });
                });
            });
        }
    }

    deleteSheep(data) {
        const stmtSelect = db.prepare('SELECT id FROM sheeps WHERE uuid = ?');
        const stmtDeletePoss = db.prepare('DELETE FROM possibilities WHERE sheep_id = ?');
        const stmtDeleteSheep = db.prepare('DELETE FROM sheeps WHERE uuid = ?');

        return new Promise((res, rej) => {
            db.serialize(() => {
                stmtSelect.get([data.uuid], (err, row) => {
                    if (err) return rej(err);
                    if (!row) return rej(new Error("Sheep not found"));

                    const sheepId = row.id;

                    stmtDeletePoss.run([sheepId], (err2) => {
                        if (err2) return rej(err2);

                        stmtDeleteSheep.run([data.uuid], (err3) => {
                            if (err3) return rej(err3);
                            res({ status: "ok", deletedSheepId: sheepId });
                        });
                    });
                });
            });
        });
    }
}

module.exports = new SheepService();