const axios = require('axios');
const cheerio = require('cheerio');
const AmazonBookSearch = require('szbk-amazon-book-search');
const amazonConfig = require('szbk-amazon-book-search/config');
const { extractBookDetails } = require('szbk-amazon-book-search/lib/module');
const env = require('../config/env');
const logger = require('../utils/logger');
const { cacheThumbnail } = require('../utils/mediaCache');

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const buildHeaders = () => ({ ...amazonConfig.headers });

const buildSearchUrl = (locale, query) => {
  const base = locale === 'tr' ? amazonConfig.tr_base_url : amazonConfig.en_base_url;
  return encodeURI(`${base}${query}`);
};

const buildDetailUrl = (locale, asin) => {
  const base = locale === 'tr' ? amazonConfig.tr_detail_url : amazonConfig.en_detail_url;
  return encodeURI(`${base}${asin}`);
};

const createAmazonClient = (locale) => new AmazonBookSearch(locale);

const getGeminiKey = (includeGemini) => (includeGemini ? env.geminiApiKey : undefined);

const fetchPage = async (url) => {
  const response = await axios.get(url, { headers: buildHeaders() });
  if (!response.data) {
    throw new Error('Amazon sayfasina erisilemedi');
  }
  return response.data;
};

const parseSearchResults = (html, limit) => {
  const $ = cheerio.load(html);
  const items = [];

  $('[data-component-type="s-search-result"]').each((_, element) => {
    const asin = $(element).attr('data-asin');
    if (!asin) return;

    const title = $(element).find('h2 a span').first().text().trim();
    const price = $(element).find('[data-a-color="base"] .a-offscreen').first().text().trim();
    const image = $(element).find('img.s-image').attr('src');
    const author = $(element).find('.a-color-secondary .a-size-base+ .a-size-base').first().text().trim();

    items.push({ asin, title, price, image, author });
  });

  return items.slice(0, limit);
};

const fetchDetailsByAsin = async (asin, locale, includeGemini) => {
  await delay(amazonConfig.fetchTimeout);
  const detailHtml = await fetchPage(buildDetailUrl(locale, asin));
  const fallbackIsbn = '0000000000';
  const details = await extractBookDetails(
    detailHtml,
    fallbackIsbn,
    getGeminiKey(includeGemini),
    locale
  );
  const cachedThumbnail = await cacheThumbnail({
    isbn: details.isbn || fallbackIsbn,
    locale,
    url: details.thumbImage
  });
  return { asin, locale, cachedThumbnail, ...details };
};

const fetchBooksForLocale = async ({ query, locale, limit, includeGemini }) => {
  const searchHtml = await fetchPage(buildSearchUrl(locale, query));
  const asins = parseSearchResults(searchHtml, limit);

  const detailedResults = [];
  for (const asinInfo of asins) {
    try {
      const detailed = await fetchDetailsByAsin(asinInfo.asin, locale, includeGemini);
      detailedResults.push({ ...detailed, summary: asinInfo });
    } catch (error) {
      logger.warn(`[amazon:${locale}] ${asinInfo.asin} detayi cekilemedi: ${error.message}`);
    }
  }

  return detailedResults;
};

const getBooksByIsbn = async (isbn, locales, includeGemini) => {
  const results = {};
  const tasks = locales.map(async (locale) => {
    const client = createAmazonClient(locale);
    try {
      const data = await client.getBookDetails(isbn, getGeminiKey(includeGemini));
      data.cachedThumbnail = await cacheThumbnail({ isbn, locale, url: data.thumbImage });
      results[locale] = data;
    } catch (error) {
      results[locale] = { error: error.message };
    }
  });

  await Promise.all(tasks);
  return results;
};

const searchBooksByTitle = async ({ title, locales, includeGemini, limit }) => {
  const tasks = locales.map(async (locale) => {
    try {
      const list = await fetchBooksForLocale({
        query: title,
        locale,
        limit,
        includeGemini
      });
      return { locale, items: list };
    } catch (error) {
      return { locale, items: [], error: error.message };
    }
  });

  return Promise.all(tasks);
};

const filterBooksByPublished = (books, publishedText) => {
  if (!publishedText) return books;
  const normalized = publishedText.toLowerCase();
  return books.filter((book) => book.date && book.date.toLowerCase().includes(normalized));
};

const searchBooksByTitleAndDate = async ({ title, published, locales, includeGemini, limit }) => {
  const localeResults = await searchBooksByTitle({ title, locales, includeGemini, limit });
  return localeResults.map((result) => ({
    ...result,
    items: filterBooksByPublished(result.items, published)
  }));
};

module.exports = {
  getBooksByIsbn,
  searchBooksByTitle,
  searchBooksByTitleAndDate
};
