"use client";

import { useEffect, useState, useRef } from "react";
import { importLibrary, setOptions } from "@googlemaps/js-api-loader";
import { Location } from "@prisma/client";
import { gpx } from "@tmcw/togeojson";

export default function Gallery() {
    const [locations, setLocations] = useState<Location[]>([]);
    const [filteredLocations, setFilteredLocations] = useState<Location[]>([]);
    const [selectedLocation, setSelectedLocation] = useState<Location | null>(null);
    const [search, setSearch] = useState("");
    const [viewingStreetView, setViewingStreetView] = useState(false);
    const [iframeUrl, setIframeUrl] = useState<string | null>(null);
    const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
    const [thumbnails, setThumbnails] = useState<Record<string, string>>({});
    const [toastMessage, setToastMessage] = useState<string | null>(null);
    const [totalMiles, setTotalMiles] = useState<number>(0);
    const [geometryLoaded, setGeometryLoaded] = useState(false);
    const [runtimeApiKey, setRuntimeApiKey] = useState<string>("");

    const locationsRef = useRef<Location[]>([]);

    const mapRef = useRef<HTMLDivElement>(null);
    const miniMapRef = useRef<HTMLDivElement>(null);
    const googleMapObj = useRef<google.maps.Map | null>(null);
    const miniMapObj = useRef<google.maps.Map | null>(null);
    const miniMapMarkerObj = useRef<google.maps.marker.AdvancedMarkerElement | null>(null);
    const svServiceRef = useRef<google.maps.StreetViewService | null>(null);
    const activePolylinesRef = useRef<{ id: string; polyline: google.maps.Polyline; bounds: google.maps.LatLngBounds; firstCoord: google.maps.LatLngLiteral }[]>([]);

    // Fetch runtime API key from server (GOOGLE_MAPS_API_KEY env var)
    useEffect(() => {
        fetch("/api/config")
            .then((res) => res.json())
            .then((data) => {
                if (data.apiKey) setRuntimeApiKey(data.apiKey);
            })
            .catch((err) => console.error("Error fetching config:", err));
    }, []);

    // Fetch locations
    useEffect(() => {
        const queryParams = new URLSearchParams(window.location.search);
        const initialLocId = queryParams.get("locationId");

        fetch("/api/locations")
            .then((res) => res.json())
            .then((data) => {
                if (Array.isArray(data)) {
                    setLocations(data);
                    locationsRef.current = data;
                    setFilteredLocations(data);
                    if (data.length > 0) {
                        const targetLoc = data.find((l: Location) => l.id === initialLocId) || data[0];
                        setSelectedLocation(targetLoc);
                    }
                } else {
                    console.error("API returned non-array data:", data);
                }
            })
            .catch((err) => console.error("Error fetching locations:", err));
    }, []);

    // Filter locations
    useEffect(() => {
        const term = search.toLowerCase();
        setFilteredLocations(
            locations.filter((loc) => {
                return loc.title.toLowerCase().includes(term) || loc.city.toLowerCase().includes(term) || (loc.tags && loc.tags.toLowerCase().includes(term));
            })
        );
    }, [search, locations]);

    // Load Google Maps API & Initialize
    useEffect(() => {
        if (!runtimeApiKey) return;

        setOptions({
            key: runtimeApiKey,
            v: "weekly",
        });

        importLibrary("maps").then(async () => {
            const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
            const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
            const { StreetViewPanorama } = await google.maps.importLibrary("streetView") as google.maps.StreetViewLibrary;
            await google.maps.importLibrary("geometry"); // For distance calculations

            setGeometryLoaded(true);

            // Initialize Street View Service
            svServiceRef.current = new google.maps.StreetViewService();

            // Initialize Map
            googleMapObj.current = new Map(mapRef.current as HTMLElement, {
                center: { lat: 20, lng: 0 },
                zoom: 2,
                mapId: "STREET_VIEW_GALLERY_MAP",
            });

            // Initialize Mini Map
            miniMapObj.current = new Map(miniMapRef.current as HTMLElement, {
                center: { lat: 20, lng: 0 },
                zoom: 14,
                mapId: "STREET_VIEW_MINI_MAP",
                disableDefaultUI: true, // This hides everything (pegman, map types, etc.)
                zoomControl: false,
                mapTypeControl: false,
                streetViewControl: false,
                fullscreenControl: false,
                clickableIcons: false,
                keyboardShortcuts: false
            });

            miniMapMarkerObj.current = new AdvancedMarkerElement({
                map: miniMapObj.current,
                position: { lat: 0, lng: 0 },
            });

            // Intercept Pegman Drops
            const defaultStreetView = googleMapObj.current.getStreetView();
            // We must hide the close button since we are intercepting anyway, but just in case
            defaultStreetView.setOptions({ enableCloseButton: false });

            defaultStreetView.addListener("visible_changed", () => {
                if (defaultStreetView.getVisible()) {
                    const pos = defaultStreetView.getPosition();
                    // Intercept the drop: immediately hide the buggy WebGL canvas
                    defaultStreetView.setVisible(false);

                    if (pos) {
                        // const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "";
                        setIframeUrl(`https://www.google.com/maps/embed/v1/streetview?key=${runtimeApiKey}&location=${pos.lat()},${pos.lng()}&heading=0&pitch=0&fov=90`);
                        setViewingStreetView(true);

                        if (miniMapObj.current && miniMapMarkerObj.current) {
                            miniMapObj.current.setCenter(pos);
                            miniMapMarkerObj.current.position = pos;
                        }
                    }
                }
            });
        });
    }, [runtimeApiKey]);

    // Draw all GPX routes for filtered locations
    useEffect(() => {
        if (!googleMapObj.current || typeof window === 'undefined' || !window.google || !geometryLoaded) return;

        // Clear existing routes
        activePolylinesRef.current.forEach((p) => p.polyline.setMap(null));
        activePolylinesRef.current = [];

        const bounds = new google.maps.LatLngBounds();
        let hasPoints = false;
        let calculatedMeters = 0;
        const newThumbnails: Record<string, string> = {};

        filteredLocations.forEach((loc) => {
            if (!loc.gpxData) return;

            const parser = new DOMParser();
            const xmlDoc = parser.parseFromString(loc.gpxData, "text/xml");
            const geoJson = gpx(xmlDoc);

            let coords: google.maps.LatLngLiteral[] = [];
            let locBounds = new google.maps.LatLngBounds();

            geoJson.features.forEach((feature) => {
                if (feature.geometry?.type === "LineString") {
                    coords = coords.concat(feature.geometry.coordinates.map((c: any) => ({ lat: c[1], lng: c[0] })));
                } else if (feature.geometry?.type === "MultiLineString") {
                    feature.geometry.coordinates.forEach((line: any) => {
                        coords = coords.concat(line.map((c: any) => ({ lat: c[1], lng: c[0] })));
                    });
                } else if (feature.geometry?.type === "Point") {
                    coords.push({ lat: feature.geometry.coordinates[1], lng: feature.geometry.coordinates[0] });
                }
            });

            if (coords.length > 0) {
                // Calculate distance
                calculatedMeters += google.maps.geometry.spherical.computeLength(coords);

                const polyline = new google.maps.Polyline({
                    path: coords,
                    strokeColor: "#0000FF",
                    strokeOpacity: 0.6,
                    strokeWeight: 4,
                    clickable: true,
                    map: googleMapObj.current,
                    zIndex: selectedLocation?.id === loc.id ? 10 : 1, // Elevate selected outline
                });

                // Also draw on mini map
                const miniPolyline = new google.maps.Polyline({
                    path: coords,
                    strokeColor: "#0000FF",
                    strokeOpacity: 0.8,
                    strokeWeight: 4,
                    map: miniMapObj.current,
                    zIndex: 1,
                    clickable: true
                });

                coords.forEach((c) => {
                    bounds.extend(c);
                    locBounds.extend(c);
                    hasPoints = true;
                });

                activePolylinesRef.current.push({
                    id: loc.id,
                    polyline,
                    bounds: locBounds,
                    firstCoord: coords[0]
                });
                // Add Google Street View click detection (Main Map)
                polyline.addListener("click", (clickEvent: google.maps.MapMouseEvent) => {
                    if (!clickEvent.latLng) return;
                    const clickPos = clickEvent.latLng;
                    // const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "";
                    setIframeUrl(`https://www.google.com/maps/embed/v1/streetview?key=${runtimeApiKey}&location=${clickPos.lat()},${clickPos.lng()}&heading=0&pitch=0&fov=90`);
                    setViewingStreetView(true);

                    if (miniMapObj.current && miniMapMarkerObj.current) {
                        miniMapObj.current.setCenter(clickPos);
                        miniMapMarkerObj.current.position = clickPos;
                    }
                });

                // Add Google Street View click detection (Mini Map)
                miniPolyline.addListener("click", (clickEvent: google.maps.MapMouseEvent) => {
                    if (!clickEvent.latLng) return;
                    const clickPos = clickEvent.latLng;
                    // const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "";
                    setIframeUrl(`https://www.google.com/maps/embed/v1/streetview?key=${runtimeApiKey}&location=${clickPos.lat()},${clickPos.lng()}&heading=0&pitch=0&fov=90`);
                    setViewingStreetView(true);

                    if (miniMapObj.current && miniMapMarkerObj.current) {
                        miniMapObj.current.setCenter(clickPos);
                        miniMapMarkerObj.current.position = clickPos;
                    }
                });

                // Generate Static Map Thumbnail URL
                try {
                    const maxThumbnailPoints = 150;
                    const step = Math.max(1, Math.floor(coords.length / maxThumbnailPoints));
                    const simplifiedCoords = coords.filter((_, i) => i % step === 0);
                    const encodedPath = google.maps.geometry.encoding.encodePath(simplifiedCoords);
                    // const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || "";
                    // Requesting a high-res (scale=2) map, and a slightly taller size so the Google logo sits proportionally smaller at the bottom right.
                    newThumbnails[loc.id] = `https://maps.googleapis.com/maps/api/staticmap?size=600x250&scale=2&path=weight:3%7Ccolor:blue%7Cenc:${encodedPath}&key=${runtimeApiKey}`;
                } catch (err) {
                    console.error("Failed to generate static map thumbnail", err);
                }
            }
        });

        setThumbnails(newThumbnails);

        // Update stats
        setTotalMiles(calculatedMeters * 0.000621371);

        // Fit bounds for all visible filtered locations
        if (hasPoints) {
            googleMapObj.current.fitBounds(bounds);
        }

    }, [filteredLocations, geometryLoaded, selectedLocation]); // Note: dependency on selectedLocation is REMOVED to prevent redrawing all routes!

    // Handle Selection Highlights and panning smoothly
    useEffect(() => {
        if (!googleMapObj.current || !geometryLoaded) return;

        let didPan = false;

        activePolylinesRef.current.forEach((item) => {
            if (selectedLocation?.id === item.id) {
                item.polyline.setOptions({ strokeColor: "#00FF00", strokeOpacity: 1.0, strokeWeight: 6, zIndex: 10 });
                // Smoothly fit bounds exactly like the initial filtered view
                if (!didPan) {
                    googleMapObj.current!.fitBounds(item.bounds);
                    didPan = true;
                }
            } else {
                item.polyline.setOptions({ strokeColor: "#0000FF", strokeOpacity: 0.6, strokeWeight: 4, zIndex: 1 });
            }
        });
    }, [selectedLocation, geometryLoaded]);

    // Update URL when selection changes
    useEffect(() => {
        if (!selectedLocation) return;
        if (typeof window !== "undefined") {
            const url = new URL(window.location.href);
            url.searchParams.set("locationId", selectedLocation.id);
            window.history.pushState({}, "", url.toString());
        }
    }, [selectedLocation]);



    const closeMobileSidebar = () => {
        setIsMobileSidebarOpen(false);
    };

    const handleLocationSelect = (loc: Location) => {
        // Switch to map view to show route, not street view directly
        setViewingStreetView(false);
        setIframeUrl(null);

        // If clicking the currently selected location, force a map pan/zoom because React state won't trigger the effect
        if (selectedLocation?.id === loc.id) {
            const item = activePolylinesRef.current.find(p => p.id === loc.id);
            if (item && googleMapObj.current) {
                googleMapObj.current.fitBounds(item.bounds);
            }
        } else {
            setSelectedLocation(loc);
        }

        // Auto-close standard Bootstrap offcanvas on mobile natively
        closeMobileSidebar();
    };

    return (
        <div className="container-fluid vh-100 d-flex flex-column p-0 overflow-hidden gsv-background">
            <nav className="navbar navbar-dark gsv-navbar px-2 px-md-3 mt-0 d-flex justify-content-between align-items-center z-3">
                <div className="d-flex align-items-center gap-2">
                    <button
                        className="btn btn-outline-light btn-sm d-md-none"
                        type="button"
                        onClick={() => setIsMobileSidebarOpen(true)}
                        aria-controls="gallerySidebar"
                    >
                        ☰
                    </button>
                    <span className="navbar-brand mb-0 h1 gsv-title fs-md-4 d-none d-lg-block">Street View Gallery</span>
                </div>

                <div className="mx-auto flex-grow-1 px-2 px-md-4 gsv-search-wrapper">
                    <input
                        type="text"
                        className="form-control form-control-sm gsv-input bg-dark text-white border-secondary w-100"
                        placeholder="Search..."
                        value={search}
                        onChange={(e) => setSearch(e.target.value)}
                    />
                </div>

                <div className="text-white fw-medium d-flex align-items-center gap-2 flex-shrink-0" style={{ fontSize: "0.85rem", whiteSpace: "nowrap" }}>
                    {totalMiles > 0 && <span>📍 {totalMiles.toFixed(1)} miles tracked</span>}
                </div>
            </nav>

            <div className="row flex-grow-1 g-0 position-relative" style={{ minHeight: 0 }}>
                {/* Left: List */}
                <div
                    className={`col-md-3 offcanvas-md offcanvas-start gsv-sidebar d-flex flex-column bg-dark h-100 border-end border-secondary ${isMobileSidebarOpen ? 'show' : ''}`}
                    tabIndex={-1}
                    id="gallerySidebar"
                    aria-labelledby="gallerySidebarLabel"
                    style={isMobileSidebarOpen ? { visibility: 'visible' } : undefined}
                >
                    <div className="offcanvas-header d-md-none border-bottom border-secondary text-white p-3 d-flex justify-content-between align-items-center">
                        <h5 className="offcanvas-title m-0" id="gallerySidebarLabel">Locations</h5>
                        <button type="button" className="btn-close btn-close-white" onClick={closeMobileSidebar} aria-label="Close"></button>
                    </div>

                    <div className="offcanvas-body p-0 d-flex flex-column flex-grow-1" style={{ minHeight: 0 }}>
                        <div className="flex-grow-1 p-2" style={{ overflowY: 'auto', WebkitOverflowScrolling: 'touch' }}>
                            {filteredLocations.map((loc) => (
                                <div
                                    key={loc.id}
                                    className={`card mb-2 gsv-card cursor-pointer p-0 shadow-sm ${selectedLocation?.id === loc.id ? "gsv-card-active border-success border-2" : "border-secondary"
                                        }`}
                                    onClick={() => handleLocationSelect(loc)}
                                    style={{ cursor: "pointer", overflow: "hidden" }}
                                >
                                    {/* --- MOBILE LAYOUT (Horizontal) --- */}
                                    <div className="row g-0 h-100 d-md-none">
                                        {/* Thumbnail Map (Left) */}
                                        <div className="col-5 bg-dark border-end border-secondary position-relative" style={{ minHeight: "105px", overflow: "hidden" }}>
                                            {thumbnails[loc.id] ? (
                                                <img
                                                    src={thumbnails[loc.id]}
                                                    alt="Route thumbnail"
                                                    style={{
                                                        position: "absolute",
                                                        top: 0,
                                                        left: 0,
                                                        width: "100%",
                                                        height: "100%",
                                                        objectFit: "cover",
                                                        objectPosition: "center",
                                                        transform: "scale(1.2) translateY(5%)", // Zoom in slightly and push down to crop out the bottom Google/Map Data logos
                                                        transformOrigin: "center bottom"
                                                    }}
                                                />
                                            ) : (
                                                <div className="w-100 h-100 d-flex align-items-center justify-content-center position-absolute top-0 start-0">
                                                    <span className="text-secondary" style={{ fontSize: "0.7rem" }}>Loading...</span>
                                                </div>
                                            )}
                                        </div>
                                        {/* Content (Right) */}
                                        <div className="col-7 bg-dark d-flex flex-column justify-content-center p-2 text-white">
                                            <h6 className="card-title mb-1 text-truncate gsv-title" style={{ fontSize: "0.9rem" }} title={loc.title}>{loc.title}</h6>
                                            <p className="card-text mb-1 text-truncate gsv-subtitle" style={{ fontSize: "0.75rem", lineHeight: "1.2" }}>
                                                {loc.city}<br />{new Date(loc.captureDate).toLocaleDateString()}
                                            </p>
                                            <div className="d-flex justify-content-between align-items-center mt-auto">
                                                {loc.tags && (
                                                    <small className="text-secondary text-truncate" style={{ maxWidth: "100%", fontSize: "0.7rem", display: "block" }}>{loc.tags}</small>
                                                )}
                                                {!loc.gpxData && (
                                                    <span className="badge bg-secondary" style={{ fontSize: "0.55rem" }}>No Route</span>
                                                )}
                                            </div>
                                        </div>
                                    </div>

                                    {/* --- DESKTOP LAYOUT (Vertical/Original) --- */}
                                    <div className="d-none d-md-block">
                                        {/* Thumbnail Map (Top) */}
                                        <div className="card-img-top bg-dark border-bottom border-secondary d-flex align-items-center justify-content-center" style={{ width: "100%", height: "140px", flexShrink: 0, overflow: "hidden", position: "relative" }}>
                                            {thumbnails[loc.id] ? (
                                                <img
                                                    src={thumbnails[loc.id]}
                                                    alt="Route thumbnail"
                                                    style={{
                                                        width: "100%",
                                                        height: "100%",
                                                        objectFit: "cover",
                                                        objectPosition: "center",
                                                        transform: "scale(1.2) translateY(5%)",
                                                        transformOrigin: "center bottom"
                                                    }}
                                                />
                                            ) : (
                                                <span className="text-secondary small">Loading Map...</span>
                                            )}
                                        </div>
                                        {/* Content (Bottom) */}
                                        <div className="card-body p-2 bg-dark text-white">
                                            <h6 className="card-title mb-1 text-truncate gsv-title" title={loc.title}>{loc.title}</h6>
                                            <p className="card-text small mb-1 text-truncate gsv-subtitle">
                                                {loc.city} • {new Date(loc.captureDate).toLocaleDateString()}
                                            </p>
                                            <div className="d-flex justify-content-between align-items-center mt-1">
                                                <small className="text-secondary text-truncate" style={{ maxWidth: "100%" }}>{loc.tags}</small>
                                            </div>
                                            <div className="d-flex justify-content-between align-items-center mt-1">
                                                {!loc.gpxData && (
                                                    <span className="badge bg-secondary" style={{ fontSize: "0.6rem" }}>No Route Data</span>
                                                )}
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            ))}
                            {filteredLocations.length === 0 && (
                                <div className="text-center text-muted mt-4 p-3 bg-dark rounded">No locations found.</div>
                            )}

                            {/* Oldest date indicator at the bottom */}
                            {locations.length > 0 && (
                                <div className="text-secondary mt-3 mb-2" style={{ fontSize: "0.75rem", textAlign: "center", textTransform: "uppercase", letterSpacing: "1px" }}>
                                    Images dating back to {
                                        new Date(Math.min(...locations.map(l => new Date(l.captureDate).getTime()))).getFullYear()
                                    }
                                </div>
                            )}
                        </div>
                    </div>
                </div>
                {/* Main Panel (Map or Street View) */}
                <div className="col-12 col-md-9 position-relative bg-black d-flex flex-column p-0">
                    <div ref={mapRef} style={{ width: "100%", height: "100%", position: "absolute", zIndex: 0 }} />

                    {/* Overlay controls and mini-map, only shown when in Street View mode */}
                    {viewingStreetView && iframeUrl && (
                        <>
                            <div
                                style={{
                                    position: 'absolute',
                                    top: 0,
                                    left: 0,
                                    width: '100%',
                                    height: '100%',
                                    zIndex: 1,
                                    backgroundColor: '#000'
                                }}
                            >
                                <iframe
                                    width="100%"
                                    height="100%"
                                    style={{ border: 0 }}
                                    loading="lazy"
                                    allowFullScreen
                                    src={iframeUrl}
                                ></iframe>
                            </div>
                            <button
                                className="btn btn-dark position-absolute shadow-lg"
                                style={{ top: "60px", left: "10px", zIndex: 2, display: "flex", alignItems: "center", gap: "8px" }}
                                onClick={() => {
                                    setViewingStreetView(false);
                                    setIframeUrl(null);
                                }}
                            >
                                <span>&larr;</span> Back to Map
                            </button>
                        </>
                    )}

                    <div
                        ref={miniMapRef}
                        className={`shadow-lg border border-3 border-dark rounded ${viewingStreetView ? 'd-block' : 'd-none'}`}
                        style={{
                            position: "absolute",
                            bottom: "20px",
                            left: "20px",
                            width: "200px",
                            height: "200px",
                            zIndex: 4,
                            pointerEvents: "auto"
                        }}
                    />
                </div>
            </div>

            {/* Manual React Backdrop for Mobile Sidebar */}
            {isMobileSidebarOpen && (
                <div
                    className="offcanvas-backdrop fade show d-md-none"
                    onClick={() => setIsMobileSidebarOpen(false)}
                />
            )}
        </div>
    );
}
