import { Request, Response, NextFunction } from "express";
import { productService, ProductFilters } from "./product.service";
import { catchAsyncError } from "../../middlewares/catchAsyncError";
import ErrorHandler from "../../middlewares/error";
import { AuthRequest } from "../../middlewares/auth";
import database from "../../config/db";

export const productController = {
  
  // Delete product
  // deleteProduct: catchAsyncError(
  //   async (req: AuthRequest, res: Response, next: NextFunction) => {
  //     const { id } = req.params;
  //     const userId = req.user?.id;

  //     if (!userId) {
  //       return next(new ErrorHandler("Authentication required", 401));
  //     }

  //     try {
  //       const deletedProduct = await productService.deleteProduct(id, userId);

  //       res.status(200).json({
  //         success: true,
  //         message: "Product deleted successfully",
  //         data: deletedProduct,
  //       });
  //     } catch (error: any) {
  //       return next(
  //         new ErrorHandler(
  //           error.message,
  //           error.message.includes("own") ? 403 : 400,
  //         ),
  //       );
  //     }
  //   },
  // ),


  // Create new product
  createProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Check if logo file is provided
      const logoFile = req.files?.logo;

      const data = {
        ...req.body,
        creator_id: userId,
        creator_type: req.user?.account_type,
      };

      // Validation
      if (!data.name || data.name.trim().length < 3) {
        return next(
          new ErrorHandler("Product name must be at least 3 characters", 400),
        );
      }

      if (!data.description || data.description.trim().length < 10) {
        return next(
          new ErrorHandler("Description must be at least 10 characters", 400),
        );
      }

      try {
        const product = await productService.createProduct(data, logoFile);

        res.status(201).json({
          success: true,
          message: "Product created successfully",
          data: product,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Update product
  updateProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const data = req.body;
      
      // Check if new logo file is provided
      const logoFile = req.files?.logo;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      try {
        const updatedProduct = await productService.updateProduct(
          id,
          data,
          logoFile,
          userId,
        );

        res.status(200).json({
          success: true,
          message: "Product updated successfully",
          data: updatedProduct,
        });
      } catch (error: any) {
        return next(
          new ErrorHandler(
            error.message,
            error.message.includes("own") ? 403 : 400,
          ),
        );
      }
    },
  ),

  // Delete product (soft delete)
  deleteProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      try {
        const deletedProduct = await productService.deleteProduct(id, userId);

        res.status(200).json({
          success: true,
          message: "Product deleted successfully",
          data: deletedProduct,
        });
      } catch (error: any) {
        return next(
          new ErrorHandler(
            error.message,
            error.message.includes("own") ? 403 : 400,
          ),
        );
      }
    },
  ),

  // Permanently delete product (hard delete) - Optional
  permanentlyDeleteProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      // Check if user is admin (you can add admin check)
      const isAdmin = req.user?.role === 'admin'; // Assuming you have role field

      try {
        const deletedProduct = await productService.permanentlyDeleteProduct(
          id, 
          isAdmin ? undefined : userId // Allow admin to delete any product
        );

        res.status(200).json({
          success: true,
          message: "Product permanently deleted successfully",
          data: deletedProduct,
        });
      } catch (error: any) {
        return next(
          new ErrorHandler(
            error.message,
            error.message.includes("own") ? 403 : 400,
          ),
        );
      }
    },
  ),

  // Get product by ID
  getProductById: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const incrementViews = req.query.views !== "false";

      const product = await productService.getProductById(id, incrementViews);

      if (!product) {
        return next(new ErrorHandler("Product not found", 404));
      }

      res.status(200).json({
        success: true,
        data: product,
      });
    },
  ),

  // Get product by slug
  getProductBySlug: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { slug } = req.params;
      const incrementViews = req.query.views !== "false";

      const product = await productService.getProductBySlug(
        slug,
        incrementViews,
      );

      if (!product) {
        return next(new ErrorHandler("Product not found", 404));
      }

      res.status(200).json({
        success: true,
        data: product,
      });
    },
  ),

  // Get all products
  getAllProducts: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const {
        page = 1,
        limit = 20,
        category_id,
        creator_id,
        creator_type,
        status = "active",
        is_featured,
        is_verified,
        is_sponsored,
        min_rating,
        min_upvotes,
        search,
        tags,
        sort_by = "created_at",
        order = "desc",
      } = req.query;

      // Parse tags if provided
      let tagsArray: string[] = [];
      if (tags) {
        tagsArray = typeof tags === "string" ? tags.split(",") : [];
      }

      const filters: ProductFilters = {
        page: parseInt(page as string),
        limit: parseInt(limit as string),
        category_id: category_id as string,
        creator_id: creator_id as string,
        creator_type: creator_type as string,
        status: status as string,
        is_featured: is_featured ? is_featured === "true" : undefined,
        is_verified: is_verified ? is_verified === "true" : undefined,
        is_sponsored: is_sponsored ? is_sponsored === "true" : undefined,
        min_rating: min_rating ? parseFloat(min_rating as string) : undefined,
        min_upvotes: min_upvotes ? parseInt(min_upvotes as string) : undefined,
        search: search as string,
        tags: tagsArray,
        sort_by: sort_by as string,
        order: order as "asc" | "desc",
      };

      const result = await productService.getAllProducts(filters);

      res.status(200).json({
        success: true,
        ...result,
      });
    },
  ),

  // Search products
  searchProducts: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { q, category_id, min_rating, min_upvotes, limit } = req.query;

      if (!q || q.toString().trim().length < 2) {
        return next(
          new ErrorHandler("Search query must be at least 2 characters", 400),
        );
      }

      const filters = {
        category_id: category_id as string,
        min_rating: min_rating ? parseFloat(min_rating as string) : undefined,
        min_upvotes: min_upvotes ? parseInt(min_upvotes as string) : undefined,
        limit: limit ? parseInt(limit as string) : 10,
      };

      const products = await productService.searchProducts(
        q.toString(),
        filters,
      );

      res.status(200).json({
        success: true,
        data: products,
      });
    },
  ),

  // Get trending products
  getTrendingProducts: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const limit = parseInt(req.query.limit as string) || 10;
      const days = parseInt(req.query.days as string) || 7;

      const products = await productService.getTrendingProducts(limit, days);

      res.status(200).json({
        success: true,
        data: products,
      });
    },
  ),

  // Get products by creator
  getProductsByCreator: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { creatorId } = req.params;
      const {
        status = "active",
        is_featured,
        limit = 20,
        page = 1,
      } = req.query;

      const filters = {
        status: status as string,
        is_featured: is_featured ? is_featured === "true" : undefined,
        limit: parseInt(limit as string),
        page: parseInt(page as string),
      };

      const result = await productService.getProductsByCreator(
        creatorId,
        filters,
      );

      res.status(200).json({
        success: true,
        ...result,
      });
    },
  ),

  // Upvote a product
  upvoteProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      try {
        const result = await productService.upvoteProduct(id, userId);

        res.status(200).json({
          success: true,
          message: "Product upvoted successfully",
          data: { upvotes: result.upvotes },
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Follow a product
  followProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;

      if (!userId) {
        return next(new ErrorHandler("Authentication required", 401));
      }

      try {
        const result = await productService.followProduct(id, userId);

        res.status(200).json({
          success: true,
          message: "Product followed successfully",
          data: { followers: result.followers },
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Get product statistics
  getProductStats: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { id } = req.params;

      const stats = await productService.getProductStats(id);

      if (!stats) {
        return next(new ErrorHandler("Product not found", 404));
      }

      res.status(200).json({
        success: true,
        data: stats,
      });
    },
  ),

  // Verify product (admin only)
  verifyProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;

      try {
        const product = await productService.verifyProduct(id);

        res.status(200).json({
          success: true,
          message: "Product verified successfully",
          data: product,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Feature product (admin only)
  featureProduct: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const { featured = true } = req.body;

      try {
        const product = await productService.featureProduct(id, featured);

        res.status(200).json({
          success: true,
          message: `Product ${featured ? "featured" : "unfeatured"} successfully`,
          data: product,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Bulk operations (admin only)
  bulkUpdateProducts: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { updates } = req.body;

      if (!Array.isArray(updates) || updates.length === 0) {
        return next(new ErrorHandler("Updates array is required", 400));
      }

      const results = [];
      for (const update of updates) {
        const { id, status, is_featured, is_verified, category_id } = update;

        if (!id) {
          continue;
        }

        const updateData: any = {};
        if (status) updateData.status = status;
        if (is_featured !== undefined) updateData.is_featured = is_featured;
        if (is_verified !== undefined) updateData.is_verified = is_verified;
        if (category_id) updateData.category_id = category_id;

        if (Object.keys(updateData).length > 0) {
          try {
            const updated = await productService.updateProduct(id, updateData);
            results.push(updated);
          } catch (error) {
            results.push({ id, error: (error as Error).message });
          }
        }
      }

      res.status(200).json({
        success: true,
        message: "Bulk update completed",
        data: results,
      });
    },
  ),

  // Get similar products
  getSimilarProducts: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const limit = parseInt(req.query.limit as string) || 5;

      // First get the product
      const product = await productService.getProductById(id, false);
      if (!product) {
        return next(new ErrorHandler("Product not found", 404));
      }

      // Query similar products by category and tags
      const query = `
      SELECT 
        p.*,
        c.name as category_name,
        (
          SELECT COUNT(*) 
          FROM (
            SELECT UNNEST(p.tags) INTERSECT SELECT UNNEST($1::jsonb)
          ) common_tags
        ) as common_tag_count
      FROM products p
      LEFT JOIN products_categories c ON p.category_id = c.id
      WHERE p.id != $2
        AND p.status = 'active'
        AND (
          p.category_id = $3 OR 
          p.tags && $1::jsonb
        )
      ORDER BY 
        CASE WHEN p.category_id = $3 THEN 1 ELSE 0 END DESC,
        common_tag_count DESC,
        p.rating DESC,
        p.views DESC
      LIMIT $4;
    `;

      const result = await database.query(query, [
        product.tags || [],
        id,
        product.category_id,
        limit,
      ]);

      res.status(200).json({
        success: true,
        data: result.rows,
      });
    },
  ),
};
