const fetch = require("node-fetch");
const fs = require("fs");
const path = require("path");
const {
  Companies,
  SDS,
  UserProjects,
  Users,
  Subscriptions,
  Projects,
} = require("../models");
const { addFormattedIds, addFormattedId } = require("../utils/idFormatter");
const { createSDSNotification } = require("../utils/notificationHelper");

const PROXY_BASE_URL = "https://nordsafe-sds-proxy.vercel.app/api";

const getSDS = async (req, res) => {
  const { projectId } = req.query;

  if (!projectId)
    return res.status(400).json({ message: "Project id is required" });

  try {
    const sds = await SDS.findAll({
      where: {
        ProjectId: projectId,
      },
    });

    // Add formatted IDs
    res.json(addFormattedIds("sds", sds));
  } catch (err) {
    res.status(500).json({ message: "Failed to fetch" });
  }
};

const getPublicSDS = async (req, res) => {
  const { projectId } = req.query;

  if (!projectId)
    return res.status(400).json({ message: "Project id is required" });

  try {
    const projectInfo = await Projects.findByPk(projectId, {
      include: [
        {
          model: Companies,
        },
      ],
    });
    if (!projectInfo) return res.status(404).json({ message: "Project not found" });

    const sds = await SDS.findAll({
      where: {
        ProjectId: projectId,
      },
    });

    res.json({
      projectInfo,
      // Add formatted IDs
      sds: addFormattedIds("sds", sds),
    });
  } catch (err) {
    res.status(500).json({ message: "Failed to fetch" });
  }
};

const searchSDS = async (req, res) => {
  const { product_name, page, pageSize, language } = req.body;
  if (!product_name)
    return res.status(400).json({ message: "Product name is required" });

  const requestData = {
    language,
    limit_val: pageSize,
    offset_val: page,
    product_name,
    issue_date: "",
    country: "",
    cas_no: "",
    mfg_name: "",
    msds_id: "",
    product_code: "",
    sortfield: "issue_date",
    sortdir: "desc",
  };

  try {
    const company = await Companies.findByPk(req.user.companyId);
    if (!company)
      return res.status(404).json({ message: "Something went wrong" });

    const subscription = await Subscriptions.findOne({
      where: {
        companyId: req.user.companyId,
      },
    });
    if (!subscription)
      return res.status(404).json({ message: "Something went wrong" });

    const subMonthlySDSSearchCount = subscription.monthlySDSSearchCount;
    if (subscription.monthlySDSSearchUsage >= subMonthlySDSSearchCount)
      return res.status(400).json({
        message: `You can only have ${subMonthlySDSSearchCount} SDS searches in this month`,
      });

    await Subscriptions.update(
      {
        monthlySDSSearchUsage: subscription.monthlySDSSearchUsage * 1 + 1,
      },
      {
        where: {
          id: subscription.id,
        },
      },
    );

    const response = await fetch(PROXY_BASE_URL + "/search", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(requestData),
    });

    const data = await response.json().catch(() => null);
    if (!response.ok) {
      const err = new Error("SDS search failed");
      err.response = { data };
      throw err;
    }

    res.status(200).json(data);
  } catch (error) {
    console.log(error);

    res.status(500).json({
      message: "Field to fetch",
      error: error.response?.data || error.message || "Server error",
    });
  }
};

const saveSDS = async (req, res) => {
  const {
    doc_id,
    product_name,
    product_code,
    mfg_detail,
    issue_date,
    country,
    lang,
  } = req.body;
  const { projectId } = req.query;
  if (!doc_id)
    return res.status(400).json({ message: "Document id is required" });
  if (!projectId)
    return res.status(400).json({ message: "Project id is required" });

  try {
    const company = await Companies.findByPk(req.user.companyId);
    if (!company)
      return res.status(404).json({ message: "Something went wrong" });

    const subscription = await Subscriptions.findOne({
      where: {
        CompanyId: company.id,
      },
      order: [["createdAt", "DESC"]],
    });

    if (!subscription)
      return res.status(404).json({ message: "Something went wrong" });

    const subMonthlySDSSaveCount = subscription.monthlySDSSaveCount;
    if (subscription.monthlySDSSaveUsage >= subMonthlySDSSaveCount)
      return res.status(400).json({
        message: `You can only save ${subMonthlySDSSaveCount} SDS files in this month`,
      });

    await Subscriptions.update(
      {
        monthlySDSSaveUsage: subscription.monthlySDSSaveUsage * 1 + 1,
      },
      {
        where: {
          id: subscription.id,
        },
      },
    );

    const allSameSDS = await SDS.findAll({
      where: {
        product_name,
        product_code,
        mfg_detail: JSON.stringify(mfg_detail),
        issue_date,
        country,
        lang,
      },
    });

    const existsSDS = allSameSDS ? allSameSDS[0] : null;

    let fileName = `${Date.now()}.pdf`;

    if (!existsSDS) {
      const response = await fetch(PROXY_BASE_URL + "/get", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ doc_id }),
      });
      const rawText = await response.text();
      if (!response.ok) {
        let errData = rawText;
        try {
          errData = JSON.parse(rawText);
        } catch {
          /* keep text */
        }
        const err = new Error("SDS get failed");
        err.response = { data: errData };
        throw err;
      }
      let base64Data = rawText;
      try {
        const parsed = JSON.parse(rawText);
        base64Data = typeof parsed === "string" ? parsed : rawText;
      } catch {
        /* plain base64 body */
      }
      const buffer = Buffer.from(base64Data, "base64");
      const filePath = path.join(__dirname, "../sds-files", fileName);
      fs.writeFileSync(filePath, buffer);
    } else {
      if (allSameSDS.some((sds) => sds.CompanyId == req.user.companyId)) {
        return res.status(200).json(existsSDS);
      }
      fileName = existsSDS.fileName;
    }

    await SDS.create({
      product_name,
      product_code,
      mfg_detail: JSON.stringify(mfg_detail),
      issue_date,
      country,
      lang,
      fileName,
      ProjectId: projectId,
    });

    // Get the created SDS with formatted ID
    const createdSDS = await SDS.findOne({
      where: {
        product_name,
        product_code,
        ProjectId: projectId,
      },
      order: [["id", "DESC"]],
    });

    if (createdSDS) {
      const formattedSDS = addFormattedId("sds", { id: createdSDS.id });

      // Get all users in this project to notify them
      try {
        const projectUsers = await UserProjects.findAll({
          where: { ProjectId: projectId },
          include: [{ model: Users, attributes: ["id", "fullname", "email"] }],
        });

        // Create notifications for all project users
        for (const userProject of projectUsers) {
          if (userProject.User && userProject.User.id !== req.user.id) {
            await createSDSNotification({
              userId: userProject.User.id,
              assignedBy: req.user.id,
              companyId: req.user.companyId,
              projectId: projectId,
              sdsId: createdSDS.id,
              productName: product_name,
              formattedId: formattedSDS.formattedId,
            });
          }
        }
      } catch (notifError) {
        console.error("Failed to create SDS notifications:", notifError);
        // Don't fail the SDS save if notification fails
      }
    }

    res.status(200).json({ message: "SDS saved successfully" });
  } catch (error) {
    console.log(error.message);

    res.status(500).json({
      message: "Field to fetch",
      error: error.response?.data || error.message || "Server error",
    });
  }
};

module.exports = { searchSDS, getSDS, saveSDS, getPublicSDS };
