const apiKey = document.querySelector('#api-key') as HTMLInputElement;
{
	const storedApiKey = localStorage.getItem('fio-api-key');
	if (storedApiKey)
		apiKey.value = storedApiKey;
}
document.querySelector('#fetch')!.addEventListener('click', async () => {
	const loader = document.querySelector('#loader') as HTMLElement;
	loader.style.display = 'block';
	try {
		await renderLedger(apiKey.value);
		localStorage.setItem('fio-api-key', apiKey.value);
	} catch (e) {
		console.error(e);
	}
	loader.style.display = 'none';
});

async function getPrices(): Promise<Record<string, number | null>> {
	const allPrices: Price[] = await fetchJSON('https://refined-prun.github.io/refined-prices/all.json');
	const priceMap: Record<string, number | null> = {};
	for (const price of allPrices)
		if (price.ExchangeCode === 'IC1')
			priceMap[price.MaterialTicker] = price.VWAP30D;
	return priceMap;
}
const pricePromise = getPrices();

const ledger = document.querySelector('textarea#ledger') as HTMLTextAreaElement;
async function renderLedger(apiKey: string): Promise<void> {
	ledger.style.display = 'none';
	ledger.value = 'Time,Mat,Quantity,Actual Unit Price,Discounted Unit Price,Gateway,Debit,Credit,Contract ID\n';

	const prices = await pricePromise;
	const contracts: Contract[] = await fetchJSON('https://rest.fnar.net/contract/allcontracts',
			{headers: {'Authorization': apiKey}});
	contracts.sort((a, b) => a.DateEpochMs - b.DateEpochMs);
	for (const contract of contracts) {
		if (contract.PartnerCompanyCode === null || contract.PartnerName.endsWith(' Commodity Exchange')) continue; // NPC contract
		contract.Conditions.sort((a, b) => a.ConditionIndex - b.ConditionIndex);
		for (let i = 0; i < contract.Conditions.length; i++) {
			const condition = contract.Conditions[i];
			if ((contract.Party !== condition.Party && condition.Type === 'DELIVERY') || // counterparty is delivering
					(contract.Party === condition.Party && condition.Type === 'COMEX_PURCHASE_PICKUP')) { // we are picking up
				const time = new Date(contract.DateEpochMs).toISOString();
				const mat = condition.MaterialTicker;
				const quantity = condition.MaterialAmount;
				const totalPrice = contract.Conditions[i-1].Amount;
				ledger.value += `${time},${mat},${quantity},${prices[mat]},${totalPrice / quantity},,${totalPrice},,${contract.ContractLocalId}\n`;
			} else
				continue;
		}
	}

	ledger.style.display = 'block';
}

document.querySelector('#copy')!.addEventListener('click', () => {
	navigator.clipboard.writeText(ledger.value);
});

async function fetchJSON(url: string, options: RequestInit = {}): Promise<any> {
	const controller = new AbortController();
	const timeoutId = setTimeout(() => controller.abort(), 5000);
	const doc = await fetch(url, {...options, signal: controller.signal}).then((r) => r.json());
	clearTimeout(timeoutId);
	return doc;
}

interface Contract {
	Conditions: Array<ContractCondition>;
	ContractLocalId: string;
	Party: string;
	Status: string;
	PartnerName: string;
	PartnerCompanyCode: string;
	DateEpochMs: number;
}

interface ContractCondition {
	ConditionIndex: number;
	Type: string;
	Party: string;
	MaterialTicker: string;
	MaterialAmount: number;
	Amount: number;
	Currency: string;
}

interface Price {
	MaterialTicker: string
	ExchangeCode: string
	VWAP30D: number | null
}
