import { Inventory } from "../Inventory/InventoryModel.js";
import User from "../user/userModel.js";
import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js";
import TerritoryManager from "../TerritoryManagers/TerritoryManagerModel.js";
import SalesCoordinator from "../SalesCoOrdinators/SalesCoOrdinatorModel.js";
import RetailDistributor from "../RetailDistributor/RetailDistributorModel.js";
import { RDStock } from "../Stock/RdStockModel.js";
// Add inventory data
export const addInventory = async (req, res) => {
  try {
    const { products, addedFor, addedForId } = req.body;
    const userId = req.user._id;
    const userType = req.userType;

    if (addedFor === "RetailDistributor") {
      // Find the RetailDistributor stock
      const rdStock = await RDStock.findOne({ userId: addedForId });
      if (!rdStock) {
        return res
          .status(400)
          .json({ error: "Stock not available for the RetailDistributor" });
      }

      // Array to hold product names that have issues
      let invalidProducts = [];

      // Loop through products in the request and check stock availability
      for (const product of products) {
        const { productid, Sale, ProductName } = product;

        // Find product in the RetailDistributor's stock
        const rdProduct = rdStock.products.find(
          (p) => p.productid.toString() === productid.toString()
        );

        if (rdProduct) {
          // Check if sales quantity is less than or equal to the stock
          if (Sale <= rdProduct.Stock) {
            // Decrease the stock by sales amount
            rdProduct.Stock -= Sale;
          } else {
            // If sales > stock, add to invalid products list
            invalidProducts.push(ProductName);
          }
        } else {
          // Product not found in stock, add to invalid products list
          invalidProducts.push(ProductName);
        }
      }

      // If there are any invalid products, return error message
      if (invalidProducts.length > 0) {
        return res.status(400).json({
          success: false,
          message: `Insufficient stock or product not found for: ${invalidProducts.join(
            ", "
          )}`,
        });
      }

      // Save updated stock if all products are valid
      await rdStock.save();
    }

    // Create and save new inventory record
    const newInventory = new Inventory({
      userId,
      userType,
      addedFor,
      addedForId,
      products,
    });

    await newInventory.save();
    res.status(201).json({
      success: true,
      message: "Inventory added successfully",
      data: newInventory,
    });
  } catch (error) {
    res.status(500).json({ success: false, message: "Server error", error });
  }
};

// Get all distributors (PD or RD)
export const getDistributors = async (req, res) => {
  try {
    const { type } = req.params;

    if (!["PrincipalDistributor", "RetailDistributor"].includes(type)) {
      return res.status(400).json({ message: "Invalid distributor type" });
    }
    let filter = { role: "principal-Distributor" };
    let query = {};
    // Check the user type and adjust the filter accordingly
    if (req.userType === "SalesCoOrdinator") {
      // If userType is "SalesCoOrdinator", filter by req.user.mappedBy
      filter.mappedby = req.user.mappedby;
      query.mappedSC = req.user._id;
    } else {
      // Otherwise, filter by req.user._id
      filter.mappedby = req.user._id;
      query.mappedTM = req.user._id;
    }
    let distributors;
    // console.log("type",type);
    if (type === "PrincipalDistributor") {
      // Fetch all PrincipalDistributors
      const principalDistributors = await User.find(filter).sort({
        createdAt: -1,
      });
      // console.log("principalDistributors",principalDistributors);
      // Map each PrincipalDistributor to include their ShippingAddress
      distributors = await Promise.all(
        principalDistributors.map(async (distributor) => {
          const shippingAddress = await ShippingAddress.findOne({
            user: distributor._id,
          });
          return {
            ...distributor.toObject(),
            shippingAddress,
          };
        })
      );
    } else {
      // For RetailDistributor
      distributors = await RetailDistributor.find(query)
        .populate("kyc")
        .sort({ createdAt: -1 });
    }

    res.status(200).json(distributors);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const getAllInventories = async (req, res) => {
  try {
    const { page = 1, show = 10, startDate, endDate, name } = req.query;
    const query = {};

    if (startDate && endDate) {
      const start = new Date(startDate);
      const end = new Date(endDate);

      if (start.toDateString() === end.toDateString()) {
        query.createdAt = {
          $gte: start,
          $lt: new Date(start).setDate(start.getDate() + 1),
        };
      } else {
        query.createdAt = {
          $gte: start,
          $lte: new Date(end).setDate(end.getDate() + 1),
        };
      }
    } else if (startDate && endDate === "") {
      query.createdAt = {
        $gte: new Date(startDate),
        $lte: new Date(),
      };
    } else if (endDate && startDate === "") {
      query.createdAt = {
        $lte: new Date(endDate),
      };
    }

    const allInventories = await Inventory.find(query).sort({ createdAt: -1 });

    // Populate additional details
    const populatedInventories = await Promise.all(
      allInventories.map(async (inventory) => {
        let user = null;
        if (inventory.userType === "TerritoryManager") {
          user = await TerritoryManager.findById(inventory.userId);
        } else if (inventory.userType === "SalesCoordinator") {
          user = await SalesCoordinator.findById(inventory.userId);
        }

        let addedForData = null;
        let tradeName = null;

        if (inventory.addedFor === "PrincipalDistributor") {
          addedForData = await User.findById(inventory.addedForId);
          if (addedForData) {
            const shippingAddress = await ShippingAddress.findOne({
              user: addedForData._id,
            });
            addedForData = {
              ...addedForData.toObject(),
              shippingAddress,
            };
            tradeName =
              addedForData.shippingAddress?.tradeName?.toLowerCase() || "";
          }
        } else if (inventory.addedFor === "RetailDistributor") {
          addedForData = await RetailDistributor.findById(inventory.addedForId).populate("kyc");
          tradeName = addedForData?.kyc?.trade_name?.toLowerCase() || "";
        }

        return {
          ...inventory.toObject(),
          user,
          addedForData,
          tradeName,
        };
      })
    );

    // Apply name filter if the name parameter is provided
    let filteredInventories = populatedInventories;
    if (name) {
      filteredInventories = filteredInventories.filter(
        (inventory) =>
          inventory.tradeName &&
          inventory.tradeName.includes(name.toLowerCase())
      );
    }

    // Calculate total count of filtered data
    const total_data = filteredInventories.length;

    // Apply pagination after filtering
    const paginatedInventories = filteredInventories.slice(
      (page - 1) * show,
      page * show
    );

    // Calculate total pages
    const total_pages = Math.ceil(total_data / show);

    // Send response with pagination info
    res.status(200).json({
      total_data,
      total_pages,
      current_page: Number(page),
      inventories: paginatedInventories,
    });
  } catch (error) {
    console.error("Error in getAllInventories:", error);
    res.status(500).json({ message: error.message });
  }
};

// Get single inventory
export const getSingleInventory = async (req, res) => {
  try {
    const { id } = req.params;

    const inventory = await Inventory.findById(id);
    if (!inventory) {
      return res.status(404).json({ message: "Inventory not found" });
    }

    // Populate user details based on userType
    let user = null;
    if (inventory.userType === "TerritoryManager") {
      user = await TerritoryManager.findById(inventory.userId);
    } else if (inventory.userType === "SalesCoOrdinator") {
      user = await SalesCoordinator.findById(inventory.userId);
    }

    // Populate addedFor details based on addedFor
    let addedForData = null;
    if (inventory.addedFor === "PrincipalDistributor") {
      addedForData = await User.findById(inventory.addedForId);
      const shippingAddress = await ShippingAddress.findOne({
        user: addedForData._id,
      });
      addedForData = {
        ...addedForData.toObject(),
        shippingAddress,
      };
    } else if (inventory.addedFor === "RetailDistributor") {
      addedForData = await RetailDistributor.findById(inventory.addedForId).populate("kyc");
    }

    res.status(200).json({
      ...inventory.toObject(),
      user,
      addedForData,
    });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};
