import { useDeviceId } from "@/shared/hooks/use-device-id"
import { useFollows } from "@/shared/hooks/use-follows"
import { usePush } from "@/shared/hooks/use-push"
import { usePwaUpdate } from "@/shared/hooks/use-pwa-update"
import { fetchTopics } from "@/shared/lib/aw-api"
import { BACKEND_URL, VAPID_PUBLIC_KEY } from "@/shared/lib/constants"
import { BlockTitle, Button, List, ListItem, Navbar, Preloader, Toggle } from "konsta/react"
import { useCallback, useEffect, useState } from "react"
import { type GeoResult, clearGeoCache, detectFromCoords, loadCachedResult } from "../../location/lib/geo"
import { NotificationGuide } from "./notification-guide"

function formatCacheAge(cachedAt: number): string {
	const minutes = Math.floor((Date.now() - cachedAt) / 60_000)
	if (minutes < 1) return "gerade eben"
	if (minutes < 60) return `vor ${minutes} Min.`
	const hours = Math.floor(minutes / 60)
	if (hours < 24) return `vor ${hours} Std.`
	const days = Math.floor(hours / 24)
	return `vor ${days} T.`
}

function isStandalone(): boolean {
	if (typeof window === "undefined") return false
	return (
		window.matchMedia("(display-mode: standalone)").matches ||
		("standalone" in navigator && (navigator as { standalone?: boolean }).standalone === true)
	)
}

export function SettingsPage() {
	const deviceId = useDeviceId()
	const { needRefresh, checkForUpdate, applyUpdate } = usePwaUpdate()
	const push = usePush()
	const { follow } = useFollows()
	const [checking, setChecking] = useState(false)
	const [loading, setLoading] = useState(false)
	const [result, setResult] = useState<GeoResult | null>(null)
	const [errorMsg, setErrorMsg] = useState<string | null>(null)
	const [showGuide, setShowGuide] = useState(false)
	const [devHealth, setDevHealth] = useState<string | null>(null)
	const [devPush, setDevPush] = useState<string | null>(null)
	const [devTopics, setDevTopics] = useState<string | null>(null)
	const [devPoliticians, setDevPoliticians] = useState<string | null>(null)

	useEffect(() => {
		const cached = loadCachedResult()
		if (cached) setResult(cached)
	}, [])

	const detect = useCallback((skipCache: boolean) => {
		if (!navigator.geolocation) {
			setErrorMsg("Standortbestimmung wird nicht unterstützt")
			return
		}
		setLoading(true)
		setErrorMsg(null)
		navigator.geolocation.getCurrentPosition(
			async (pos) => {
				try {
					const r = await detectFromCoords(pos.coords.latitude, pos.coords.longitude, skipCache)
					setResult(r)
				} catch (e) {
					setErrorMsg(String(e))
				} finally {
					setLoading(false)
				}
			},
			(err) => {
				setErrorMsg(err.message)
				setLoading(false)
			},
		)
	}, [])

	function handleClearCache() {
		clearGeoCache()
		setResult(null)
	}

	async function handleCheckUpdate() {
		setChecking(true)
		try {
			await checkForUpdate()
		} finally {
			setChecking(false)
		}
	}

	const hasLocation = result && result.mandates.length > 0
	const standalone = isStandalone()

	if (showGuide) {
		return <NotificationGuide onBack={() => setShowGuide(false)} />
	}

	return (
		<div className="pb-20">
			<Navbar title="Einstellungen" />

			{/* --- Notifications --- */}
			{VAPID_PUBLIC_KEY && (
				<>
					<BlockTitle>Benachrichtigungen</BlockTitle>
					<List inset strong>
						{push.permission === "denied" ? (
							<ListItem
								title={
									<span className="text-red-500">
										Benachrichtigungen sind blockiert. Bitte in den Systemeinstellungen aktivieren.
									</span>
								}
							/>
						) : (
							<ListItem
								label
								title="Push-Benachrichtigungen"
								after={
									<Toggle
										checked={push.subscribed}
										disabled={push.loading}
										onChange={() => {
											if (push.subscribed) push.unsubscribe()
											else push.subscribe()
										}}
									/>
								}
							/>
						)}
						{!standalone && <ListItem link title="Einrichtung auf dem iPhone" onClick={() => setShowGuide(true)} />}
					</List>
				</>
			)}

			{/* --- Location --- */}
			<BlockTitle>Standort</BlockTitle>
			{hasLocation && result.bundesland ? (
				<List inset strong>
					<ListItem title="Bundesland" after={result.bundesland} />
					{result.landtag_label && <ListItem title="Landtag" after={result.landtag_label} />}
					<ListItem title="Abgeordnete geladen" after={String(result.mandates.length)} />
					{result.cachedAt && <ListItem title="Zwischengespeichert" after={formatCacheAge(result.cachedAt)} />}
				</List>
			) : null}

			{loading && (
				<div className="flex items-center justify-center h-16 mb-3">
					<Preloader />
					<span className="ml-3 text-sm text-black/55 dark:text-white/55">
						{hasLocation ? "Aktualisiere…" : "Erkenne…"}
					</span>
				</div>
			)}

			{errorMsg && (
				<div className="mx-4 mb-3 p-3 bg-red-500/10 rounded-lg text-red-500 text-sm" role="alert">
					{errorMsg}
				</div>
			)}

			<div className="flex flex-col gap-2 px-4">
				{!hasLocation && !loading && (
					<Button large onClick={() => detect(false)}>
						Standort erkennen
					</Button>
				)}
				{hasLocation && (
					<>
						<Button small outline onClick={() => detect(true)} disabled={loading}>
							Abgeordnete neu laden
						</Button>
						<Button small outline onClick={handleClearCache} disabled={loading}>
							Cache löschen
						</Button>
					</>
				)}
			</div>

			{/* --- App Update --- */}
			<BlockTitle className="mt-8">App-Update</BlockTitle>
			<List inset strong>
				{needRefresh ? (
					<ListItem
						title="Neue Version verfügbar"
						after={
							<Button small onClick={applyUpdate}>
								Jetzt aktualisieren
							</Button>
						}
					/>
				) : (
					<ListItem
						title="App ist aktuell"
						after={
							<Button small outline onClick={handleCheckUpdate} disabled={checking}>
								{checking ? "Prüfe…" : "Prüfen"}
							</Button>
						}
					/>
				)}
			</List>

			{/* --- About --- */}
			<BlockTitle>Info</BlockTitle>
			<List inset strong>
				<ListItem
					title="Datenquelle"
					after={
						<a
							href="https://www.abgeordnetenwatch.de"
							target="_blank"
							rel="noopener noreferrer"
							className="text-primary"
						>
							abgeordnetenwatch.de
						</a>
					}
				/>
				<ListItem
					title="Geräte-ID"
					after={<span className="font-mono text-xs max-w-[50%] truncate">{deviceId}</span>}
				/>
			</List>

			{/* --- Developer --- */}
			<BlockTitle>Entwickler</BlockTitle>
			<List inset strong>
				<ListItem
					title="Backend Health"
					after={
						<div className="flex items-center gap-2">
							{devHealth && (
								<span className={`text-xs ${devHealth === "ok" ? "text-green-600" : "text-red-500"}`}>{devHealth}</span>
							)}
							<Button
								small
								outline
								onClick={async () => {
									setDevHealth(null)
									try {
										const res = await fetch(`${BACKEND_URL}/health`)
										setDevHealth(res.ok ? "ok" : `${res.status}`)
									} catch (e) {
										setDevHealth(String(e))
									}
								}}
							>
								Prüfen
							</Button>
						</div>
					}
				/>
				<ListItem
					title="Test-Push"
					after={
						<div className="flex items-center gap-2">
							{devPush && (
								<span className={`text-xs ${devPush === "ok" ? "text-green-600" : "text-red-500"}`}>{devPush}</span>
							)}
							<Button
								small
								outline
								onClick={async () => {
									setDevPush(null)
									try {
										const res = await fetch(`${BACKEND_URL}/push/test`, {
											method: "POST",
											headers: { "Content-Type": "application/json" },
											body: JSON.stringify({ device_id: deviceId }),
										})
										setDevPush(res.ok ? "ok" : `${res.status}`)
									} catch (e) {
										setDevPush(String(e))
									}
								}}
							>
								Senden
							</Button>
						</div>
					}
				/>
				<ListItem
					title="Alle Themen folgen"
					after={
						<div className="flex items-center gap-2">
							{devTopics && <span className="text-xs text-green-600">{devTopics}</span>}
							<Button
								small
								outline
								onClick={async () => {
									setDevTopics(null)
									try {
										const topics = await fetchTopics()
										for (const t of topics) follow("topic", t.id, t.label)
										setDevTopics(`${topics.length}`)
									} catch (e) {
										setDevTopics(String(e))
									}
								}}
							>
								Folgen
							</Button>
						</div>
					}
				/>
				<ListItem
					title="Alle Abgeordnete folgen"
					after={
						<div className="flex items-center gap-2">
							{devPoliticians && <span className="text-xs text-green-600">{devPoliticians}</span>}
							<Button
								small
								outline
								onClick={() => {
									setDevPoliticians(null)
									const cached = loadCachedResult()
									if (!cached || cached.mandates.length === 0) {
										setDevPoliticians("Kein Standort-Cache")
										return
									}
									for (const m of cached.mandates) {
										follow("politician", m.politician.id, m.politician.label)
									}
									setDevPoliticians(`${cached.mandates.length}`)
								}}
							>
								Folgen
							</Button>
						</div>
					}
				/>
			</List>
		</div>
	)
}
