import moment from "moment";
import { v4 as uuidv4 } from "uuid";
import { Op } from "sequelize";
import { User } from "@/models/user";
import { Rule } from "@/models/rule";
import { z } from "zod";
import { Disease } from "../models/disease";
import { Symptom } from "../models/symptom";

export const CreateRule = async (req, res, next) => {
    try {
        const validator = z.object({
            disease_id: z
                .string({
                    required_error: "missing required field: disease_id",
                })
                .min("disease_id must be provided"),
            confidence: z.number({
                required_error: "missing required field: confidence",
            }),
            symptoms_id: z.array(z.string()),
            follow_up_questions: z.array(z.string()).optional(),
        });

        const body = validator.parse(req.body);
        const rule = await Rule.create({
            ...body,
            id: uuidv4(),
            created_by_id: req.user.id,
        });

        res.status(200).json({
            success: true,
            data: rule,
        });
    } catch (err) {
        next(err);
    }
};

export const GetRules = async (req, res, next) => {
    try {
        const { page = 1, limit = 10, search = "" } = req.query;

        const q = {};
        const query = {
            [Op.or]: ["$disease.name$"].map((field) => {
                return {
                    [field]: {
                        [Op.like]: `%${search}%`,
                    },
                };
            }),
        };

        const rules = await Rule.findAll({
            include: [
                {
                    model: User,
                    as: "created_by",
                    attributes: ["id", "username", "email", "role"],
                },
                {
                    model: Disease,
                    as: "disease",
                    attributes: [
                        "id",
                        "name",
                        "description",
                        "severity",
                        "treatment",
                    ],
                },
            ],
            where: query,
            order: [["created_at", "DESC"]],
            limit: Number(limit),
            offset: (Number(page) > 1 ? Number(page) - 1 : 0) * Number(limit),
        });

        const jsonOfRules = JSON.parse(JSON.stringify(rules));
        const symptoms = await Symptom.findAll({}, { raw: true });

        const result = jsonOfRules.map((item) => {
            return {
                ...item,
                symptoms: symptoms.filter((sym) =>
                    item.symptoms_id.includes(sym.id),
                ),
            };
        });

        const data_size = await Rule.count(q);
        const page_size = Math.ceil(data_size / Number(limit));
        const newest = await Rule.count({
            where: {
                created_at: {
                    [Op.gte]: moment().subtract(7, "d").toISOString(),
                },
            },
        });

        res.status(200).json({
            success: true,
            properties: {
                all: data_size,
                new: newest,
            },
            pagination: {
                current_page: Number(page),
                limit: Number(limit),
                data_size,
                page_size,
                next: Number(page) < page_size ? Number(page) + 1 : 0,
                prev: Number(page) > 1 ? Number(page) - 1 : 0,
            },
            data: result,
        });
    } catch (err) {
        next(err);
    }
};
