import { createSignal, createEffect, createState, createMemo, createComputed } from "solid-js";
import { req } from '../websocket';
import { pgRange2String, fmt, create_deferred, c } from '../util';
import { state as glo } from '../store';

export default function(props) {
	let original = {
		search: '',
		species: [],
		types: [],
		strains: [],
		effects: [],
		producers: {},
		min_thc2tc: '0',
		max_thc2tc: '1',
		sort: 'unsorted',
		inventory: null
	};
	let america;
	if(history.state.america) {
		if(typeof history.state.america.producers === 'object') {
			america = JSON.parse(JSON.stringify(history.state.america));
			for(const key in america.producers) {
				if(america.producers[key].checked === undefined) {
					america.producers[key].checked = false;
				}
				if(america.producers[key].brands === undefined) {
					america.producers[key].brands = [];
				}
			}
		} else {
			america = history.state.america;
		}
	} else {
		let s = new URLSearchParams(location.search);
		america = {producers: {}};
		if(s.has('search')) {
			america['search'] = s.get('search');
		}
		if(s.has('min_thc2tc')) {
			america['min_thc2tc'] = s.get('min_thc2tc');
		}
		if(s.has('max_thc2tc')) {
			america['max_thc2tc'] = s.get('max_thc2tc');
		}
		if(s.has('sort')) {
			america['sort'] = s.get('sort');
		}
		if(s.has('inventory')) {
			america['inventory'] = s.get('inventory') === 'true';
		}
		if(s.has('species')) {
			america['species'] = s.get('species').split('_');
		}
		if(s.has('types')) {
			america['types'] = s.get('types').split('_');
		}
		if(s.has('strains')) {
			america['strains'] = s.get('strains').split('_');
		}
		if(s.has('effects')) {
			america['effects'] = s.get('effects').split('_');
		}
		for(const [key, value] of s) {
			if(key.startsWith('p_')) {
				let actual = key.split('_');
				if(actual[1]) {
					america.producers[actual[1]] = {checked: false, brands: value.split('_')}
				}
			}
		}
		if(s.has('producers')) {
			let p = s.get('producers').split('_');
			for(let i = 0; i < p.length; ++i) {
				if(america.producers[p[i]] === undefined) {
					america.producers[p[i]] = {checked: true, brands: []}
				} else {
					america.producers[p[i]].checked = true;
				}
			}
		}
	}
	const [products, setProducts] = createSignal(history.state.products);
	const [state, setState] = createState(Object.assign(JSON.parse(JSON.stringify(original)), america));
	const [f, setF] = createSignal(history.state.f);
	createComputed(() => {
		let o = {};
		for(let i = 0; i < f()?.idk.length; ++i) {
			o[f().idk[i].producer] = {checked: false, brands: []};
			if(state.producers[f().idk[i].producer] === undefined) {
				setState('producers', f().idk[i].producer, o[f().idk[i].producer]);
			}
		}
		original.producers = o;
	});
	let poop = create_deferred();
	if(!products()) {
		lol();
	}
	req('productsq').then(x => {setTimeout(poop.resolve); setF(x);});
	createEffect(() => history.replaceState({...history.state, america: diffState()}, ""));
	createEffect(() => history.replaceState({...history.state, products: products()}, ""));
	createEffect(() => history.replaceState({...history.state, f: f()}, ""));

	const inhalation = createMemo(() => state.types.includes('flower') || state.types.includes('preroll') || state.types.includes('cartridge') || state.types.includes('disposable'));
	const sublingual = createMemo(() => state.types.includes('oil') || state.types.includes('spray'));
	const ingestion = createMemo(() => state.types.includes('capsule') || state.types.includes('tea') || state.types.includes('gummy') || state.types.includes('mint') || state.types.includes('chocolate') || state.types.includes('baked'));
	const canSortByConcentration = createMemo(() => {
		let r = 0;
		if(inhalation()) {++r}
		if(sublingual()) {++r}
		if(ingestion()) {++r}
		return r === 1;
	});
	const canSortByPrice_g = createMemo(() => inhalation() && !sublingual() && !ingestion());
	createEffect(() => {
		if(!canSortByConcentration() && (state.sort.startsWith('THC') || state.sort.startsWith('CBD')) || !canSortByPrice_g() && state.sort.startsWith('price_g')) {
			setState('sort', 'unsorted');
		}
	})
	function inventoryRadio(e) {
		let v = null;
		switch(e.target.value) {
			case 't':
				v = true;
				break;
			case 'f':
				v = false;
				break;
		}
		setState('inventory', v)
	}
	async function lol() {
		let conditions = [];
		for(let key in state.producers) {
			let a = new Set(state.producers[key].brands);
			if(a.size) {
				await poop;
			}
			let b;
			//checking every brand under a producer does not imply checking the producer
			//the following conditional is ok because productsq is fresh
			if(state.producers[key].checked || a.size === (b = new Set(f().idk.find(e => e.producer === key || (e.producer === null && key === 'null')).brands)).size && state.producers[key].brands.every(value => b.has(value))) {
				conditions.push({producer: key === 'null' ? null : key});
			} else if(a.size) {
				conditions.push({producer: key === 'null' ? null : key, brands: state.producers[key].brands});
			}
		}
		let special = {};
		if(state.min_thc2tc !== '0' || state.max_thc2tc !== '1') {
			special.thc2tc = [state.min_thc2tc, state.max_thc2tc];
		}
		if(state.sort !== 'unsorted') {
			let [what, how] = state.sort.split(/\s+/);
			special[what] = how === 'ascending' || how === 'a-z';
		}
		req('products', {...special,
			stores: [props.sid],
			species: state.species.length ? state.species : undefined,
			types: state.types.length ? state.types : undefined,
			strain_ids: state.strains.length ? state.strains : undefined,
			producers: conditions.length ? conditions : undefined,
			search: state.search.length ? state.search : undefined,
			in_stock: state.inventory === null ? undefined : state.inventory
		}).then(setProducts);
	}
	function diffState() {
		let diff = {};
		for(const key in state) {
			if(Array.isArray(state[key])) {
				if(state[key].length) {
					diff[key] = [...state[key]];
				}
			} else if(typeof state[key] === 'object') {
				//
			} else if(state[key] !== original[key]) {
				diff[key] = state[key];
			}
		}
		let producers = {};
		let yes = false;
		for(const p in state.producers) {
			let yesyes = false;
			let obj = {};
			if(state.producers[p].checked) {
				obj.checked = true;
				yesyes = true;
			}
			if(state.producers[p].brands.length) {
				obj.brands = [...state.producers[p].brands];
				yesyes = true;
			}
			if(yesyes) {
				producers[p] = obj;
				yes = true;
			}
		}
		if(yes) {
			diff.producers = producers;
		}
		return diff;
	}
	return <>
		<Show when={glo.user?.god && props.sid === undefined}>
			<a onClick={c} href={'edit'}>⚙</a>
		</Show>
		<Show when={f()}>
			<form onsubmit={e => {
				e.preventDefault();
				lol()
				let diff = JSON.parse(JSON.stringify(history.state.america));
				if(diff.producers) {
					let a = [];
					for(const key in diff.producers) {
						if(diff.producers[key].checked) {
							a.push(key);
						}
						if(diff.producers[key].brands?.length) {
							diff['p_' + key] = diff.producers[key].brands.join('_');
						}
					}
					diff.producers = a.join('_');
					if(!diff.producers) {
						delete diff.producers;
					}
				}
				for(const key in diff) {
					if(Array.isArray(diff[key])) {
						diff[key] = diff[key].join('_');
					}
				}
				diff = new URLSearchParams(diff).toString();
				if(diff.length) {
					diff = '?' + diff;
				}
				history.replaceState(history.state, "", location.href.split('?')[0] + diff);
			}}>
				<label>
					search
					<input type="search" value={state.search} onInput={e => setState('search', e.target.value)} />
				</label><br />
				<label>
					sort by
					<select value={state.sort} onChange={e => setState('sort', e.target.value)}>
						<option>unsorted</option>
						<option>price ascending</option>
						<option>price descending</option>
						<option disabled={!canSortByPrice_g()} title={canSortByPrice_g() ? '' : 'sorting by price / g only makes sense for inhalation products'} value="price_g ascending">minimum price / g ascending</option>
						<option disabled={!canSortByPrice_g()} title={canSortByPrice_g() ? '' : 'sorting by price / g only makes sense for inhalation products'} value="price_g descending">minimum price / g descending</option>
						<option disabled={!canSortByConcentration()} title={canSortByConcentration() ? '' : 'sorting by concentration only makes sense for products within a consumption method'}>THC ascending</option>
						<option disabled={!canSortByConcentration()} title={canSortByConcentration() ? '' : 'sorting by concentration only makes sense for products within a consumption method'}>THC descending</option>
						<option disabled={!canSortByConcentration()} title={canSortByConcentration() ? '' : 'sorting by concentration only makes sense for products within a consumption method'}>CBD ascending</option>
						<option disabled={!canSortByConcentration()} title={canSortByConcentration() ? '' : 'sorting by concentration only makes sense for products within a consumption method'}>CBD descending</option>
						<option>producer a-z</option>
						<option>producer z-a</option>
						<option>brand a-z</option>
						<option>brand z-a</option>
						<option>name a-z</option>
						<option>name z-a</option>
					</select>
				</label><br />
				<fieldset>
					<legend>inventory</legend>
					<label><input type="radio" name="inventory" checked={state.inventory === null} onChange={inventoryRadio} value="e" />everything</label><br />
					<label><input type="radio" name="inventory" checked={state.inventory} onChange={inventoryRadio} value="t" />in stock</label><br />
					<label><input type="radio" name="inventory" checked={state.inventory === false} onChange={inventoryRadio} value="f" />out of stock</label><br />
				</fieldset>
				<fieldset>
					<legend>species</legend>
					<For each={f().species}>{s => <>
						<label><input type="checkbox" checked={state.species.includes(s)} onChange={e => {
							if(e.target.checked) {
								setState('species', [s, ...state.species]);
							} else {
								setState('species', t => t.filter(sp => sp !== s));
							}
						}} />{s}</label><br />
					</>}</For>
				</fieldset>
				<fieldset>
					<legend>formats</legend>
					<For each={f().product_types}>{s => <>
						<Switch>
							<Match when={s === 'flower'}>Inhalation<br/></Match>
							<Match when={s === 'oil'}>Subligual<br/></Match>
							<Match when={s === 'capsule'}>Edible<br/></Match>
						</Switch>
						<label><input type="checkbox" checked={state.types.includes(s)} onChange={e => {
							if(e.target.checked) {
								setState('types', [s, ...state.types]);
							} else {
								setState('types', t => t.filter(typ => typ !== s));
							}
						}} />{s}</label><br />
					</>}</For>
				</fieldset>
				<fieldset>
					<legend>strains</legend>
					<div style="height: 300px; overflow-y: auto">
						<For each={f().strains}>{s => <>
							<label><input type="checkbox" checked={state.strains.includes(s.id)} onChange={e => {
								if(e.target.checked) {
									setState('strains', [s.id, ...state.strains]);
								} else {
									setState('strains', t => t.filter(typ => typ !== s.id));
								}
							}} />{s.name}</label><br />
						</>}</For>
					</div>
				</fieldset>
				<fieldset>
					<legend>producers and brands</legend>
					<ul style="padding: 0; margin: 0; max-height: 300px; overflow-y: auto"><For each={f().idk}>{s => <li>
						<label><input type="checkbox" checked={state.producers[s.producer].checked} onChange={e => setState('producers', s.producer, 'checked', e.target.checked)} />{s.producer === null ? 'unknown' : s.producer}</label>
						<Show when={s.brands.length > 1 || s.brands[0] !== ''}><ul>
							<For each={s.brands}>{ss => <li>
								<label><input disabled={state.producers[s.producer].checked} type="checkbox" checked={state.producers[s.producer].brands.includes(ss)} onChange={e => {
									if(e.target.checked) {
										setState('producers', s.producer, 'brands', [ss, ...state.producers[s.producer].brands]);
									} else {
										setState('producers', s.producer, 'brands', b => b.filter(br => br !== ss));
									}
								}} />{ss === '' ? s.producer : ss}</label>
							</li>}</For>
						</ul></Show>
					</li>}</For></ul>
				</fieldset>
				<fieldset>
					<legend>THC : total cannabinoids</legend>
					<label>min <input type="number" step="any" min="0" max={state.max_thc2tc} value={state.min_thc2tc} onInput={e => setState('min_thc2tc', e.target.value)} /></label>
					<label>max <input type="number" step="any" min={state.min_thc2tc} max="1" value={state.max_thc2tc} onInput={e => setState('max_thc2tc', e.target.value)} /></label>
				</fieldset>
				<br />
				<button>search</button>
			</form>
		</Show>
		<div>{products() && products().length}</div>
		<div class="grid">
			<For each={products()}>{p => <div class="c card">
				<div class="front">
					<a onClick={c} href={p.product_id + (p.name ? '-' : '') + p.name.replace(/\s+/g, '-') + (p.variant_ids === null ? '' : '?recommended_variants=' + p.variant_ids.join('_'))}>
						{fmt(p.producer, p.brand, p.name)}
					</a>
					<img style="width: 100%; height: auto;" width={p.x} height={p.y} src={p.image} loading="lazy" />
					{p.type}<br />
					{p.species}<br />
					{p.strain}<br />
					THC: {pgRange2String(p.thc, p.type, p.min_portions, p.max_portions)}<br />
					CBD: {pgRange2String(p.cbd, p.type, p.min_portions, p.max_portions)}<br />
					starting from ${p.min_price}{p.min_price_g ? `, ${p.min_price_g} / g` : ''}<br />
					<Switch fallback={p.terpenes.slice(1, -1).split(',').join(', ')}>
						<Match when={p.terpenes === null}>unknown terpenes</Match>
						<Match when={p.terpenes.length === 0}>terpenes removed</Match>
					</Switch><br />
				</div>
				<div class="back">
					shit can go here
					eventually need https://github.com/ryansolid/solid/tree/master/packages/solid-rx if we want click instead of hover
				</div>
			</div>}</For>
		</div>
	</>
}