'use strict';

/* eslint-disable newline-per-chained-call */
const bhttp = require('bhttp');
const cheerio = require('cheerio');
const moment = require('moment');

const slugify = require('../utils/slugify');
const { ex, get } = require('../utils/q');

function titleExtractor(pathname) {
    const components = pathname.split('/')[2].split('-');
    const entryId = components.slice(-1)[0];

    const title = components.slice(0, -1).reduce((accTitle, word, index) => `${accTitle}${index > 0 ? ' ' : ''}${word.slice(0, 1).toUpperCase()}${word.slice(1)}`, '');

    return { title, entryId };
}

function scrapeLatest(html, site) {
    const $ = cheerio.load(html, { normalizeWhitespace: true });
    const sceneElements = $('.site-list .scene-item').toArray();

    return sceneElements.map((item) => {
        const element = $(item);

        const sceneLinkElement = element.find('a').first();
        const { protocol, hostname, pathname } = new URL(sceneLinkElement.attr('href'));
        const url = `${protocol}//${hostname}${pathname}`;
        const { title, entryId } = titleExtractor(pathname);

        const date = moment.utc(element.find('.entry-date').text(), 'MMM D, YYYY').toDate();
        const actors = element.find('.contain-actors a').map((actorIndex, actorElement) => $(actorElement).text()).toArray();

        const duration = Number(element.find('.scene-runtime').text().slice(0, -4)) * 60;

        const posterString = sceneLinkElement.find('img[data-srcset]').attr('data-srcset') || sceneLinkElement.find('img[data-src]').attr('data-src');
        const poster = `https:${posterString.match(/[\w/.]+$/)[0]}`;

        return {
            url,
            entryId,
            title,
            actors,
            date,
            duration,
            poster,
            rating: null,
            site,
        };
    });
}

function scrapeScene(html, url, site) {
    const $ = cheerio.load(html, { normalizeWhitespace: true });
    const sceneElement = $('.scene-info');

    const { protocol, hostname, pathname } = new URL(url);
    const originalUrl = `${protocol}//${hostname}${pathname}`;

    const entryId = originalUrl.split('-').slice(-1)[0];
    const title = sceneElement.find('h1.scene-title.grey-text').text();
    const description = sceneElement.find('.synopsis').contents().slice(2).text().replace(/[\s\n]+/g, ' ').trim();

    const date = moment.utc(sceneElement.find('span.entry-date').text(), 'MMM D, YYYY').toDate();
    const actors = $('a.scene-title.grey-text.link').map((actorIndex, actorElement) => $(actorElement).text()).toArray();

    const duration = Number(sceneElement.find('.duration-ratings .duration').text().slice(10, -4)) * 60;

    const poster = `https:${$('video, dl8-video').attr('poster')}`;
    const photos = $('.contain-scene-images.desktop-only a').map((index, el) => `https:${$(el).attr('href')}`).toArray();

    const trailerEl = $('source');
    const trailerSrc = trailerEl.attr('src');
    const trailerType = trailerEl.attr('type');

    const siteName = sceneElement.find('a.site-title').text();
    const channel = siteName.replace(/[\s']+/g, '').toLowerCase();

    const tags = $('.categories a.cat-tag').map((tagIndex, tagElement) => $(tagElement).text()).toArray();

    return {
        url,
        entryId,
        title,
        description,
        actors,
        date,
        duration,
        tags,
        photos,
        poster,
        trailer: {
            src: trailerSrc,
            type: trailerType,
        },
        rating: null,
        site,
        channel,
    };
}

async function fetchActorReleases(url) {
    const { qus } = await get(url);

    return qus('.contain-block:not(.live-scenes) .scene-item > a:first-child'); // live scenes repeat on all pages
}

async function scrapeProfile(html) {
    const { q, qus } = ex(html);
    const profile = {};

    profile.description = q('.bio_about_text', true);

    const avatar = q('img.performer-pic', 'src');
    if (avatar) profile.avatar = `https:${avatar}`;

    const releases = qus('.scene-item > a:first-child');
    const otherPages = qus('.pagination a:not([rel=next]):not([rel=prev])');
    const olderReleases = await Promise.all(otherPages.map(async page => fetchActorReleases(page)));

    profile.releases = releases.concat(olderReleases.flat());

    return profile;
}

async function fetchLatest(site, page = 1) {
    const res = await bhttp.get(`${site.url}?page=${page}`);

    return scrapeLatest(res.body.toString(), site);
}

async function fetchScene(url, site) {
    const res = await bhttp.get(url);

    return scrapeScene(res.body.toString(), url, site);
}

async function fetchProfile(actorName) {
    const actorSlug = slugify(actorName);

    const res = await bhttp.get(`https://www.naughtyamerica.com/pornstar/${actorSlug}`);

    if (res.statusCode === 200) {
        return scrapeProfile(res.body.toString());
    }

    return null;
}

module.exports = {
    fetchLatest,
    fetchScene,
    fetchProfile,
};
