import { Request, Response } from 'express';
import prisma from '../config/database';
import { meiliClient } from '../config/search';
import { sendSuccess, sendError } from '../utils/response.utils';

// 1. Intelligent Search Endpoint (Supports Meilisearch / Database Fallback)
export const searchBooks = async (req: Request, res: Response) => {
  try {
    const {
      query = '',
      category,
      language,
      author,
      publisher,
      minPrice,
      maxPrice,
      minRating,
      sortBy = 'relevance',
      limit = 20,
      page = 1,
    } = req.query;

    const take = Math.max(1, Math.min(100, Number(limit) || 20));
    const currentPage = Math.max(1, Number(page) || 1);
    const skip = (currentPage - 1) * take;

    // Try Meilisearch index query if query text is provided
    try {
      if (query && meiliClient) {
        const index = meiliClient.index('books');
        const searchRes = await index.search(String(query), {
          limit: take,
          offset: skip,
          filter: [
            language ? `language = "${language}"` : null,
            minPrice ? `price >= ${minPrice}` : null,
            maxPrice ? `price <= ${maxPrice}` : null,
          ].filter(Boolean) as string[],
        });

        if (searchRes.hits && searchRes.hits.length > 0) {
          return sendSuccess(res, 'Search results from Meilisearch', {
            hits: searchRes.hits,
            totalHits: searchRes.estimatedTotalHits,
            source: 'MEILISEARCH',
          });
        }
      }
    } catch (searchErr) {
      // Fallback seamlessly to MySQL fulltext search
    }

    // MySQL Database Fallback Query
    const where: any = { isActive: true };

    if (query) {
      const qStr = String(query).trim();
      where.OR = [
        { title: { contains: qStr } },
        { isbn: { contains: qStr } },
        { barcode: { contains: qStr } },
        { description: { contains: qStr } },
        { publisher: { name: { contains: qStr } } },
        { bookAuthors: { some: { author: { name: { contains: qStr } } } } },
        { bookCategories: { some: { category: { name: { contains: qStr } } } } },
      ];
    }

    if (language) where.language = String(language);
    if (category) {
      const value = String(category);
      where.bookCategories = { some: { category: { OR: [{ id: value }, { slug: value }, { name: value }] } } };
    }
    if (author) {
      const value = String(author);
      where.bookAuthors = { some: { author: { OR: [{ id: value }, { slug: value }, { name: value }] } } };
    }
    if (publisher) {
      const value = String(publisher);
      where.publisher = { OR: [{ id: value }, { slug: value }, { name: value }] };
    }
    if (minPrice || maxPrice) {
      where.price = {};
      if (minPrice) where.price.gte = Number(minPrice);
      if (maxPrice) where.price.lte = Number(maxPrice);
    }
    if (minRating) where.ratingAverage = { gte: Number(minRating) };

    let orderBy: any = { createdAt: 'desc' };
    if (sortBy === 'price_asc') orderBy = { price: 'asc' };
    if (sortBy === 'price_desc') orderBy = { price: 'desc' };
    if (sortBy === 'rating') orderBy = { ratingAverage: 'desc' };

    const [books, total] = await Promise.all([
      prisma.book.findMany({
        where,
        take,
        skip,
        include: {
          publisher: true,
          bookAuthors: { include: { author: true } },
          bookCategories: { include: { category: true } },
        },
        orderBy,
      }),
      prisma.book.count({ where }),
    ]);

    const formattedResults = books.map((b) => ({
      id: b.id,
      title: b.title,
      slug: b.slug,
      isbn: b.isbn,
      price: Number(b.price),
      discountPrice: b.discountPrice ? Number(b.discountPrice) : null,
      coverImage: b.coverImage,
      ratingAverage: Number(b.ratingAverage),
      authorName: b.bookAuthors[0]?.author.name || 'Indian Author',
      publisherName: b.publisher?.name || 'IBW Press',
      categoryName: b.bookCategories[0]?.category.name || 'General',
    }));

    return sendSuccess(res, 'Search results retrieved', {
      books: formattedResults,
      pagination: {
        total,
        page: currentPage,
        limit: take,
        totalPages: Math.ceil(total / take),
      },
      source: 'MYSQL_DATABASE',
    });
  } catch (error: any) {
    return sendError(res, 'Search query failed', error.message, 500);
  }
};

// 2. Fast Autocomplete Suggestions Endpoint
export const getAutocompleteSuggestions = async (req: Request, res: Response) => {
  try {
    const { q = '' } = req.query;
    const queryStr = String(q).trim();

    if (!queryStr) {
      return sendSuccess(res, 'Empty search query', { suggestions: [] });
    }

    const books = await prisma.book.findMany({
      where: {
        isActive: true,
        OR: [
          { title: { contains: queryStr } },
          { isbn: { contains: queryStr } },
          { bookAuthors: { some: { author: { name: { contains: queryStr } } } } },
        ],
      },
      take: 6,
      select: {
        id: true,
        title: true,
        slug: true,
        coverImage: true,
        price: true,
        discountPrice: true,
        bookAuthors: { select: { author: { select: { name: true } } } },
      },
    });

    const suggestions = books.map((b) => ({
      id: b.id,
      title: b.title,
      slug: b.slug,
      coverImage: b.coverImage,
      price: Number(b.discountPrice || b.price),
      authorName: b.bookAuthors[0]?.author.name || 'Indian Author',
    }));

    return sendSuccess(res, 'Autocomplete suggestions fetched', { suggestions });
  } catch (error: any) {
    return sendError(res, 'Autocomplete failed', error.message, 500);
  }
};

// 3. Trending & Popular Search Keywords Endpoint
export const getTrendingSearches = async (req: Request, res: Response) => {
  try {
    const trending = [
      { keyword: 'The Mahabharata Unabridged', count: '12.4k searches' },
      { keyword: 'Rabindranath Tagore Gitanjali', count: '9.8k searches' },
      { keyword: 'Srimad Bhagavad Gita Sanskrit', count: '8.2k searches' },
      { keyword: 'R.K. Narayan Malgudi Days', count: '6.5k searches' },
      { keyword: 'Amish Tripathi Shiva Trilogy', count: '5.1k searches' },
      { keyword: 'Discovery of India Jawaharlal Nehru', count: '4.8k searches' },
    ];

    return sendSuccess(res, 'Trending searches retrieved', { trending });
  } catch (error: any) {
    return sendError(res, 'Failed to fetch trending searches', error.message, 500);
  }
};
