import type { ResultSetHeader, RowDataPacket } from 'mysql2';
import { DEFAULT_LANDING_KONTEN } from '$lib/constants/landing-defaults';
import type { LandingContent, LandingItem, LandingItemInput, LandingItemTipe } from '$lib/types/landing';
import db from '$lib/server/db';

interface KontenRow extends RowDataPacket {
	kunci: string;
	nilai: string;
}

interface ItemRow extends RowDataPacket, LandingItem {
	is_aktif: number;
}

const ITEM_TIPES: LandingItemTipe[] = ['feature', 'step', 'faq', 'stat', 'mobile_highlight'];

function mapItem(row: ItemRow): LandingItem {
	return {
		id: row.id,
		tipe: row.tipe,
		urutan: row.urutan,
		judul: row.judul,
		deskripsi: row.deskripsi,
		icon: row.icon,
		warna: row.warna,
		is_aktif: Boolean(row.is_aktif)
	};
}

function emptyItemGroups(): Record<LandingItemTipe, LandingItem[]> {
	return {
		feature: [],
		step: [],
		faq: [],
		stat: [],
		mobile_highlight: []
	};
}

export async function getLandingKontenMap(): Promise<Record<string, string>> {
	const [rows] = await db.query<KontenRow[]>('SELECT kunci, nilai FROM landing_konten');
	const konten: Record<string, string> = { ...DEFAULT_LANDING_KONTEN };

	for (const row of rows) {
		konten[row.kunci] = row.nilai;
	}

	return konten;
}

export async function getLandingItems(aktifOnly = true): Promise<LandingItem[]> {
	const where = aktifOnly ? 'WHERE is_aktif = 1' : '';
	const [rows] = await db.query<ItemRow[]>(
		`SELECT id, tipe, urutan, judul, deskripsi, icon, warna, is_aktif
		 FROM landing_item ${where}
		 ORDER BY tipe, urutan, id`
	);

	return rows.map(mapItem);
}

function groupItems(items: LandingItem[]): Record<LandingItemTipe, LandingItem[]> {
	const grouped = emptyItemGroups();
	for (const item of items) {
		grouped[item.tipe].push(item);
	}
	return grouped;
}

export async function getLandingContent(): Promise<LandingContent> {
	const [konten, items] = await Promise.all([getLandingKontenMap(), getLandingItems(true)]);

	return {
		konten,
		items: groupItems(items)
	};
}

export async function updateLandingKontenBulk(
	updates: Record<string, string>
): Promise<boolean> {
	if (Object.keys(updates).length === 0) return true;

	const entries = Object.entries(updates).map(([kunci, nilai]) => [kunci, nilai.trim()]);

	for (const [kunci, nilai] of entries) {
		await db.query(
			`INSERT INTO landing_konten (kunci, nilai)
			 VALUES (?, ?)
			 ON DUPLICATE KEY UPDATE nilai = VALUES(nilai)`,
			[kunci, nilai]
		);
	}

	return true;
}

export async function saveLandingItem(input: LandingItemInput & { id?: number }): Promise<number | null> {
	const judul = input.judul.trim();
	if (!judul || !ITEM_TIPES.includes(input.tipe)) return null;

	const payload = [
		input.tipe,
		input.urutan,
		judul,
		input.deskripsi?.trim() || null,
		input.icon?.trim() || null,
		input.warna?.trim() || null,
		input.is_aktif === false ? 0 : 1
	];

	if (input.id) {
		const [result] = await db.query<ResultSetHeader>(
			`UPDATE landing_item
			 SET tipe = ?, urutan = ?, judul = ?, deskripsi = ?, icon = ?, warna = ?, is_aktif = ?
			 WHERE id = ?`,
			[...payload, input.id]
		);
		return result.affectedRows > 0 ? input.id : null;
	}

	const [result] = await db.query<ResultSetHeader>(
		`INSERT INTO landing_item (tipe, urutan, judul, deskripsi, icon, warna, is_aktif)
		 VALUES (?, ?, ?, ?, ?, ?, ?)`,
		payload
	);

	return result.insertId || null;
}

export async function deleteLandingItem(id: number): Promise<boolean> {
	const [result] = await db.query<ResultSetHeader>('DELETE FROM landing_item WHERE id = ?', [id]);
	return result.affectedRows > 0;
}

export async function toggleLandingItem(id: number, isAktif: boolean): Promise<boolean> {
	const [result] = await db.query<ResultSetHeader>(
		'UPDATE landing_item SET is_aktif = ? WHERE id = ?',
		[isAktif ? 1 : 0, id]
	);
	return result.affectedRows > 0;
}
