document.addEventListener('alpine:init', () => {
	Alpine.data("dashboard", () => ({
		// dashboard
		today: "",
		filter: { date1: "", date2: "" },
		list: [],
		isLoading: false,
		counters: { Pend: 0, Coll: 0, Recv: 0, Inc: 0, Fin: 0, Total: 0 },
		retryingPdf: {},
		statusColor: {
			Pend: 'bg-white text-black font-bold',
			PartColl: 'bg-[#ff99aa] text-black font-bold',
			Coll: 'bg-[#d63031] text-white font-bold',
			PartRecv: 'bg-[#a0c0d9] text-black font-bold',
			Recv: 'bg-[#0984e3] text-white font-bold',
			Inc: 'bg-[#ffff00] text-black font-bold',
			Fin: 'bg-[#008000] text-white font-bold',
		},
		statusRowBg: {
			Pend: 'bg-white text-black',
			PartColl: 'bg-[#ff99aa] text-black',
			Coll: 'bg-[#d63031] text-white',
			PartRecv: 'bg-[#a0c0d9] text-black',
			Recv: 'bg-[#0984e3] text-white',
			Inc: 'bg-[#ffff00] text-black',
			Fin: 'bg-[#008000] text-white',
		},
		filterTable: "",
		filterKey: 'Total',
		statusMap: {
			Total: [],
			Pend: ['Pend'],
			Coll: ['Coll', 'PartColl'],
			Recv: ['Recv', 'PartRecv'],
			Inc: ['Inc'],
			Fin: ['Fin'],
		},

		// Sorting & Pagination
		sortCol: 'REQDATE',
		sortAsc: false,
		currentPage: 1,
		pageSize: 30,

		sort(col) {
			if (this.sortCol === col) {
				this.sortAsc = !this.sortAsc;
			} else {
				this.sortCol = col;
				this.sortAsc = true;
			}
		},

		nextPage() {
			if (this.currentPage < this.totalPages) this.currentPage++;
		},

		prevPage() {
			if (this.currentPage > 1) this.currentPage--;
		},

		get totalPages() {
			return Math.ceil(this.filtered.length / this.pageSize) || 1;
		},

		get sorted() {
			return this.filtered.slice().sort((a, b) => {
				let modifier = this.sortAsc ? 1 : -1;
				if (a[this.sortCol] < b[this.sortCol]) return -1 * modifier;
				if (a[this.sortCol] > b[this.sortCol]) return 1 * modifier;
				return 0;
			});
		},

		get paginated() {
			const start = (this.currentPage - 1) * this.pageSize;
			const end = start + this.pageSize;
			return this.sorted.slice(start, end);
		},

		init() {
			this.today = new Date().toISOString().slice(0, 10);

			// Production: default to today
			this.filter.date1 = this.today;
			this.filter.date2 = this.today;		

			this.$watch('filterTable', () => {
				this.currentPage = 1;
			});
			this.fetchList();
		},

		fetchList() {
			this.isLoading = true;
			this.list = [];
			let statusOrder = { Pend: 1, PartColl: 2, Coll: 3, PartRecv: 4, Recv: 5, Inc: 6, Fin: 7 };
			let param = new URLSearchParams(this.filter).toString();
			for (let k in this.counters) { this.counters[k] = 0; }
			fetch(`${BASEURL}/api/requests?${param}`, {
				method: 'GET',
				headers: { 'Content-Type': 'application/json' },
			}).then(res => res.json()).then(data => {
				this.list = data.data ?? [];
				this.filterKey = 'Total';
				this.list.forEach(item => {
					if (this.counters[item.STATS] !== undefined) { this.counters[item.STATS]++; this.counters.Total++; }
					else {
						if (item.STATS == 'PartColl') { this.counters.Coll++; }
						else if (item.STATS == 'PartRecv') { this.counters.Recv++; }
						this.counters.Total++;
					}
				});
				this.list.sort((a, b) => {
					let codeA = statusOrder[a.STATS] ?? 0;
					let codeB = statusOrder[b.STATS] ?? 0;
					return codeA - codeB;
				});
			}).finally(() => {
				this.isLoading = false;
			});
		},

		reset() {
			this.filter.date1 = this.today;
			this.filter.date2 = this.today;
			this.fetchList();
		},

		isValidated(item) {
			return item.ISVAL == 1 && item.ISPENDING != 1;
		},
		get filtered() {
			let filteredList = this.list;
			if (this.filterKey === 'Validated') {
				filteredList = filteredList.filter(item => this.isValidated(item));
			} else {
				const validStatuses = this.statusMap[this.filterKey];
				if (validStatuses.length > 0) {
					filteredList = filteredList.filter(item => validStatuses.includes(item.STATS));
				}
			}
			if (this.filterTable) {
				const searchTerm = this.filterTable.toLowerCase();
				filteredList = filteredList.filter(item =>
					Object.values(item).some(value =>
						String(value).toLowerCase().includes(searchTerm)
					)
				);
			}
			return filteredList;
		},
		get validatedCount() {
			return this.list.filter(r => this.isValidated(r)).length;
		},

		/*
		sample dialog
		*/
		item: '',
		isDialogSampleOpen: false,
		isSampleLoading: false,

		openSampleDialog(accessnumber) {
			this.isDialogSampleOpen = true;
			this.fetchItem(accessnumber)
		},

		closeSampleDialog() {
			this.isDialogSampleOpen = false;
		},

		fetchItem(accessnumber) {
			this.isSampleLoading = true;
			this.item = [];
			fetch(`${BASEURL}/api/samples/${accessnumber}`, { method: 'GET', headers: { 'Content-Type': 'application/json' } })
				.then(res => res.json()).then(data => {
					this.item = data.data ?? {};
					if (!Array.isArray(this.item.samples)) this.item.samples = [];
				}).finally(() => {
					this.isSampleLoading = false;
				});
		},

		collect(sampcode, accessnumber) {
			fetch(`${BASEURL}/api/samples/collect/${accessnumber}`, {
				method: 'POST', headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ samplenumber: sampcode, userid: '<?= session('userid'); ?>' })
			})
				.then(res => res.json()).then(data => {
					this.fetchItem(accessnumber);
				});
		},

		unreceive(sampcode, accessnumber) {
			if (!confirm(`Unreceive sample ${sampcode} from request ${accessnumber}?`)) { return; }
			fetch(`${BASEURL}/api/samples/unreceive/${accessnumber}`, {
				method: 'POST', headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ samplenumber: sampcode, userid: '<?= session('userid'); ?>' })
			})
				.then(res => res.json()).then(data => {
					this.fetchItem(accessnumber);
				});
		},

		/*
		unvalidate dialog
		*/
		isDialogUnvalOpen: false,
		unvalReason: '',
		unvalAccessnumber: null,
		openUnvalDialog(accessnumber) {
			this.unvalReason = '';
			this.isDialogUnvalOpen = true;
			this.unvalAccessnumber = accessnumber;
		},
		unvalidate(accessnumber, userid) {
			if (!confirm(`Unvalidate request ${accessnumber}?`)) { return; }
			fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, {
				method: "DELETE",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ userid: `${userid}`, comment: this.unvalReason.trim() })
			}).then(response => {
				this.closeUnvalDialog();
				this.fetchList();
				console.log(`Unvalidate clicked for ${accessnumber}, by user ${userid}`);
			});
		},
		closeUnvalDialog() {
			this.isDialogUnvalOpen = false;
		},

		/*
		audit dialog
		*/
		isDialogAuditOpen: false,
		auditData: null,
		auditAccessnumber: null,
		auditTab: 'all',
		openAuditDialog(accessnumber) {
			this.auditAccessnumber = accessnumber;
			this.auditData = null;
			this.auditTab = 'all';
			this.isDialogAuditOpen = true;
			this.fetchAudit(accessnumber);
		},
		closeAuditDialog() {
			this.isDialogAuditOpen = false;
			this.auditData = null;
			this.auditAccessnumber = null;
		},
		fetchAudit(accessnumber) {
			fetch(`${BASEURL}/api/requests/${accessnumber}/audit`, {
				method: 'GET',
				headers: { 'Content-Type': 'application/json' }
			}).then(res => res.json()).then(data => {
				this.auditData = data.data;
			});
		},
		get getAllAuditEvents() {
			if (!this.auditData) return [];
			let events = [];
			let id = 0;
			
			this.auditData.validation.forEach(v => {
				let desc = `Validated by ${v.user}`;
				if (v.type === 'UNVAL') {
					desc = `Unvalidated by ${v.user}`;
				}
				events.push({
					id: id++,
					category: 'validation',
					type: v.type,
					description: desc,
					datetime: v.datetime,
					user: v.user,
					reason: v.reason || null
				});
			});
			
			this.auditData.sample_collection.forEach(s => {
				events.push({
					id: id++,
					category: 'sample',
					type: s.action === 'COLLECTED' ? 'COLLECT' : 'UNRECEIVE',
					description: `Tube ${s.tubenumber}: ${s.action} by ${s.user}`,
					datetime: s.datetime,
					user: s.user,
					reason: null
				});
			});

			this.auditData.tube_received?.forEach(t => {
				events.push({
					id: id++,
					category: 'receive',
					type: 'RECEIVED',
					description: `${t.sampletype} received by ${t.user}`,
					datetime: t.datetime,
					user: t.user,
					reason: null
				});
			});

			return events.sort((a, b) => {
				if (!a.datetime) return 1;
				if (!b.datetime) return -1;
				return new Date(a.datetime) - new Date(b.datetime);
			});
		},
		get getFilteredAuditEvents() {
			if (this.auditTab === 'all') return this.getAllAuditEvents;
			return this.getAllAuditEvents.filter(e => e.category === this.auditTab);
		},

		async retryPdf(accessnumber) {
			if (this.retryingPdf[accessnumber]) return;

			this.retryingPdf[accessnumber] = true;
			try {
				const res = await fetch(`${BASEURL}/report/${accessnumber}/pdf`);
				const data = await res.json();
				if (data.success) {
					this.showToast('PDF queued for generation', 'success');
				} else {
					throw new Error(data.error || 'Unknown error');
				}
			} catch (e) {
				this.showToast('PDF generation failed - try again', 'error');
			} finally {
				this.retryingPdf[accessnumber] = false;
			}
		},

		showToast(message, type = 'success') {
			const toast = document.createElement('div');
			toast.className = `alert alert-${type} fixed top-4 right-4 z-50`;
			toast.innerHTML = `<i class="fa ${type === 'error' ? 'fa-times-circle' : 'fa-check-circle'}"></i> ${message}`;
			document.body.appendChild(toast);
			setTimeout(() => toast.remove(), 2000);
		},
	}));
});
