const { getBooksByIsbn, searchBooksByTitle, searchBooksByTitleAndDate } = require('../services/amazonService');
const {
  getIsbnCache,
  setIsbnCache,
  getTitleCache,
  setTitleCache,
  getFilterCache,
  setFilterCache
} = require('../services/cacheService');
const { toBoolean, resolveLocales, toInteger } = require('../utils/request');
const { normalizeIsbnForLookup } = require('../utils/isbn');
const env = require('../config/env');

const ensureGeminiAvailability = (includeGemini) => {
  if (includeGemini && !env.geminiApiKey) {
    const error = new Error('Gemini entegrasyonu icin GEMINI_API_KEY tanimlanmali');
    error.status = 400;
    throw error;
  }
};

const buildMeta = (req) => ({
  locales: resolveLocales(req.query.locales),
  includeGemini: toBoolean(req.query.withGemini, false),
  limit: toInteger(req.query.limit, 3)
});

const searchByIsbn = async (req, res, next) => {
  try {
    const requestedIsbn = req.params.isbn;
    const normalizedIsbn = normalizeIsbnForLookup(requestedIsbn);
    const { locales, includeGemini } = buildMeta(req);
    ensureGeminiAvailability(includeGemini);

    const cached = await getIsbnCache(normalizedIsbn, locales, includeGemini);
    if (cached) {
      res.locals.cacheHit = true;
      return res.json({
        ...cached,
        cacheHit: true
      });
    }

    const data = await getBooksByIsbn(normalizedIsbn, locales, includeGemini);
    const responsePayload = {
      isbn: requestedIsbn,
      normalizedIsbn,
      locales,
      includeGemini,
      data,
      cachedAt: new Date().toISOString()
    };
    await setIsbnCache(normalizedIsbn, locales, includeGemini, responsePayload);
    res.locals.cacheHit = false;
    res.json({
      ...responsePayload,
      cacheHit: false
    });
  } catch (error) {
    next(error);
  }
};

const searchByTitle = async (req, res, next) => {
  try {
    const title = req.query.title;
    if (!title) {
      const error = new Error('title parametresi zorunludur');
      error.status = 400;
      throw error;
    }

    const { locales, includeGemini, limit } = buildMeta(req);
    ensureGeminiAvailability(includeGemini);

    const cacheParams = { title, locales, includeGemini, limit };
    const cached = await getTitleCache(cacheParams);
    if (cached) {
      res.locals.cacheHit = true;
      return res.json({ ...cached, cacheHit: true });
    }

    const data = await searchBooksByTitle({ title, locales, includeGemini, limit });
    const responsePayload = {
      title,
      locales,
      limit,
      includeGemini,
      data,
      cachedAt: new Date().toISOString()
    };
    await setTitleCache(cacheParams, responsePayload);
    res.locals.cacheHit = false;

    res.json({
      ...responsePayload,
      cacheHit: false
    });
  } catch (error) {
    next(error);
  }
};

const searchByTitleAndDate = async (req, res, next) => {
  try {
    const { title, published } = req.query;
    if (!title || !published) {
      const error = new Error('title ve published parametreleri zorunludur');
      error.status = 400;
      throw error;
    }

    const { locales, includeGemini, limit } = buildMeta(req);
    ensureGeminiAvailability(includeGemini);

    const cacheParams = { title, published, locales, includeGemini, limit };
    const cached = await getFilterCache(cacheParams);
    if (cached) {
      res.locals.cacheHit = true;
      return res.json({ ...cached, cacheHit: true });
    }

    const data = await searchBooksByTitleAndDate({
      title,
      published,
      locales,
      includeGemini,
      limit
    });

    const responsePayload = {
      title,
      published,
      locales,
      limit,
      includeGemini,
      data,
      cachedAt: new Date().toISOString()
    };
    await setFilterCache(cacheParams, responsePayload);
    res.locals.cacheHit = false;

    res.json({
      ...responsePayload,
      cacheHit: false
    });
  } catch (error) {
    next(error);
  }
};

module.exports = {
  searchByIsbn,
  searchByTitle,
  searchByTitleAndDate
};
