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

export class Provider8Mandarake implements ISearchProvider {
	readonly stationId = StationId.Mandarake;

	async search(params: ISearchParams): Promise<IPage> {
		return exeSearch(params);
	}
}

async function exeSearch(params: ISearchParams) {
	const {keyword, begin = 1, maxNum = 48, category, minPrice, maxPrice, shipping, sort, order} = params;
	const pageNum = beginToPage(begin, maxNum);
	const warn: string[] = [];
	const url = new URL("https://order.mandarake.co.jp/order/listPage/list");
	url.searchParams.set("keyword", keyword);
	url.searchParams.set("page", String(pageNum));
	url.searchParams.set("dispCount", String(maxNum));
	if (category) {
		url.searchParams.set("categoryCode", category);
	}
	if (minPrice) {
		url.searchParams.set("minPrice", String(minPrice));
	}
	if (maxPrice) {
		url.searchParams.set("maxPrice", String(maxPrice));
	}
	if (shipping === 'free') {
		warn.push('unsupported shipping');
	}
	if (sort) {
		if (sort === Sort.Latest) {
			url.searchParams.set("sort", 'arrival');
			if (order === Order.Asc) {
				url.searchParams.set("sortOrder", '0');
			} else {
				url.searchParams.set("sortOrder", '1');
			}
		} else if (sort ===Sort.Price) {
			url.searchParams.set("sort", 'price');
			if (order === Order.Desc) {
				url.searchParams.set("sortOrder", '1');
			} else {
				url.searchParams.set("sortOrder", '0');
			}
		} else if(sort!==Sort.Default) {
			warn.push(`unsupported sort: ${sort}`);
		}
	}

	
	const resp = await wrappedFetch(url, {
		headers: {
			'Cookie': 'tr_mndrk_user=778e501f.64c8374096346; adult_confirm=1; initialized_cart=1;',
		}
	});

	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(parse(html));

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

function parseProducts(doc: HTMLElement): Omit<IPage, keyof ISearchParams> {
	const map = new Map<string, ISearchItem>();
	doc.querySelectorAll('.thumlarge .block[data-itemidx]')
		.map(parseItem)
		.forEach(item => item.itemId && map.set(item.itemId, item));

	const totalText = doc.querySelector('.item_list_head .count')?.textContent;
	const total = totalText ? parseInt(totalText.replace(/\D+/g, '')) : 0;

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

function parseItem(el: HTMLElement): ISearchItem {
	const priceArr = el.querySelector('.price')?.textContent?.split(/\(/);
	const basePrice = priceArr[0]?.replace(/\D+/g, '');
	const priceText = (priceArr[1] || priceArr[0]).replace(/\D+/g, '');
	const title = el.querySelector('.title a');
	const img = el.querySelector('.pic img');

	return {
		itemId: el.getAttribute('data-itemidx'),
		url: title?.getAttribute('href'),
		image: {
			imageUrl: img?.getAttribute('src'),
		},
		name: title?.textContent?.trim(),
		price: priceText ? parseInt(priceText) : undefined,
		basePrice: basePrice ? parseInt(basePrice) : undefined,
	};
}