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

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

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

      const data: FaqCreateData = {
        ...req.body,
        author_id: userId,
      };

      // Check if user has permission to create FAQ for this product
      const productId = data.product_id;
      if (productId) {
        const productCheck = await database.query(
          `SELECT creator_id FROM products WHERE id = $1`,
          [productId],
        );

        if (productCheck.rows.length === 0) {
          return next(new ErrorHandler("Product not found", 404));
        }

        const isProductOwner = productCheck.rows[0].creator_id === userId;
        const isAdmin = req.user?.roles?.some((role: any) =>
          ["admin", "super_admin"].includes(role.name),
        );

        if (!isProductOwner && !isAdmin) {
          return next(
            new ErrorHandler(
              "You can only create FAQs for your own products",
              403,
            ),
          );
        }
      }

      try {
        const faq = await productFaqService.createFaq(data);

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

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

      const faq = await productFaqService.getFaqById(id, incrementViews);

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

      // Check if FAQ requires login and user is not authenticated
      if (faq.requires_login) {
        const userId = (req as AuthRequest).user?.id;
        if (!userId) {
          return next(new ErrorHandler("This FAQ requires login to view", 401));
        }
      }

      // Check if FAQ is published or user has access
      if (faq.status !== "published") {
        const userId = (req as AuthRequest).user?.id;
        if (
          !userId ||
          (userId !== faq.author_id &&
            !(req as AuthRequest).user?.roles?.some((r: any) =>
              ["admin", "super_admin"].includes(r.name),
            ))
        ) {
          return next(new ErrorHandler("FAQ is not publicly available", 403));
        }
      }

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

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

      const faq = await productFaqService.getFaqBySlug(slug, incrementViews);

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

      if (faq.requires_login) {
        const userId = (req as AuthRequest).user?.id;
        if (!userId) {
          return next(new ErrorHandler("This FAQ requires login to view", 401));
        }
      }

      if (faq.status !== "published") {
        const userId = (req as AuthRequest).user?.id;
        if (
          !userId ||
          (userId !== faq.author_id &&
            !(req as AuthRequest).user?.roles?.some((r: any) =>
              ["admin", "super_admin"].includes(r.name),
            ))
        ) {
          return next(new ErrorHandler("FAQ is not publicly available", 403));
        }
      }

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

  // Get all FAQs
  getAllFaqs: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const {
        page = 1,
        limit = 20,
        product_id,
        category,
        subcategory,
        status = "published",
        is_featured,
        is_pinned,
        complexity,
        requires_login,
        search,
        tags,
        author_id,
        sort_by = "faq_order",
        order = "asc",
      } = req.query;

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

      const filters: FaqFilters = {
        page: parseInt(page as string),
        limit: parseInt(limit as string),
        product_id: product_id as string,
        category: category as string,
        subcategory: subcategory as string,
        status: status as string,
        is_featured: is_featured ? is_featured === "true" : undefined,
        is_pinned: is_pinned ? is_pinned === "true" : undefined,
        complexity: complexity as string,
        requires_login: requires_login ? requires_login === "true" : undefined,
        search: search as string,
        tags: tagsArray,
        author_id: author_id as string,
        sort_by: sort_by as string,
        order: order as "asc" | "desc",
      };

      const result = await productFaqService.getAllFaqs(filters);

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

  // Get FAQs by product
  getProductFaqs: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const {
        page = 1,
        limit = 20,
        category,
        subcategory,
        status = "published",
        is_featured,
        is_pinned,
        complexity,
        search,
        sort_by = "faq_order",
        order = "asc",
      } = req.query;

      const filters: FaqFilters = {
        page: parseInt(page as string),
        limit: parseInt(limit as string),
        product_id: productId,
        category: category as string,
        subcategory: subcategory as string,
        status: status as string,
        is_featured: is_featured ? is_featured === "true" : undefined,
        is_pinned: is_pinned ? is_pinned === "true" : undefined,
        complexity: complexity as string,
        search: search as string,
        sort_by: sort_by as string,
        order: order as "asc" | "desc",
      };

      const result = await productFaqService.getProductFaqs(productId, filters);

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

  // Get FAQ categories for a product
  getProductFaqCategories: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;

      const categories =
        await productFaqService.getProductFaqCategories(productId);

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

  // Update FAQ
  updateFaq: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const data = req.body;

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

      try {
        const updatedFaq = await productFaqService.updateFaq(id, data, userId);

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

  // Delete FAQ
  deleteFaq: 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 deletedFaq = await productFaqService.deleteFaq(id, userId);

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

  // Mark FAQ as helpful
  markFaqHelpful: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { id } = req.params;
      const userId = req.user?.id;
      const { helpful = true } = req.body;

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

      try {
        const result = await productFaqService.markFaqHelpful(
          id,
          userId,
          helpful,
        );

        res.status(200).json({
          success: true,
          message: `FAQ marked as ${helpful ? "helpful" : "not helpful"}`,
          data: {
            [result.type]: result.count,
          },
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Increment FAQ click count
  incrementFaqClick: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { id } = req.params;

      try {
        await productFaqService.incrementClickCount(id);

        res.status(200).json({
          success: true,
          message: "Click count incremented",
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

  // Get FAQ statistics
  getFaqStats: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;

      const stats = await productFaqService.getFaqStats(productId);

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

  // Get popular FAQs
  getPopularFaqs: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const limit = parseInt(req.query.limit as string) || 10;

      const popularFaqs = await productFaqService.getPopularFaqs(
        productId,
        limit,
      );

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

  // Search FAQs
  searchFaqs: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { q } = req.query;
      const { product_id, category, limit = 20 } = req.query;

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

      const filters = {
        product_id: product_id as string,
        category: category as string,
        limit: parseInt(limit as string),
      };

      const results = await productFaqService.searchFaqs(q.toString(), filters);

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

  // Reorder FAQs
  reorderFaqs: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const { productId } = req.params;
      const userId = req.user?.id;
      const { faq_ids } = req.body;

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

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

      // Check if user owns the product
      const productCheck = await database.query(
        `SELECT creator_id FROM products WHERE id = $1`,
        [productId],
      );

      if (productCheck.rows.length === 0) {
        return next(new ErrorHandler("Product not found", 404));
      }

      const isProductOwner = productCheck.rows[0].creator_id === userId;
      const isAdmin = req.user?.roles?.some((role: any) =>
        ["admin", "super_admin"].includes(role.name),
      );

      if (!isProductOwner && !isAdmin) {
        return next(
          new ErrorHandler(
            "You can only reorder FAQs for your own products",
            403,
          ),
        );
      }

      try {
        const reorderedFaqs = await productFaqService.reorderFaqs(
          productId,
          faq_ids,
        );

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

  // Bulk update FAQs
  bulkUpdateFaqs: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;
      const { faq_ids, status, category, subcategory, is_featured, is_pinned } =
        req.body;

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

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

      if (faq_ids.length > 100) {
        return next(
          new ErrorHandler("Cannot update more than 100 FAQs at once", 400),
        );
      }

      const updateData: any = {};
      if (status) updateData.status = status;
      if (category) updateData.category = category;
      if (subcategory) updateData.subcategory = subcategory;
      if (is_featured !== undefined) updateData.is_featured = is_featured;
      if (is_pinned !== undefined) updateData.is_pinned = is_pinned;

      try {
        const updatedFaqs = await productFaqService.bulkUpdateFaqs(
          faq_ids,
          updateData,
        );

        res.status(200).json({
          success: true,
          message: `${updatedFaqs.length} FAQs updated successfully`,
          data: updatedFaqs,
        });
      } catch (error: any) {
        return next(new ErrorHandler(error.message, 400));
      }
    },
  ),

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

      const relatedFaqs = await productFaqService.getRelatedFaqs(id, limit);

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

  // Get FAQs by category
  getFaqsByCategory: catchAsyncError(
    async (req: Request, res: Response, next: NextFunction) => {
      const { productId, category } = req.params;
      const { subcategory } = req.query;

      const faqs = await productFaqService.getFaqsByCategory(
        productId,
        category,
        subcategory as string,
      );

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

  // Get user's FAQs
  getUserFaqs: catchAsyncError(
    async (req: AuthRequest, res: Response, next: NextFunction) => {
      const userId = req.user?.id;
      const { page = 1, limit = 20, product_id, status = "draft" } = req.query;

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

      const filters: FaqFilters = {
        page: parseInt(page as string),
        limit: parseInt(limit as string),
        author_id: userId,
        product_id: product_id as string,
        status: status as string,
      };

      const result = await productFaqService.getAllFaqs(filters);

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