'use strict';

/* eslint-disable newline-per-chained-call */
const bhttp = require('bhttp');
const { JSDOM } = require('jsdom');
const moment = require('moment');

async function scrapeProfileFrontpage(html, url, name) {
    const { document } = new JSDOM(html).window;
    const bioEl = document.querySelector('.dashboard-bio-list');

    const bioUrl = `https:${document.querySelector('.seemore a').href}`;

    const keys = Array.from(bioEl.querySelectorAll('dt'), el => el.textContent.trim());
    const values = Array.from(bioEl.querySelectorAll('dd'), el => el.textContent.trim());

    const bio = keys.reduce((acc, key, index) => ({ ...acc, [key]: values[index] }), {});

    const profile = {
        name,
        gender: 'female',
    };

    const birthdateString = bio['Date of Birth:'];
    const measurementsString = bio['Measurements:'];

    const birthCityString = bio['Place of Birth:'];
    const birthCity = birthCityString !== undefined && birthCityString !== 'Unknown' && birthCityString !== 'Unknown (add)' && birthCityString;

    const birthCountryString = bio['Country of Origin:'];
    const birthCountry = birthCountryString !== undefined && birthCountryString !== 'Unknown' && birthCountryString !== 'Unknown (add)' && birthCountryString;

    const piercingsString = bio['Piercings:'];
    const tattoosString = bio['Tattoos:'];

    if (birthdateString && birthdateString !== 'Unknown (add)') profile.birthdate = moment.utc(birthdateString.slice(0, birthdateString.indexOf(' (')), 'MMMM D, YYYY').toDate();
    if (measurementsString) [profile.bust, profile.waist, profile.hip] = measurementsString.split('-').map(measurement => (measurement === '??' ? null : measurement));

    if (bio['Fake Boobs:']) profile.naturalBoobs = bio['Fake Boobs:'] === 'No';
    profile.birthPlace = `${birthCity || ''}${birthCity ? ', ' : ''}${birthCountry || ''}`;

    profile.hair = bio['Hair Color:'].toLowerCase();
    profile.eyes = bio['Eye Color:'].toLowerCase();

    if (piercingsString) profile.hasPiercings = !!(piercingsString !== 'Unknown (add)' && piercingsString !== 'None');
    if (tattoosString) profile.hasTattoos = !!(tattoosString !== 'Unknown (add)' && tattoosString !== 'None');

    if (profile.hasPiercings && piercingsString !== 'various') profile.piercings = piercingsString;
    if (profile.hasTattoos && tattoosString !== 'various') profile.tattoos = tattoosString;

    profile.social = Array.from(bioEl.querySelectorAll('.dashboard-socialmedia a'), el => el.href);

    return {
        profile,
        url: bioUrl,
    };
}

async function scrapeProfileBio(html, frontpageProfile, url, name) {
    const { document } = new JSDOM(html).window;
    const bioEl = document.querySelector('#biographyTable');

    const keys = Array.from(bioEl.querySelectorAll('td:nth-child(1)'), el => el.textContent.trim());
    const values = Array.from(bioEl.querySelectorAll('td:nth-child(2)'), el => el.textContent.trim());

    const bio = keys.reduce((acc, key, index) => ({ ...acc, [key]: values[index] }), {});

    const profile = {
        ...frontpageProfile,
        name,
        gender: 'female',
    };

    const birthdateString = bio['Date of Birth:'];
    const measurementsString = bio['Measurements:'];

    const birthCityString = bio['Place of Birth:'];
    const birthCity = birthCityString !== undefined && birthCityString !== 'Unknown' && birthCityString !== 'Unknown (add)' && birthCityString;

    const birthCountryString = bio['Country of Origin:'];
    const birthCountry = birthCountryString !== undefined && birthCountryString !== 'Unknown' && birthCountryString !== 'Unknown (add)' && birthCountryString;

    const piercingsString = bio['Piercings:'];
    const tattoosString = bio['Tattoos:'];

    if (birthdateString && birthdateString !== 'Unknown') profile.birthdate = moment.utc(birthdateString.slice(0, birthdateString.indexOf(' (')), 'MMMM D, YYYY').toDate();
    if (measurementsString) [profile.bust, profile.waist, profile.hip] = measurementsString.split('-').map(measurement => (measurement === '??' ? null : measurement));

    if (bio['Fake boobs']) profile.naturalBoobs = bio['Fake boobs:'] === 'No';
    profile.ethnicity = bio['Ethnicity:'];

    profile.birthPlace = `${birthCity || ''}${birthCity ? ', ' : ''}${birthCountry || ''}`;

    profile.hair = bio['Hair Color:'].toLowerCase();
    profile.eyes = bio['Eye Color:'].toLowerCase();
    profile.height = Number(bio['Height:'].match(/\d+/)[0]);
    profile.weight = Number(bio['Weight:'].match(/\d+/)[0]);

    if (piercingsString) profile.hasPiercings = !!(piercingsString !== 'Unknown (add)' && piercingsString !== 'None');
    if (tattoosString) profile.hasTattoos = !!(tattoosString !== 'Unknown (add)' && tattoosString !== 'None');

    if (profile.hasPiercings && piercingsString !== 'various') profile.piercings = piercingsString;
    if (profile.hasTattoos && tattoosString !== 'various') profile.tattoos = tattoosString;

    profile.social = Array.from(bioEl.querySelectorAll('#socialmedia a'), el => el.href);

    return profile;
}

async function fetchProfile(actorName) {
    const slug = actorName.replace(' ', '_');
    const frontpageUrl = `https://www.freeones.com/html/v_links/${slug}`;

    const resFrontpage = await bhttp.get(frontpageUrl);

    if (resFrontpage.statusCode === 200) {
        const { url, bio } = await scrapeProfileFrontpage(resFrontpage.body.toString(), frontpageUrl, actorName);
        const resBio = await bhttp.get(url);

        return scrapeProfileBio(resBio.body.toString(), bio, url, actorName);
    }

    // apparently some actors are appended 'Babe' as their surname...
    const fallbackSlug = `${slug}_Babe`;
    const fallbackUrl = `https://www.freeones.com/html/s_links/${fallbackSlug}`;
    const resFallback = await bhttp.get(fallbackUrl);

    if (resFallback.statusCode === 200) {
        const { url, profile } = await scrapeProfileFrontpage(resFallback.body.toString(), fallbackUrl, actorName);
        const resBio = await bhttp.get(url);

        return scrapeProfileBio(resBio.body.toString(), profile, url, actorName);
    }

    return null;
}

module.exports = {
    fetchProfile,
};
