const axios = require('axios');
const cheerio = require('cheerio');

function domainMatches(hostname, cookieDomain) {
  const normalizedDomain = String(cookieDomain || '').replace(/^\./, '').toLowerCase();
  const normalizedHost = String(hostname || '').toLowerCase();
  return normalizedHost === normalizedDomain || normalizedHost.endsWith(`.${normalizedDomain}`);
}

function pathMatches(pathname, cookiePath) {
  const normalizedPath = pathname || '/';
  const normalizedCookiePath = cookiePath || '/';
  return normalizedPath.startsWith(normalizedCookiePath);
}

function buildCookieHeader(cookies, targetUrl) {
  const url = new URL(targetUrl);
  const nowSeconds = Date.now() / 1000;
  const isHttps = url.protocol === 'https:';

  return cookies
    .filter((cookie) => {
      if (!domainMatches(url.hostname, cookie.domain)) return false;
      if (!pathMatches(url.pathname, cookie.path)) return false;
      if (cookie.expires && cookie.expires > 0 && cookie.expires < nowSeconds) return false;
      if (cookie.secure && !isHttps) return false;
      return true;
    })
    .map((cookie) => `${cookie.name}=${cookie.value}`)
    .join('; ');
}

function hasLoginInputsInHtml(html, config) {
  try {
    const $ = cheerio.load(html || '');
    const hasUsername = config.authUsernameSelector ? $(config.authUsernameSelector).length > 0 : false;
    const hasPassword = config.authPasswordSelector ? $(config.authPasswordSelector).length > 0 : false;
    const hasAuthenticatedUser =
      $('#currentUser').length > 0 ||
      $('.currentUser').length > 0 ||
      $('[data-target="#logout"], [href*="logout"]').length > 0;

    return hasUsername && hasPassword && !hasAuthenticatedUser;
  } catch {
    return false;
  }
}

function extractTitle(html) {
  try {
    const $ = cheerio.load(html || '');
    return $('title').first().text().trim();
  } catch {
    return '';
  }
}

function buildForecastUrl(baseUrl, { activeTab, perPage, page }) {
  const url = new URL(baseUrl);
  url.searchParams.set('ForecastSearch[activeTab]', String(activeTab));
  url.searchParams.set('ForecastSearch[perPage]', String(perPage));
  url.searchParams.set('page', String(page));
  return url.toString();
}

async function fetchTargetHtmlWithSession({ context, config, targetUrl }) {
  const requestUrl = targetUrl || config.targetUrl;
  const storageState = await context.storageState();
  const cookieHeader = buildCookieHeader(storageState.cookies || [], requestUrl);

  const response = await axios.get(requestUrl, {
    headers: {
      Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Accept-Language': 'ru,en;q=0.9',
      'User-Agent': config.httpUserAgent,
      Referer: config.baseUrl,
      Cookie: cookieHeader
    },
    timeout: config.requestTimeoutMs,
    maxRedirects: 10,
    validateStatus: () => true,
    responseType: 'text'
  });

  const html = typeof response.data === 'string' ? response.data : String(response.data || '');
  const finalUrl = response?.request?.res?.responseUrl || requestUrl;
  const loginByUrl = Boolean(config.authLoginDetectUrlPart && String(finalUrl).includes(config.authLoginDetectUrlPart));
  const loginByHtml = hasLoginInputsInHtml(html, config);

  return {
    status: response.status,
    html,
    finalUrl,
    title: extractTitle(html),
    authRequired: loginByUrl || loginByHtml
  };
}

module.exports = {
  fetchTargetHtmlWithSession,
  buildForecastUrl
};
