import {IPage, ISearchItem, ISearchParams, ISearchProvider, Order, Sort, StationId} from "../type";
import {HTMLElement, parse} from "node-html-parser";
import {beginToPage, wrappedFetch} from "../lib";

export class Provider9Fril implements ISearchProvider {
	readonly stationId = StationId.Fril;

	async search(params: ISearchParams): Promise<IPage> {
		const maxNum = 40;
		const {keyword, begin = 1, maxNum: mn, category, minPrice, maxPrice, shipping, sort, order} = params;
		const warn: string[] = [];
		const pageNum = beginToPage(begin, maxNum);
		const url = new URL("https://fril.jp/s");
		url.searchParams.set("query", keyword);
		url.searchParams.set("page", String(pageNum));
		if (mn !== undefined) {
			warn.push('unsupported maxNum');
		}
		if (category) {
			url.searchParams.set("category_id", category);
		}
		if (minPrice) {
			url.searchParams.set("min", String(minPrice));
		}
		if (maxPrice) {
			url.searchParams.set("max", String(maxPrice));
		}
		if (shipping === 'free') {
			url.searchParams.set("carriage", '1');
		}
		if (sort) {
			if (sort === Sort.Latest) {
				url.searchParams.set("sort", 'created_at');
				if (order === Order.Asc) {
					url.searchParams.set("order", 'asc');
				} else {
					url.searchParams.set("order", 'desc');
				}
			} else if (sort ===Sort.Price) {
				url.searchParams.set("sort", 'sell_price');
				if (order === Order.Desc) {
					url.searchParams.set("order", 'desc');
				} else {
					url.searchParams.set("order", 'asc');
				}
			} else if(sort!==Sort.Default) {
				warn.push(`unsupported sort: ${sort}`);
			}
		}

		
		const resp = await wrappedFetch(url);

		if (!resp.ok) {
			if (resp.status === 404) {
				return {...params, dataList: [], error: '404 Not Found'};
			}
			return {...params, dataList: [], error: `HTTP error! status: ${resp.status}`};
		}

		// noinspection TypeScriptUnresolvedReference
		const html = await resp.text();
		const result = parseProducts(html);

		return {
			srcUrl: url.toString(),
			warning: warn.join(', '),
			begin,
			maxNum,
			pageNum,
			...params,
			...result,
		};
	}
}


function parseProducts(docHtml: string): Omit<IPage, keyof ISearchParams> {
	const map = new Map<string, ISearchItem>();
	const doc = parse(docHtml);
	doc.querySelectorAll('.item-list .content .item')
		.map(parseItem)
		.forEach(item => item.itemId && map.set(item.itemId, item));

	const totalText = doc.querySelector('.item-header .page-count')?.textContent.match(/[\d,]+/)?.[0]?.replace(/,/g, '')
	const total = totalText ? parseInt(totalText) : 0;

	return {
		total: Math.max(total || 0, map.size),
		dataList: Array.from(map.values())
	};
}


function parseItem(el: HTMLElement): ISearchItem {
	const link = el.querySelector('.item-box__item-name a');
	const img = el.querySelector('.item-box__image-wrapper img');
	const url = link?.getAttribute('href');
	const priceText = link.getAttribute('data-rat-cp-price') || el.querySelector('.price-status__price')?.textContent?.replace(/\D+/g, '');

	return {
		itemId: url.replace(/^.*\//, ''),
		itemSlug: link?.getAttribute('data-rat-itemid'),
		url,
		image: {
			imageUrl: img?.getAttribute('data-original'),
			alt: img?.getAttribute('alt'),
		},
		name: link?.textContent?.trim(),
		price: priceText ? parseInt(priceText) : undefined,
	};
}