import { Route, ViewType } from '@/types';

import ofetch from '@/utils/ofetch';
import { load } from 'cheerio';
import { parseRelativeDate } from '@/utils/parse-date';
import { puppeteerGet } from './utils';
import sanitizeHtml from 'sanitize-html';
import cache from '@/utils/cache';

export const route: Route = {
    path: '/user/:id/:type?',
    categories: ['social-media'],
    example: '/picnob/user/xlisa_olivex',
    parameters: {
        id: 'Instagram id',
        type: 'Type of profile page (profile or tagged)',
    },
    features: {
        requireConfig: false,
        requirePuppeteer: true,
        antiCrawler: true,
        supportBT: false,
        supportPodcast: false,
        supportScihub: false,
    },
    radar: [
        {
            source: ['www.pixnoy.com/profile/:id'],
            target: '/user/:id',
        },
        {
            source: ['www.pixnoy.com/profile/:id/tagged'],
            target: '/user/:id/tagged',
        },
    ],
    name: 'User Profile - Picnob',
    maintainers: ['TonyRL', 'micheal-death', 'AiraNadih', 'DIYgod'],
    handler,
    view: ViewType.Pictures,
};

async function handler(ctx) {
    // NOTE: 'picnob' is still available, but all requests to 'picnob' will be redirected to 'pixnoy' eventually
    const baseUrl = 'https://www.pixnoy.com';
    const id = ctx.req.param('id');
    const type = ctx.req.param('type') ?? 'profile';
    const profileUrl = `${baseUrl}/profile/${id}/${type === 'tagged' ? 'tagged/' : ''}`;

    // TODO: can't bypass cloudflare 403 error without puppeteer
    let html;
    let usePuppeteer = false;
    try {
        const data = await ofetch(profileUrl);
        html = data;
    } catch {
        html = await puppeteerGet(profileUrl);
        usePuppeteer = true;
    }
    const $ = load(html);

    const list = $('.post_box')
        .toArray()
        .map((item) => {
            const $item = $(item);
            const sum = $item.find('.sum').text();
            const coverLink = $item.find('.cover_link').attr('href');
            const shortcode = coverLink?.split('/')?.[2];

            return {
                title: sanitizeHtml(sum.split('\n')[0], { allowedTags: [], allowedAttributes: {} }),
                description: `<img src="${$item.find('.preview_w img').attr('data-src')}" /><br />${sum.replaceAll('\n', '<br>')}`,
                link: `${baseUrl}${coverLink}`,
                guid: shortcode,
                pubDate: parseRelativeDate($item.find('.time .txt').text()),
            };
        });

    const newDescription = await Promise.all(
        list.map((item) =>
            cache.tryGet(`picnob:user:${id}:${item.guid}`, async () => {
                try {
                    const html = usePuppeteer
                        ? await puppeteerGet(item.link)
                        : await ofetch(item.link, {
                              headers: {
                                  'user-agent': 'PostmanRuntime/7.44.0',
                              },
                          });
                    const $ = load(html);
                    if ($('.video_img').length > 0) {
                        return `<video src="${$('.video_img a').attr('href')}" poster="${$('.video_img img').attr('data-src')}"></video><br />${$('.sum_full').text()}`;
                    } else {
                        let description = '';
                        for (const slide of $('.swiper-slide').toArray()) {
                            const $slide = $(slide);
                            description += `<img src="${$slide.find('.pic img').attr('data-src')}" /><br />`;
                        }
                        description += $('.sum_full').text();
                        return description;
                    }
                } catch {
                    return '';
                }
            })
        )
    );

    return {
        title: `${$('h1.fullname').text()} (@${id}) ${type === 'tagged' ? 'tagged' : 'public'} posts - Picnob`,
        description: $('.info .sum').text(),
        link: profileUrl,
        image: $('.ava .pic img').attr('src'),
        item: list.map((item, index) => ({
            ...item,
            description: newDescription[index] || item.description,
        })),
    };
}
