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 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(4)
      .lean();

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

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

    // =========================
    // RECEPTION PRODUCTS
    // =========================
    const receptionproductsRaw = receptionCategory
      ? await Product.find({
          category: receptionCategory._id,
        })
          .populate('category', 'name slug')
          .populate('subcategory', 'name slug')
          .limit(4)
          .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,
    }).limit(4);

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

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

    // =========================
    // SLIDER
    // =========================
    const slider = await Slider.find({
      isActive: true,
    })
      .sort({ createdAt: -1 })
      .limit(4)
      .lean();

    // =========================
    // BANNERS
    // =========================
    const banners = await Banner.find({
      status: true,
      banner_slug: {
        $in: [
          'hometop',
          'homebottom',
          'homesmall',
          'homesmall-1',
        ],
      },
    })
      .sort({ createdAt: -1 })
      .limit(4)
      .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',
    })
      .populate({
        path: 'customer',
        model: UserModel,
        select:
          'name email avatar',
      })
      .limit(4);

    // =========================
    // 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(4)
      .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,

      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;
}