Object.entries(require('./common.js')).forEach(([name, exported]) => global[name] = exported);
const url = "https://ocs.ca";
function reqq(level, category, name) {
	return request({
		url: 'https://u2ghas8n0v-dsn.algolia.net/1/indexes/ocs_products/query?x-algolia-application-id=U2GHAS8N0V&x-algolia-api-key=0fce38bd280fd213b8a14f7a59602b7d',
		method: 'POST',
		body: '{"params":"hitsPerPage=1000&distinct=0&filters=(NOT tags:%22subsubcategory--Variety Packs%22) AND (NOT tags:subsubcategory--Topicals) AND (tags:language--en) AND (tags:%22' + level + 'category--' + category + '%22)"}'
	}).then(obj => {
		obj = JSON.parse(obj);
		if(obj.nbHits > obj.hitsPerPage) {
			console.log("missing " + (obj.nbHits - obj.hitsPerPage) + ' items for ' + category);
		}
		for(let i = 0; i < obj.hits.length; ++i) {
			obj.hits[i].type = name;
		}
		return obj.hits;
	});
}
function ok() {
	for(let i = 0; i < arguments.length; ++i) {
		if(arguments[i] === undefined || arguments[i] === null) {
			return false;
		}
	}
	return true;
}
(async function() {
	let e = Promise.all([
		reqq('sub', 'Dried Flower', 'flower'),
		reqq('sub', 'Pre-Rolls', 'preroll'),
		reqq('sub', 'Oils', 'oil'),
		reqq('sub', 'Capsules', 'capsule'),
		reqq('subsub', '510 Thread Pens and Kits', 'cartridge'),
		reqq('subsub', 'Disposable Pens and Kits', 'disposable'),
		reqq('subsub', 'Proprietary Systems Pens and Kits', 'cartridge'),
		reqq('subsub', 'Coffees and Teas', 'tea'),
		reqq('subsub', 'Soft Chews', 'gummy'),
		reqq('subsub', 'Hard Edibles', 'mint'),
		reqq('sub', 'Chocolates', 'chocolate'),
		reqq('subsub', 'Cookies', 'cookie')
	]).then(e => Object.values(groupBy(e.flat(), 'handle')));
	await postgres.connect();
	await postgres.query('begin');
	e = await e;
	let storeID = await return_key(
		`insert into store (
			name,
			URL,
			region,
			country
		) values (
			$1, $2, $3, $4
		) on conflict do nothing
		returning ID`,
		[
			'Ontario Cannabis Store',
			url,
			'ontario',
			'canada'
		]
	);
	if(storeID.length === 0) {
		storeID = await return_key(
			`select
				ID
			from
				store
			where
				name = $1 and
				URL = $2 and
				region = $3 and
				country = $4 and
				address is null and
				address2 is null and
				city is null and
				postal_code is null and
				coordinate is null and
				timezone is null`,
			[
				'Ontario Cannabis Store',
				url,
				'ontario',
				'canada'
			]
		);
		if(storeID.length === 0) {
			console.error("why can't I find the store???");
			process.exit(1);
		}
	}
	storeID = storeID[0][0];
	//image: https://cdn.shopify.com/s/files/1/2636/1928/files/OCS_EN_LOGO_BLK_SM_nav.png?v=1560138074
	//what the font
	//stupid as fuck though. we can do better
	let ii = 0;
	let progress = 0;
	cliProgressBar.start(e.length, progress);
	async function deal() {
		while(ii < e.length) {
			let i = ii++;
			let minTHC, maxTHC, minCBD, maxCBD, unit, UOM;
			if(e[i][0].type === 'flower' || e[i][0].type === 'preroll' || e[i][0].type === 'cartridge' || e[i][0].type === 'disposable') {
				minTHC = percent2proportion(e[i][0].meta.product.thc_content_min);
				maxTHC = percent2proportion(e[i][0].meta.product.thc_content_max);
				minCBD = percent2proportion(e[i][0].meta.product.cbd_content_min);
				maxCBD = percent2proportion(e[i][0].meta.product.cbd_content_max);
				unit = 'proportion';
				UOM = 'g';
			} else {
				minTHC = e[i][0].meta.variant.thc_min_per
				maxTHC = e[i][0].meta.variant.thc_max_per;
				minCBD = e[i][0].meta.variant.cbd_min_per;
				maxCBD = e[i][0].meta.variant.cbd_max_per;
				unit = 'mg';
				if(e[i][0].type === 'oil') {
					UOM = 'ml';
				} else if(e[i][0].type === 'tea') {
					UOM = 'sachet';
				} else if(e[i][0].type === 'chocolate') {
					UOM = 'piece';
				} else {//capsule, gummy, mint, cookie
					UOM = e[i][0].type;
				}
				if(e[i][0].type === 'chocolate' || e[i][0].type === 'gummy' || e[i][0].type === 'mint') {
					let n = new Big(e[i][0].meta.variant.retail_pack_number_of_items);
					minTHC = (new Big(minTHC)).div(n).toString();
					maxTHC = (new Big(maxTHC)).div(n).toString();
					minCBD = (new Big(minCBD)).div(n).toString();
					minCBD = (new Big(minCBD)).div(n).toString();
				}
			}
			for(let j = 0; j < e[i][0].tags.length; ++j) {
				if(e[i][0].tags[j] === 'subsubcategory--Oral Sprays') {
					e[i][0].type = 'spray';
				}
			}
			let [brand, title] = normalize(e[i][0].vendor, e[i][0].title, e[i][0].type);
			let fuckoff = e[i][0].meta.product.plant_type;
			let f2;
			for(let f = 0; f < e[i][0].tags.length; ++f) {
				if(e[i][0].tags[f].startsWith('plant_type--')) {
					if(f2 !== undefined) {
						console.log("I HATE MY LIFE")
					}
					f2 = e[i][0].tags[f].slice(12);
				}
			}
			if(fuckoff === undefined) {
				fuckoff = f2
			}
			if(f2 !== fuckoff) {
				console.log("this is so gay")
				console.log(f2)
				console.log(fuckoff);
			}
			let description = e[i][0].body_html_safe;
			if(typeof description === 'string') {
				description = description.replace(/\s+/g, ' ');
			}
			let terpenes = [];
			for(let j = 0; j < e[i][0].tags.length; ++j) {
				let terpene = e[i][0].tags[j].split('terpenes--')[1];
				if(terpene) {
					terpenes.push(terpene);
				}
			}
			let productID = await return_key(
				`insert into product (
					joined_brand,
					joined_name,
					type,
					display_brand,
					display_name,
					strain,
					description,
					concentration_unit,
					measurement_unit,
					show,
					terpenes
				) values (
					$1, $2, $3, $4, $5, $6, $7, $8, $9, true, $10
				) on conflict do nothing
				returning ID`,
				[
					brand,
					title,
					e[i][0].type,
					e[i][0].vendor,
					e[i][0].title,
					fuckoff.toLowerCase().split(/\s+/)[0],
					description,
					unit,
					UOM,
					terpenes
				]
			);
			if(productID.length === 0) {
				productID = await return_key(
					`select
						ID
					from
						product
					where
						joined_brand = $1 and
						joined_name = $2 and
						type = $3`,
					[brand, title, e[i][0].type]
				);
				//console.log(productID, `${url}/products/${e[i][0].handle}) //on empty db, useful to find products that are actually variants of something we inserted earlier. good job ocs dumbfucks
				if(productID.length === 0) {
					console.error("why can't I find the product???");
					process.exit(1);
				}
			}
			productID = productID[0][0];
			let pics = new Set((await request({
				url: `${url}/products/${e[i][0].handle}.json`,
				headers: {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36"}
			}).then(JSON.parse)).product.images.map(a => a.src.split('?')[0]));
			for(let pic of pics) {
				let product_images = await return_key('select ID from product_image where product = $1 and source = $2', [productID, pic]);
				if(product_images.length === 0) {
					let response = (await exec('./image.sh ' + pic)).stdout.trim();
					if(response !== '404') {
						let ar = await cloudinary.uploader.upload(response, {public_id: response.slice(5), unique_filename: false});
						let img_insert = await return_key(
							`insert into product_image (
								product,
								source,
								destination
							) values (
								$1,
								$2,
								$3
							) on conflict do nothing
							returning ID`,
							[productID, pic, ar.secure_url]
						);
						if(img_insert.length === 0) {
							console.error("how the FUCK", productID, pic, ar.secure_url);
						} else if(img_insert.length > 1) {
							console.error('kys');
						}
					}
				} else if(product_images.length === 1) {
					//console.log('already persisted :)');
					//have a flag that once a month, we fetch images anyways just to see if there's a diff? thanks cloudinary :)
				} else {
					console.error('data integrity issue', product_images);
					//product match, source match, but destinations are different, which should be unpossible
				}
			}
			let quicky = (await request({
				url: `${url}/products/${e[i][0].handle}?view=quickview`,
				headers: {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36"}
			}).then(JSON.parse)).variants;
			for(let j = 0; j < e[i].length; ++j) {
				let fml = quicky.find(v => v.id == e[i][j].objectID);
				let gram_equivalency;
				if(fml !== undefined && fml.metafields !== undefined && fml.metafields.variant !== undefined && fml.metafields.variant.gram_equivalency !== undefined) {
					gram_equivalency = fml.metafields.variant.gram_equivalency;
				} else {
					console.log(quicky);
					console.log(fml);
					console.log(fml.metafields);
					console.log(fml.metafields.variant)
					console.log(fml.metafields.variant.gram_equivalency);
				}
				let portions = null;
				let quantity;
				switch(e[i][j].type) {
					case 'capsule':
						quantity = e[i][j].meta.variant.retail_pack_number_of_items;
						break;
					case 'disposable':
					case 'cartridge':
					case 'flower':
					case 'spray':
					case 'oil':
						if(e[i][j].meta.variant && e[i][j].meta.variant.retail_pack_net_content) {
							quantity = e[i][j].meta.variant.retail_pack_net_content;
						} else {
							quantity = e[i][j].variant_title.match(qty)[3];
						}
						break;
					case 'tea':
					case 'gummy':
					case 'mint':
					case 'preroll':
					case 'cookie':
					case 'chocolate':
						portions = e[i][j].meta.variant.retail_pack_number_of_items;
						if(portions === 0) {
							[, , portions, quantity] = e[i][j].variant_title.match(qty);
						} else {
							quantity = (new Big(e[i][j].meta.variant.retail_pack_net_content)).div(new Big(portions)).toString();
						}
						break;
				}
				if(portions !== null && portions < 2) {
					//console.log(productID, e[i][j].type, portions, quantity);
					portions = null;
				}
				let variantID = await return_key(
					`insert into variant (
						product,
						portions,
						quantity,
						flavor,
						gram_equivalency
					) values (
						$1, $2, $3, $4, $5
					)
					on conflict do nothing
					returning ID`,
					[productID, portions, quantity, e[i][j].options.flavour, gram_equivalency]
				);
				if(variantID.length === 0) {
					let parameters = [productID, quantity];
					variantID = await return_key(
						`select
							ID,
							gram_equivalency
						from
							variant
						where
							product = $1 and
							quantity = $2 and
							portions ${portions === null ? 'is null' : '= $' + parameters.push(portions)} and
							flavor ${e[i][j].options.flavour === undefined ? 'is null' : '= $' + parameters.push(e[i][j].options.flavour)}`,
						parameters
					);
					if(gram_equivalency !== variantID[0][1]) {
						console.log('warning: gram_equivalency does not match', gram_equivalency, variantID[0][1], productID, variantID[0][0], `${url}/products/${e[i][j].handle}?variant=${e[i][j].objectID}`);
					}
					if(variantID.length === 0) {
						console.error("why can't I find the variant???");
						process.exit(1);
					}
				}
				variantID = variantID[0][0];
				await postgres.query(
					`insert into variant_identifier (
						variant,
						gtin
					) values (
						$1,
						$2
					) on conflict do nothing`,
					[variantID, e[i][j].sku]
				);
				if(ok(minCBD, maxCBD, minTHC, maxTHC, e[i][j].price, e[i][j].inventory_quantity)) {
					await postgres.query(
						`insert into menu_item (
							variant,
							store,
							CBD,
							THC,
							price,
							stock,
							path
						) values (
							$1,
							$2,
							$3,
							$4,
							$5,
							$6,
							$7
						) on conflict do nothing`,
						[
							variantID,
							storeID,
							`[${minCBD},${maxCBD}]`,
							`[${minTHC},${maxTHC}]`,
							 e[i][j].price,
							 e[i][j].inventory_quantity,
							 `/products/${e[i][j].handle}?variant=${e[i][j].objectID}`
						]
					);
				} else {
					console.error(`why don't you fix your fucking data ocs?? ${url}/products/${e[i][j].handle}?variant=${e[i][j].objectID}`);
				}
			}
			cliProgressBar.update(++progress);
		}
	}
	await Promise.all([
		deal(),
		deal(),
		deal(),
		deal(),
		deal(),
		deal()
	])
	await postgres.query('commit');
	await postgres.end();
})();