const db = require("../models");
const { splitSite } = require("../middlewares");

const DocTemplate = db.doctemplate;
const ExcelTemplate = db.exceltemplate;

const TEMPLATE_DEFINITIONS = [
  {
    key: "medical_notifications_template",
    label: "Medical Notifications Template",
    type: "doc",
    templateName: "med_notification",
    modelPath: "doctemplate",
  },
  {
    key: "visit_record_template",
    label: "Visit Record Template",
    type: "sheet",
    templateName: "visit_record_sheet",
    modelPath: "xlsxtemplate",
  },
];

const getTemplateDefinition = (key) => TEMPLATE_DEFINITIONS.find((item) => item.key === key);

const getModelByDefinition = (definition) => (
  definition.type === "doc" ? DocTemplate : ExcelTemplate
);

const findOrCreateTemplateDoc = async (definition, site, userName) => {
  const model = getModelByDefinition(definition);
  let templateDoc = await model.findOne({
    name: definition.templateName,
    site,
  }).sort({ createdAt: -1 });

  if (!templateDoc) {
    templateDoc = await model.create({
      name: definition.templateName,
      status: "active",
      site,
      file: [],
      create_by: userName,
      create_date: new Date(),
      edit_by: userName,
      edit_date: new Date(),
      edit_history: [{ employee: userName, date: new Date() }],
    });
  }

  return templateDoc;
};

exports.listTemplates = async (req, res) => {
  try {
    const site = splitSite.findSiteNumber(req);
    const templateRows = [];

    for (const definition of TEMPLATE_DEFINITIONS) {
      const model = getModelByDefinition(definition);
      const templateDoc = await model.findOne({
        name: definition.templateName,
        site,
      }).sort({ createdAt: -1 });
      const latestFile = templateDoc?.file?.[0] || null;

      templateRows.push({
        key: definition.key,
        label: definition.label,
        templateType: definition.type,
        templateName: definition.templateName,
        site,
        templateId: templateDoc?.id || null,
        file: latestFile
          ? {
              name: latestFile.name || "",
              originalName: latestFile.originalName || latestFile.name || "",
              url: latestFile.url || "",
              uploadedAt: latestFile.uploadedAt || templateDoc?.edit_date || templateDoc?.updatedAt || null,
            }
          : null,
      });
    }

    return res.status(200).send({
      success: true,
      data: templateRows,
    });
  } catch (error) {
    return res.status(500).send({
      success: false,
      message: error.message,
    });
  }
};

exports.prepareUploadContext = async (req, res, next) => {
  try {
    const definition = getTemplateDefinition(req.params.key);
    if (!definition) {
      return res.status(404).send({
        success: false,
        message: "Template key is not supported.",
      });
    }

    const site = splitSite.findSiteNumber(req);
    const userName = req.headers["x-user-name"] || "system";
    const templateDoc = await findOrCreateTemplateDoc(definition, site, userName);

    req.templateDefinition = definition;
    req.templateDoc = templateDoc;

    req.query.objectId = templateDoc.id;
    req.query.name = definition.templateName;
    req.query.fileType = "template";
    req.query.model = definition.modelPath;
    req.query.date = Date.now().toString();

    return next();
  } catch (error) {
    return res.status(500).send({
      success: false,
      message: error.message,
    });
  }
};

exports.uploadTemplate = async (req, res) => {
  try {
    const templateDoc = req.templateDoc;
    const definition = req.templateDefinition;
    if (!templateDoc || !definition || !req.file) {
      return res.status(400).send({
        success: false,
        message: "Template upload request is invalid.",
      });
    }

    const userName = req.headers["x-user-name"] || "system";
    const fileUrl = `/files/${definition.modelPath}/${templateDoc.id}/template/${req.file.filename}`;
    const fileRecord = {
      name: req.file.filename,
      originalName: req.file.originalname,
      url: fileUrl,
      uploadedAt: new Date(),
    };

    templateDoc.file = [fileRecord];
    templateDoc.status = "active";
    templateDoc.edit_by = userName;
    templateDoc.edit_date = new Date();
    templateDoc.edit_history = [
      ...(templateDoc.edit_history || []),
      { employee: userName, date: new Date() },
    ];
    await templateDoc.save();

    return res.status(200).send({
      success: true,
      data: {
        key: definition.key,
        templateName: definition.templateName,
        templateType: definition.type,
        templateId: templateDoc.id,
        site: templateDoc.site,
        file: fileRecord,
      },
    });
  } catch (error) {
    return res.status(500).send({
      success: false,
      message: error.message,
    });
  }
};
