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

const pagination = (req: Request) => {
  // The catalog currently has 1,072 authors. Allow a complete metadata list for
  // admin/public filters while still putting a hard ceiling on the response.
  const limit = Math.max(1, Math.min(2000, Number(req.query.limit) || 100));
  const page = Math.max(1, Number(req.query.page) || 1);
  return { limit, page, skip: (page - 1) * limit };
};

export const getCategories = async (req: Request, res: Response) => {
  try {
    const { limit, page, skip } = pagination(req);
    const search = String(req.query.search ?? '').trim();
    const where = {
      ...(search ? { name: { contains: search } } : {}),
      ...(req.query.status === 'ALL' ? {} : { isActive: true }),
    };
    const [items, total] = await Promise.all([
      prisma.category.findMany({
        where,
        skip,
        take: limit,
        include: { _count: { select: { books: true } } },
        orderBy: [{ displayOrder: 'asc' }, { name: 'asc' }],
      }),
      prisma.category.count({ where }),
    ]);
    return sendSuccess(res, 'Categories retrieved', {
      categories: items.map((item) => ({ ...item, productCount: item._count.books, _count: undefined })),
      pagination: { total, page, limit, totalPages: Math.max(1, Math.ceil(total / limit)) },
    });
  } catch (error) {
    return sendError(res, 'Failed to retrieve categories', error instanceof Error ? error.message : String(error), 500);
  }
};

export const getAuthors = async (req: Request, res: Response) => {
  try {
    const { limit, page, skip } = pagination(req);
    const search = String(req.query.search ?? '').trim();
    const where = search ? { name: { contains: search } } : {};
    const [items, total] = await Promise.all([
      prisma.author.findMany({
        where,
        skip,
        take: limit,
        include: { _count: { select: { books: true } } },
        orderBy: { name: 'asc' },
      }),
      prisma.author.count({ where }),
    ]);
    return sendSuccess(res, 'Authors retrieved', {
      authors: items.map((item) => ({ ...item, productCount: item._count.books, _count: undefined })),
      pagination: { total, page, limit, totalPages: Math.max(1, Math.ceil(total / limit)) },
    });
  } catch (error) {
    return sendError(res, 'Failed to retrieve authors', error instanceof Error ? error.message : String(error), 500);
  }
};

export const getPublishers = async (req: Request, res: Response) => {
  try {
    const { limit, page, skip } = pagination(req);
    const search = String(req.query.search ?? '').trim();
    const where = search ? { name: { contains: search } } : {};
    const [items, total] = await Promise.all([
      prisma.publisher.findMany({
        where,
        skip,
        take: limit,
        include: { _count: { select: { books: true } } },
        orderBy: { name: 'asc' },
      }),
      prisma.publisher.count({ where }),
    ]);
    return sendSuccess(res, 'Publishers retrieved', {
      publishers: items.map((item) => ({ ...item, productCount: item._count.books, _count: undefined })),
      pagination: { total, page, limit, totalPages: Math.max(1, Math.ceil(total / limit)) },
    });
  } catch (error) {
    return sendError(res, 'Failed to retrieve publishers', error instanceof Error ? error.message : String(error), 500);
  }
};

export const getCatalogues = async (req: Request, res: Response) => {
  try {
    const search = String(req.query.search ?? '').trim();
    const catalogues = await prisma.catalogue.findMany({
      where: {
        ...(search ? { title: { contains: search } } : {}),
        ...(req.query.status === 'ALL' ? {} : { isActive: true }),
      },
      include: {
        categories: { include: { category: true } },
        _count: { select: { books: true } },
      },
      orderBy: { title: 'asc' },
    });
    return sendSuccess(res, 'Catalogues retrieved', {
      catalogues: catalogues.map((catalogue) => ({
        id: catalogue.id,
        sourceCatalogueId: catalogue.sourceCatalogueId,
        title: catalogue.title,
        slug: catalogue.slug,
        pdfUrl: catalogue.pdfUrl,
        sourcePdfUrl: catalogue.sourcePdfUrl,
        assetStatus: catalogue.assetStatus,
        isActive: catalogue.isActive,
        productCount: catalogue._count.books,
        categories: catalogue.categories.map(({ category }) => ({
          id: category.id,
          name: category.name,
          slug: category.slug,
        })),
      })),
    });
  } catch (error) {
    return sendError(res, 'Failed to retrieve catalogues', error instanceof Error ? error.message : String(error), 500);
  }
};

export const getCatalogSummary = async (_req: Request, res: Response) => {
  try {
    const [products, categories, authors, publishers, attributes, catalogues, images] =
      await Promise.all([
        prisma.book.count({ where: { sourceProductId: { not: null } } }),
        prisma.category.count({ where: { sourceCategoryId: { not: null } } }),
        prisma.author.count({ where: { sourceKey: { not: null } } }),
        prisma.publisher.count({ where: { sourceKey: { not: null } } }),
        prisma.bookAttribute.count({ where: { book: { sourceProductId: { not: null } } } }),
        prisma.catalogue.count(),
        prisma.bookImage.count({ where: { book: { sourceProductId: { not: null } } } }),
      ]);
    return sendSuccess(res, 'Catalog summary retrieved', {
      products,
      categories,
      authors,
      publishers,
      attributes,
      catalogues,
      images,
    });
  } catch (error) {
    return sendError(res, 'Failed to retrieve catalog summary', error instanceof Error ? error.message : String(error), 500);
  }
};
