'use strict';

const bhttp = require('bhttp');
const cheerio = require('cheerio');
const { JSDOM } = require('jsdom');
const moment = require('moment');

const knex = require('../knex');

/* eslint-disable newline-per-chained-call */
function scrapeLatest(html, site) {
    const $ = cheerio.load(html, { normalizeWhitespace: true });
    const sceneElements = $('.card.m-1').toArray();

    return sceneElements.map((element) => {
        const sceneLinkElement = $(element).find('a').first();
        const title = sceneLinkElement.attr('title');
        const url = `${site.url}${sceneLinkElement.attr('href')}`;
        const entryId = url.split('/').slice(-1)[0];

        const date = moment.utc($(element).find('small[datetime]').attr('datetime'), 'YYYY-MM-DD HH:mm:ss').toDate();
        const actors = $(element).find('.card-subtitle a').map((actorIndex, actorElement) => $(actorElement).text().trim())
            .toArray()
            .filter(actor => actor);

        const duration = parseInt($(element).find('.card-info div:nth-child(2) .card-text').text(), 10) * 60;

        const poster = sceneLinkElement.find('img').attr('data-src');

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

async function scrapeScene(html, url, site) {
    const $ = cheerio.load(html, { normalizeWhitespace: true });

    const entryId = url.split('/').slice(-1)[0];
    const title = $('meta[itemprop="name"]').attr('content');
    const description = $('.descr-box p').text(); // meta tags don't contain full description

    const dateProp = $('meta[itemprop="uploadDate"]').attr('content');
    const date = dateProp
        ? moment.utc($('meta[itemprop="uploadDate"]').attr('content'), 'YYYY-MM-DD').toDate()
        : moment.utc($('.title-border:nth-child(2) p').text(), 'MM.DD.YYYY').toDate();
    const actors = $('.pornstar-card > a').map((actorIndex, actorElement) => $(actorElement).attr('title')).toArray();

    const likes = Number($('.info-panel.likes .likes').text());
    const duration = Number($('.info-panel.duration .duration').text().slice(0, -4)) * 60;

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

    const poster = $('#video').attr('poster');
    const photos = $('.photo-slider-guest .card a').map((photoIndex, photoElement) => $(photoElement).attr('href')).toArray();

    const trailer540 = $('source[res="540"]').attr('src');
    const trailer720 = $('source[res="720"]').attr('src');

    return {
        url,
        entryId,
        title,
        description,
        actors,
        date,
        duration,
        tags,
        poster,
        photos,
        trailer: [
            {
                src: trailer720,
                quality: 720,
            },
            {
                src: trailer540,
                quality: 540,
            },
        ],
        rating: {
            likes,
        },
        site,
    };
}

async function scrapeProfile(html, _url, actorName) {
    const { document } = new JSDOM(html).window;

    const keys = Array.from(document.querySelectorAll('.about-title'), el => el.textContent.trim().replace(':', ''));
    const values = Array.from(document.querySelectorAll('.about-info'), (el) => {
        if (el.children.length > 0) {
            return Array.from(el.children, child => child.textContent.trim()).join(', ');
        }

        return el.textContent.trim();
    });

    const bio = keys.reduce((acc, key, index) => {
        if (values[index] === '-') {
            return acc;
        }

        return {
            ...acc,
            [key]: values[index],
        };
    }, {});

    const descriptionEl = document.querySelector('.description-box');
    const avatarEl = document.querySelector('.pornstar-details .card-img-top');

    const country = await knex('countries')
        .where('nationality', 'ilike', `%${bio.Nationality}%`)
        .orderBy('priority', 'desc')
        .first();

    const profile = {
        name: actorName,
    };

    profile.birthdate = moment.utc(bio.Birthday, 'MMMM DD, YYYY').toDate();
    if (country) profile.birthPlace = country.name;

    if (bio['Bra size']) [profile.bust] = bio['Bra size'].match(/\d+\w+/);
    if (bio.Waist) profile.waist = Number(bio.Waist.match(/\d+/)[0]);
    if (bio.Hips) profile.hip = Number(bio.Hips.match(/\d+/)[0]);

    if (bio.Height) profile.height = Number(bio.Height.match(/\d{2,}/)[0]);

    if (bio['Tit Style'] && bio['Tit Style'].match('Enhanced')) profile.naturalBoobs = false;
    if (bio['Tit Style'] && bio['Tit Style'].match('Natural')) profile.naturalBoobs = true;

    if (bio['Body Art'] && bio['Body Art'].match('Tattoo')) profile.hasTattoos = true;
    if (bio['Body Art'] && bio['Body Art'].match('Piercing')) profile.hasPiercings = true;

    if (bio['Hair Style']) profile.hair = bio['Hair Style'].split(',')[0].trim().toLowerCase();
    if (bio['Eye Color']) profile.eyes = bio['Eye Color'].match(/\w+/)[0].toLowerCase();

    if (bio['Shoe size']) profile.shoes = Number(bio['Shoe size'].split('|')[1]);

    if (descriptionEl) profile.description = descriptionEl.textContent.trim();
    if (avatarEl && avatarEl.dataset.src.match('^//')) profile.avatar = `https:${avatarEl.dataset.src}`;

    return profile;
}

async function fetchLatest(site, page = 1) {
    const res = await bhttp.get(`https://ddfnetwork.com/videos/search/latest/ever/${new URL(site.url).hostname}/-/${page}`);

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

async function fetchScene(url, site) {
    const res = await bhttp.get(`https://ddfnetwork.com${new URL(url).pathname}`);

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

async function fetchProfile(actorName) {
    const resSearch = await bhttp.post('https://ddfnetwork.com/search/ajax',
        {
            type: 'hints',
            word: actorName,
        },
        {
            decodeJSON: true,
            headers: {
                'x-requested-with': 'XMLHttpRequest',
            },
        });

    if (resSearch.statusCode !== 200 || Array.isArray(resSearch.body.list)) {
        return null;
    }

    if (!resSearch.body.list.pornstarsName || resSearch.body.list.pornstarsName.length === 0) {
        return null;
    }

    const [actor] = resSearch.body.list.pornstarsName;
    const url = `https://ddfnetwork.com${actor.href}`;

    const resActor = await bhttp.get(url);

    if (resActor.statusCode !== 200) {
        return null;
    }

    return scrapeProfile(resActor.body.toString(), url, actorName);
}

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