// form/nc/nc-bank/nc-bank.js

const gridData = {}
const jsonTextData = ref('')
let id = 0 // running temp id for each row

// eslint-disable-next-line no-unused-vars
function changeTab() {
	if (rec.table !== 'bank_statement_print') {
		loadData()
	}
}

function loadData() {
	nc.setGrid(state, 'voucher', null)
	let loadTable = 'bank_statement'
	if (state.grid) {
		if (rec.table === 'bank_statement') {
			loadTable = 'bookkeeping_voucher_row'
		} else {
			loadTable = 'bookkeeping_voucher'
		}
	}
	const param = {
		name: 'form/nc/nc-bank/grid.json',
		parameter: {
			bank_statement_days_before: rec.table === 'bank_statement' ? 0 : rec.bank_statement_days_before,
			voucher_days_before: rec.table !== 'bank_statement' ? 0 : rec.voucher_days_before,
			start_date: rec.start_date,
			end_date: rec.end_date,
			account: rec.account
		},
		return: {
			grid: [
				{
					name: 'bank_statement',
					tab: 'bank_statement'
				},
				{
					name: 'bank_payment',
					tab: 'bank_payment'
				},
				{
					name: 'voucher',
					tab: loadTable
				}
			]
		}
	}
	nc.callServer(state, 'query', param, ret => {
		rec.bank_note_array = []
		compareData(ret)
		nc.grid.activateRows(state, 'bank_statement', 1)
		const area = rec.table // 'bank_statement'
		const data = state.grid[area] && state.grid[area].data
		selectGridRow(area, 1, true, data && data.length)
	})
}

function setIdAndValue(arr) {
	let idx = 0 // running sub id for each row
	arr.forEach(item => {
		id++
		item.id = id
		idx++
		item.idx = idx
		if (item.entry_date) {
			item.entry_date = item.entry_date.substring(0, 10)
		}
		if (item.start_date) {
			item.start_date = item.start_date.substring(0, 10)
		}
		if (item.end_date) {
			item.end_date = item.end_date.substring(0, 10)
		}
		if (item.record_type === 'T10' || item.record_type === 'T40') {
			let bookRec = compareBankStatement(item)
			if (!bookRec) {
				if (item.record_type === 'T40') {
					item.difference = item.balance
				} else if (typeof item.amount === 'number') {
					item.difference = item.amount
				}
			} else {
				item.voucher = bookRec.voucher_id + '-' + bookRec.row_number
				if (item.record_type === 'T40') {
					item.difference = (bookRec.book_balance - item.balance).toLocaleString('fi', { minimumFractionDigits: 2 })
				} else {
					if (bookRec.book_value - item.amount !== 0) {
						item.difference = bookRec.book_value.toLocaleString('fi', { minimumFractionDigits: 2 })
					}
				}
				bookRec.record_type = 'vr'
				if (!item.content) {
					item.content = []
				}
				item.content.unshift(bookRec)
			}
		}
		if (item.content) {
			setIdAndValue(item.content)
		}
	})
}

function selectedRecordArr(area) {
	let grid = state.grid && state.grid[area]
	if (!(grid && grid.grid && grid.grid.api)) {
		return []
	}
	let sel = grid.grid.api.getSelectedRows()
	if (sel.length > rec.max_selected_rows) {
		message.setInfo(state, `Maximum amount of rows to select is ${rec.max_selected_rows}, otherwise browser may run out of memory.`)
		return []
	}
	return sel
}

function selectAreaRow(area, findDate, data) {
	for (let idx = 0; idx < data.length; idx++) {
		if (area == 'voucher' && data[idx].bkv && findDate <= data[idx].bkv.target_date) {
			nc.grid.activateRows(state, area, idx + 1)
			break
		} else if (area == 'bank_statement' && findDate <= data[idx].start_date) {
			nc.grid.activateRows(state, area, idx + 1)
			break
		} else if (area == 'bank_payment' && findDate <= data[idx].start_date) {
			// data[idx].bankm.start_date
			nc.grid.activateRows(state, area, idx + 1)
			break
		}
	}
}

// eslint-disable-next-line no-unused-vars
function gridRowClicked(area, arrIndex, event, selected) {
	// userSelected = 1
	// rec.bank_note_array = []
	selectGridRow(area, arrIndex, selected)
}

// function selectGridRow(area, rowIndex, selected, dataArr) {
// 	const arr = dataArr || selectedRecordArr(area)
function selectGridRow(area, rowIndex, selected, arrSize) {
	if (!state.grid.voucher?.data) {
		return
	}
	let arr
	if (!arrSize) {
		arr = selectedRecordArr(area)
	} else {
		const data = state.grid[area] && state.grid[area].data
		if (!data) {
			return
		}
		if (arrSize > data.length) {
			arrSize = data.length
		}
		arr = []
		for (let idx = 0; idx < arrSize; idx++) {
			arr[idx] = data[idx]
		}
	}
	if (selected && arr.length < 1) {
		nc.setRec(state, 'bankm', {})
		return
	}
	if (selected && area === 'bank_statement') {
		selectAreaRow('voucher', arr[0].start_date, state.grid.voucher.data)
		selectAreaRow('bank_payment', arr[0].start_date, state.grid.bank_payment.data)
		if (arrSize) {
			const bankNoteArr = rec.bank_note_array
			if (arr.length < bankNoteArr.length) {
				bankNoteArr.length = arr.length
			}
			for (let idx = bankNoteArr.length; idx < arr.length; idx++) {
				bankNoteArr[idx] = JSON.parse(arr[idx].json_data)
			}
			gridData.bookStartIdx = 0
			state.grid.voucher.data.forEach(item => {
				item.bank_statement_id = undefined
			})
			setIdAndValue(bankNoteArr)
			for (let idx = 0; idx < arr.length; idx++) {
				if (bankNoteArr[idx].content && bankNoteArr[idx].content.length > 0) {
					arr[idx].difference = bankNoteArr[idx].content[bankNoteArr[idx].content.length - 1].difference
				}
			}
		}
		let date
		const voucherDateArr = {}
		state.grid.voucher.data.forEach(item => {
			date = item.bkv.target_date
			if (!voucherDateArr[date]) {
				voucherDateArr[date] = []
			}
			item.record_type = 'vr'
			voucherDateArr[date].push(item)
		})
		// jsonTextData.value = JSON.stringify(bankNoteArr[0], null, 2)
		const data = state.grid.bank_statement.data.length > 0 ? JSON.parse(state.grid.bank_statement.data[rowIndex - 1].json_data) : []
		jsonTextData.value = JSON.stringify(data, null, 2)
		nc.setRec(state, 'bankm', arr[0])
		nc.setRec(state, 'voucherDateArr', voucherDateArr)
		nc.grid.redrawRows(state, area) // refresh difference variable
		// nc.setRec(state, 'start_date', arr[0].start_date)
		// nc.setRec(state, 'end_date', arr[arr.length - 1].end_date)
	} else if (!selected && area === 'bank_statement') {
		nc.setRec(state, 'bankm', {})
	} else if (selected && area === 'bank_payment') {
		const data = JSON.parse(state.grid.bank_payment.data[rowIndex - 1].json_data)
		jsonTextData.value = JSON.stringify(data, null, 2)
		selectAreaRow('bank_statement', arr[0].start_date, state.grid.bank_statement.data)
		selectAreaRow('voucher', arr[0].start_date, state.grid.voucher.data)
	} else if (selected) {
		// voucher and voucher row do not have json_data
		selectAreaRow('bank_statement', arr[0].bkv.target_date, state.grid.bank_statement.data)
		selectAreaRow('bank_payment', arr[0].bkv.target_date, state.grid.bank_payment.data)
		nc.setRec(state, 'bkv', arr[0].bkv)
	} else if (!selected) {
		nc.setRec(state, 'bkv', {})
	}
}

function compareBankStatement(bankRec) {
	let date, sum
	date = bankRec.entry_date
	if (bankRec.record_type === 'T40') {
		sum = bankRec.balance
	} else {
		sum = bankRec.amount
	}
	let bookArr = state.grid.voucher.data
	if (!bookArr) {
		return
	}
	// all arrays are sorted by date, we can go only forward in dates so it is good to use prevIdx
	let item, itemDate
	for (let idx = gridData.bookStartIdx; idx < bookArr.length; idx++) {
		item = bookArr[idx]
		itemDate = item.bkv.target_date
		if (itemDate === date) {
			if (bankRec.record_type === 'T40') {
				gridData.bookStartIdx = idx
			}
			while (idx < bookArr.length && bookArr[idx].bkv.target_date === date) {
				if (bankRec.record_type === 'T40') {
					if (bookArr[idx].book_balance === sum) {
						item = bookArr[idx]
						return item
					}
				} else if (bookArr[idx].book_value === sum) {
					item = bookArr[idx]
					if (item.bank_statement_id == null) {
						item.bank_statement_id = bankRec.id
						return item
					}
				}
				idx++
			}
			if (bankRec.record_type === 'T40') {
				return item // return last found
			}
			return
		} else if (itemDate > date) {
			if (idx > 0) {
				if (bankRec.record_type === 'T40') {
					gridData.bookStartIdx = idx - 1
				}
			}
			if (bankRec.record_type === 'T40') {
				return item // return last found
			}
			return // break loop, we are over asked date
		}
	}
	return
}

function getBankBalance(date, sum, balance) {
	const dateBalanceArr = gridData.dateBalanceArr
	if (!dateBalanceArr) {
		return
	}
	// all arrays are sorted by date, we can go only forward in dates so it is good to use prevIdx
	let balanceItem
	for (let idx = gridData.startIdx; idx < dateBalanceArr.length; idx++) {
		balanceItem = dateBalanceArr[idx]
		if (balanceItem.date === date) {
			gridData.startIdx = idx
			while (idx < dateBalanceArr.length && dateBalanceArr[idx].date === date) {
				balanceItem = dateBalanceArr[idx]
				if (balanceItem.value === sum) {
					if (balanceItem.balance == balance) {
						// gridData.startIdx = idx + 1
						return balanceItem
					}
				} else if (balanceItem.balance === balance) {
					return balanceItem
				}
				idx++
			}
			return balanceItem
		} else if (balanceItem.date > date) {
			if (idx > 0) {
				gridData.startIdx = idx - 1
				return dateBalanceArr[gridData.startIdx] // break loop, we are over asked date
			}
			return
		}
	}
	return
}
function compareData(ret) {
	if (ret.grid && ret.grid.voucher) {
		let item, prevItem, data
		if (ret.grid.bank_statement) {
			data = ret.grid.bank_statement.data
			const dateBalanceArr = []
			let totalStatementCount = 0
			let statementIdx = 0
			let errorCount = 0

			let dataChanged
			for (let idx = 0; idx < data.length; idx++) {
				dataChanged = false
				item = data[idx]
				let json = JSON.parse(item.json_data)
				if (idx === 0) {
					let date = dt.dateToString(rec.start_date)
					if (json.start_date > date) {
						json.start_date = date // must start from date range start to get all missing events before bank statements start date
						dataChanged = true
					}
				}
				const statementArr = json.content
				if (statementArr == null) {
					message.setError(state, `${++errorCount}. statementArr content is missing`)
				} else {
					let stm
					let statement_number = ''
					for (let j = 0; j < statementArr.length; j++) {
						totalStatementCount++
						stm = statementArr[j]
						stm.entry_date = stm.entry_date.substring(0, 10)
						if (stm.record_type === 'T10') {
							if (stm.event_type === 'otto' && stm.content && stm.content.length === 2 && stm.content[0].info_type === '01' && stm.content[1].info_type === '06') {
								stm.amount = '(' + stm.amount.toLocaleString('fi', { minimumFractionDigits: 2 }) + ')'
								dataChanged = true
							}
						} else if (stm.record_type === 'T40') {
							statementIdx++
							dateBalanceArr.push({
								name: item.name,
								record_type: stm.record_type + '-' + statement_number,
								dataIdx: idx,
								idx: statementIdx,
								start_date: item.start_date,
								end_date: item.end_date,
								date: stm.entry_date,
								balance: stm.balance,
								start_balance: json.start_balance,
								start_balance_date: json.start_balance_date
								// value: stm.balance
							})
						}
					}
				}
				if (dataChanged) {
					item.json_data = JSON.stringify(json)
				}
			}
			let balanceItem
			for (let idx = dateBalanceArr.length - 1; idx > 0; idx--) {
				balanceItem = dateBalanceArr[idx]
				if (balanceItem.date !== balanceItem.end_date) {
					message.setWarning(state, `${++errorCount}. bank statement date check error`)
					balanceItem.error = true
				}
				if (dateBalanceArr[idx - 1].date === balanceItem.start_date) {
					message.setWarning(state, `${++errorCount}. same balance date as previous record: ${balanceItem.start_date} - ${balanceItem.end_date}, ${balanceItem.name} `, balanceItem)
					dateBalanceArr[idx - 1].error = true
					balanceItem.error = true
				} else if (dateBalanceArr[idx - 1].date > balanceItem.start_date) {
					message.setWarning(
						state,
						`${++errorCount}. previous record balance end date is bigger than record start date: ${dateBalanceArr[idx - 1].date} / ${balanceItem.start_date}, ${balanceItem.name} `,
						balanceItem
					)
					dateBalanceArr[idx - 1].error = true
					balanceItem.error = true
				} else if (dt.addDays(dateBalanceArr[idx - 1].date, 1) < balanceItem.start_date) {
					const balanceEqual = dateBalanceArr[idx - 1].balance === balanceItem.start_balance && dateBalanceArr[idx - 1].date === balanceItem.start_balance_date
					const newRec = {
						// add to array
						error: true,
						dataIdx: balanceItem.dataIdx,
						idx: balanceEqual ? idx : idx + '-err',
						record_type: balanceEqual ? '' : 'err',
						balance: data[idx - 1].balance,
						start_date: dt.addDays(dateBalanceArr[idx - 1].date, 1),
						end_date: dt.addDays(balanceItem.start_date, -1)
					}
					if (!balanceEqual) {
						message.setWarning(state, `${++errorCount}.  missing balance dates: ${newRec.start_date} - ${newRec.end_date}, ${balanceItem.name} `, newRec)
					}
					dateBalanceArr.splice(idx, 0, newRec)
					const newBankRec = nc.clone(data[newRec.dataIdx - 1])
					newBankRec.id = newBankRec.id + '.1'
					newBankRec.start_date = newRec.start_date
					newBankRec.end_date = newRec.end_date
					// const content = []
					// const date = newRec.start_date
					// while (date < newRec.end_date) {
					// 	content.push({ record_type: 'T00' })
					// }
					const jsonData = {
						record_type: 'T00',
						account_owner: balanceEqual ? 'Tyhjä tiliote' : 'Virhe: puuttuva tiliote.',
						start_date: newRec.start_date,
						end_date: newRec.end_date,
						start_balance: newRec.balance
						// content: content
					}
					if (!balanceEqual) {
						jsonData.error = true
					}
					newBankRec.json_data = JSON.stringify(jsonData)
					data.splice(newRec.dataIdx, 0, newBankRec)
				}
			}
			// dateBalanceArr.sort(nc.dynamicSort(['date', '>', 'record_type', '>', 'value', '>', 'idx', '>']))
			gridData.dateBalanceArr = dateBalanceArr
			gridData.startIdx = 0
			gridData.totalStatementCount = totalStatementCount
		}

		const table = ret.grid.voucher.info.query_table
		gridData[table] = ret.grid.voucher.data // save loaded table grid data to ret.data
		data = gridData[table]
		if (table === 'bookkeeping_voucher') {
			for (let idx = 0; idx < data.length; idx++) {
				item = data[idx]
				if (item.json_data.debet_price !== item.json_data.kredit_price) {
					item.difference = item.json_data.debet_price - item.json_data.kredit_price
				}
			}
		} else if (table === 'bookkeeping_voucher_row') {
			// "query order by bkv.target_date does not work in 4Dv19, sort data in nc-bank.js"
			data.sort(nc.dynamicSort(['bkv.target_date', '>', 'bkv.voucher_type', '<', 'voucher_id', '>', 'row_number', '>']))
			for (let idx = 0; idx < data.length; idx++) {
				item = data[idx]
				item.book_value = item.json_data.debet_price - item.json_data.kredit_price
				if (item.bkv.voucher_type === rec.start_account_voucher_type || idx === 0) {
					item.book_balance = item.book_value
					let bankRec = getBankBalance(item.bkv.target_date, item.book_value, item.book_balance)
					if (bankRec) {
						item.bank_statement_record_type = bankRec.record_type + '.' + bankRec.idx
						item.bank_statement_value = bankRec.value
						item.bank_statement_balance = bankRec.balance
						item.bank_statement_date = bankRec.date
					}
				} else {
					prevItem = data[idx - 1]
					item.book_balance = nc.round(prevItem.book_balance + item.book_value, rec.difference_round)
					if (idx < data.length - 1) {
						let nextItem = data[idx + 1]
						if (nextItem.bkv.target_date !== item.bkv.target_date) {
							let bankRec = getBankBalance(item.bkv.target_date, item.book_value, item.book_balance)
							if (bankRec) {
								item.bank_statement_record_type = bankRec.record_type + '.' + bankRec.idx
								item.bank_statement_value = bankRec.value
								item.bank_statement_balance = bankRec.balance // prevItem.bank_statement_balance + item.bank_statement_value
								item.bank_statement_date = bankRec.date
							}
						}
					}
				}
				if (item.book_balance && item.bank_statement_balance && (item.bkv.target_date === item.bank_statement_date || item.bkv.voucher_type === 6)) {
					item.balance_difference = nc.round(item.book_balance - item.bank_statement_balance, rec.difference_round)
				}
			}
		}
		nc.setRec(state, 'bankm', {})
		nc.grid.activateRows(state, 'bank_statement', 1)
	}
}

compareData(state)
onMounted(() => {
	const area = rec.table // 'bank_statement'
	const data = state.grid[area] && state.grid[area].data
	if (data) {
		selectGridRow(area, 1, true, data.length)
	}
})
