import moment from "moment";
import { v4 as uuidv4 } from "uuid";
import { Op } from "sequelize";
import { User } from "@/models/user";
import { FollowUpQuestion, Symptom } from "@/models/symptom";
import { z } from "zod";

export const CreateSymptom = async (req, res, next) => {
    try {
        const validator = z.object({
            name: z
                .string({ required_error: "missing required field: name" })
                .min("name must be provided"),
            description: z.string({
                required_error: "missing required field: description",
            }),
            category: z.enum(
                ["danger", "respiratory", "digestive", "general", "specific"],
                {
                    required_error: "missing required field: category",
                },
            ),
            question: z
                .string({
                    required_error: "missing required field: question",
                })
                .min("question must be provided"),
            follow_up_questions: z
                .array(
                    z.object({
                        question: z
                            .string({
                                required_error:
                                    "missing required field: question",
                            })
                            .min("question must be provided"),
                        type: z.enum(
                            [
                                "generic",
                                "duration",
                                "severity",
                                "frequency",
                                "yes/no",
                            ],
                            {
                                required_error: "missing required field: type",
                            },
                        ),
                        options: z.array(z.string()).optional(),
                    }),
                )
                .optional(),
        });

        const body = validator.parse(req.body);
        const symptomLength = await Symptom.count();
        const symptom = (
            await Symptom.create({
                ...body,
                id: uuidv4(),
                index: symptomLength,
                created_by_id: req.user.id,
            })
        )?.get({ plain: true });

        if (body.follow_up_questions) {
            await FollowUpQuestion.bulkCreate(
                body.follow_up_questions.map((item) => ({
                    ...item,
                    id: uuidv4(),
                    symptom_id: symptom.id,
                })),
            );
        }

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

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

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

        const symptoms = await Symptom.findAll({
            where: query,
            include: [
                {
                    model: User,
                    as: "created_by",
                    attributes: ["id", "username", "email", "role"],
                },
                {
                    model: FollowUpQuestion,
                    as: "follow_up_questions",
                    attributes: ["id", "question", "type", "options"],
                },
            ],
            order: [["index", "ASC"]],
        });

        const data_size = await Symptom.count(q);
        const page_size = Math.ceil(data_size / Number(limit));
        const newest = await Symptom.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: symptoms,
        });
    } catch (err) {
        next(err);
    }
};

export const RepositionSymptom = async (req, res, next) => {
    try {
        const prev = await Symptom.findByPk(req.params.id);
        const { index } = req.body;

        if (index < prev.index) {
            await Symptom.increment("index", {
                by: 1,
                where: {
                    index: {
                        [Op.gte]: index,
                        [Op.lt]: prev.index,
                    },
                },
            });
        } else {
            await Symptom.decrement("index", {
                by: 1,
                where: {
                    index: {
                        [Op.gt]: prev.index,
                        [Op.lte]: index,
                    },
                },
            });
        }

        await Symptom.update({ index }, { where: { id: req.params.id } });
        const symptom = await Symptom.findByPk(req.params.id);

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