import mongoose from "mongoose";
import { NextResponse } from "next/server";

import Product from "../../../src/models/Product";
import Category from "../../../src/models/Category";
import StaticVideo from "../../../src/models/StaticVideo";
import Review from "../../../src/models/Review";
import Slider from "../../../src/models/Slider";
import Blog from "../../../src/models/Blog";
import Banner from "../../../src/models/Banner";
import ProductSKU from "../../../src/models/ProductSKU";
import ProductColorImage from "../../../src/models/ProductColorImage";
import "@/models/Color";
import "@/models/Size";
import dbConnect from "../../../src/lib/mongodb";
// IMPORTANT
import "../../../src/models/User";

export async function GET(req: Request) {
  try {
    await dbConnect();

    // =========================
    // FEATURED PRODUCTS
    // =========================
    const featuredProductsRaw = await Product.find({
      isFeatured: true,
    })
      .populate("category", "name slug")
      .populate("subcategory", "name slug")
      .limit(10)
      .lean();

    // =========================
    // NEW PRODUCTS
    // =========================
    const newProductsRaw = await Product.find()
      .populate("category", "name slug")
      .populate("subcategory", "name slug")
      .sort({ createdAt: -1 })
      .limit(10)
      .lean();

    // =========================
    // RECEPTION CATEGORY
    // =========================
    const receptionCategory = await Category.findOne({
      slug: "reception",
      // level: 1,
    });

    // =========================
    // RECEPTION PRODUCTS
    // =========================
    const receptionproductsRaw = receptionCategory
      ? await Product.find({
          category: receptionCategory._id,
        })
          .populate("category", "name slug")
          .populate("subcategory", "name slug")
          .limit(10)
          .lean()
      : [];

    // =========================
    // ATTACH VARIANTS
    // =========================
    const products = await attachProductVariants(featuredProductsRaw);

    const newProducts = await attachProductVariants(newProductsRaw);

    const receptionproducts = await attachProductVariants(receptionproductsRaw);

    // =========================
    // EVENTS
    // =========================
    const events = await Category.find({
      isevent: true,
      level: 1,
    }).limit(10);

    // =========================
    // CATEGORIES
    // =========================
    const categories = await Category.find({
      isevent: false,
      level: 1,
    }).limit(10);

    // Footer categories
    const footerCategories = await Category.find({
      level: 1,
    }).sort({ createdAt: -1 }).limit(10);

    // =========================
    // STATIC VIDEO
    // =========================
    const staticVideo = await StaticVideo.findOne();

    // =========================
    // SLIDER
    // =========================
    const slider = await Slider.find({
      status: true,
    })
      .limit(10)
      .lean();

    // =========================
    // BANNERS
    // =========================
    const banners = await Banner.find({
      status: true,
      banner_slug: {
        $in: ["hometop", "homebottom", "homesmall", "homesmall-1"],
      },
    })
      .sort({ createdAt: -1 })
      .limit(10)
      .lean();

    // =========================
    // USER MODEL
    // =========================
    const UserModel = mongoose.models.User;

    if (!UserModel) {
      throw new Error("User model not registered");
    }

    // =========================
    // REVIEWS
    // =========================
    const reviews = await Review.find({
      status: "approved",
    }).limit(10);

    // =========================
    // TRANSFORM REVIEWS
    // =========================
    const transformedReviews = reviews.map((review: any) => {
      const reviewObj = review.toObject ? review.toObject() : { ...review };

      const firstImage =
        reviewObj.images && reviewObj.images.length > 0
          ? reviewObj.images[0]
          : null;

      return {
        ...reviewObj,
        images: firstImage,
      };
    });

    // =========================
    // BLOGS
    // =========================
    const blogs = await Blog.find().sort({ createdAt: -1 }).limit(10).lean();

    // =========================
    // TRANSFORM BLOGS
    // =========================
    const transformedBlogs = blogs.map((blog: any) => {
      const firstImage =
        blog.images && blog.images.length > 0 ? blog.images[0] : null;

      return {
        ...blog,
        images: firstImage,
      };
    });

    // =========================
    // RESPONSE
    // =========================
    return NextResponse.json({
      success: true,
      message: "Home API working",
      title: "Home",

      products,

      newProducts,

      receptionproducts,

      events,

      categories,

      footerCategories,

      slider,

      staticVideo,

      reviews: transformedReviews,

      banners,

      Blogs: transformedBlogs,
    });
  } catch (error) {
    console.error("Error rendering home page:", error);

    return NextResponse.json(
      {
        success: false,
        error: "Internal Server Error",
      },
      { status: 500 },
    );
  }
}

// ======================================================
// ATTACH PRODUCT VARIANTS
// ======================================================

async function attachProductVariants(products: any[]) {
  const productIds = products.map((p: any) => p._id);

  // =========================
  // FETCH PRODUCT SKUS
  // =========================
  const skus = await ProductSKU.find({
    product: { $in: productIds },
  })
    .populate("color", "name hexCode")
    .populate("size", "name sortOrder")
    .lean();

  // =========================
  // FETCH PRODUCT COLOR IMAGES
  // =========================
  const colorImages = await ProductColorImage.find({
    product: { $in: productIds },
  }).lean();

  // =========================
  // COLOR IMAGE MAP
  // =========================
  const colorImageMap = new Map();

  colorImages.forEach((item: any) => {
    const productId = item.product.toString();

    const colorId = item.color.toString();

    const key = `${productId}_${colorId}`;

    colorImageMap.set(
      key,
      item.images
        .sort((a: any, b: any) => (a.sortOrder || 0) - (b.sortOrder || 0))
        .map((img: any) => ({
          url: img.url,
          altText: img.altText || "",
          sortOrder: img.sortOrder || 0,
          isPrimary: img.isPrimary || false,
        })),
    );
  });

  // =========================
  // GROUP SKUS BY PRODUCT
  // =========================
  const skuMap = new Map();

  skus.forEach((sku: any) => {
    const productId = sku.product.toString();

    if (!skuMap.has(productId)) {
      skuMap.set(productId, []);
    }

    skuMap.get(productId).push(sku);
  });

  // =========================
  // TRANSFORM PRODUCTS
  // =========================
  const transformedProducts = products.map((product: any) => {
    const productId = product._id.toString();

    const productSkus = skuMap.get(productId) || [];

    // =========================
    // PRICE RANGE
    // =========================
    const prices = productSkus.map((sku: any) =>
      parseFloat(sku.price?.toString() || "0"),
    );

    const minPrice = prices.length > 0 ? Math.min(...prices) : 0;

    const maxPrice = prices.length > 0 ? Math.max(...prices) : 0;

    // =========================
    // GROUP COLORS
    // =========================
    const colorMap = new Map();

    productSkus.forEach((sku: any) => {
      if (!sku.color) return;

      const colorId = sku.color._id.toString();

      if (!colorMap.has(colorId)) {
        const imageKey = `${productId}_${colorId}`;

        colorMap.set(colorId, {
          _id: sku.color._id,
          name: sku.color.name,

          hexCode: sku.color.hexCode,

          images: colorImageMap.get(imageKey) || [],

          sizes: [],
        });
      }

      const colorData = colorMap.get(colorId);

      if (sku.size) {
        colorData.sizes.push({
          _id: sku.size._id,

          name: sku.size.name,

          sortOrder: sku.size.sortOrder || 0,

          sku_id: sku._id,

          sku: sku.sku,

          sku_quantity: sku.quantity || 0,

          price: parseFloat(sku.price?.toString() || "0"),

          comparePrice: parseFloat(sku.comparePrice?.toString() || "0"),
        });
      }
    });

    // =========================
    // SORT SIZES
    // =========================
    const variants = Array.from(colorMap.values()).map((color: any) => ({
      ...color,

      sizes: color.sizes.sort(
        (a: any, b: any) => (a.sortOrder || 0) - (b.sortOrder || 0),
      ),
    }));

    return {
      ...product,

      minPrice,

      maxPrice,

      variants,

      hasSkus: productSkus.length > 0,
    };
  });

  return transformedProducts;
}
