import { z } from "zod";
import { v4 as uuidv4 } from "uuid";
import { Rule } from "@/models/rule";
import { literal, Op } from "sequelize";
import { Disease } from "@/models/disease";
import { Symptom } from "@/models/symptom";
import { Diagnose } from "@/models/diagnose";

export const CreateDiagnose = async (req, res, next) => {
    try {
        const validator = z.object({
            symptoms_id: z.array(z.string()),
            follow_up_questions: z
                .array(
                    z.object({
                        symptom_id: z.string(),
                        question: z.string(),
                        option: z.string(),
                    }),
                )
                .optional(),
        });

        const body = validator.parse(req.body);
        let rule = (
            await Rule.findOne({
                where: {
                    [Op.and]: [
                        {
                            [Op.and]: [
                                literal(
                                    `JSON_CONTAINS(symptoms_id, '[${body.symptoms_id.map((id) => `"${id}"`).join(", ")}]')`,
                                ),
                                literal(
                                    `JSON_LENGTH(symptoms_id) = ${body.symptoms_id.length}`,
                                ),
                            ],
                        },
                        {
                            [Op.and]: [
                                literal(
                                    `JSON_CONTAINS(follow_up_questions, '[${body.follow_up_questions.map((item) => `"${item.question}: ${item.option}"`).join(", ")}]')`,
                                ),
                            ],
                        },
                    ],
                },
                include: [
                    {
                        model: Disease,
                        as: "disease",
                        attributes: [
                            "id",
                            "name",
                            "description",
                            "severity",
                            "treatment",
                        ],
                    },
                ],
            })
        )?.get({ plain: true });

        const symptoms = await Symptom.findAll({
            where: {
                id: {
                    [Op.in]: body.symptoms_id,
                },
            },
            raw: true,
        });

        if (body.symptoms_id[0] === "b82fb6e4-7656-42e7-8e22-c4e9a94d5466") {
            rule = (
                await Rule.findOne({
                    where: {
                        [Op.and]: [
                            {
                                [Op.and]: [
                                    literal(
                                        `JSON_CONTAINS(symptoms_id, '[${body.symptoms_id.map((id) => `"${id}"`).join(", ")}]')`,
                                    ),
                                    literal(
                                        `JSON_LENGTH(symptoms_id) = ${body.symptoms_id.length}`,
                                    ),
                                ],
                            },
                        ],
                    },
                    include: [
                        {
                            model: Disease,
                            as: "disease",
                            attributes: [
                                "id",
                                "name",
                                "description",
                                "severity",
                                "treatment",
                            ],
                        },
                    ],
                })
            )?.get({ plain: true });
        }

        if (rule) {
            await Diagnose.create({
                ...body,
                id: uuidv4(),
                patient_id: req.params.patient,
                disease_id: rule.disease.id,
                created_by_id: req.user.id,
            });
        }

        res.status(200).json({
            success: true,
            data: rule
                ? {
                      ...rule,
                      follow_up_questions: body.follow_up_questions,
                      symptoms,
                  }
                : null,
        });
    } catch (err) {
        next(err);
    }
};

export const GetDiagnoseById = async (req, res, next) => {
    try {
        const rule = (
            await Diagnose.findOne({
                where: {
                    patient_id: req.params.patient,
                },
                include: [
                    {
                        model: Disease,
                        as: "disease",
                        attributes: [
                            "id",
                            "name",
                            "description",
                            "severity",
                            "treatment",
                        ],
                    },
                ],
            })
        )?.get({ plain: true });

        const symptoms = await Symptom.findAll({
            where: {
                id: {
                    [Op.in]: rule.symptoms_id,
                },
            },
            raw: true,
        });

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