'use client';

import { useEffect, useState, useRef, useCallback } from 'react';
import { useParams, useRouter } from 'next/navigation';
import dynamic from 'next/dynamic';
import { useRoom } from '@/hooks/useRoom';
import { useAuthStore } from '@/stores/auth';
import { useLocationSharing } from '@/hooks/useLocationSharing';
import { useServiceWorkerMessages } from '@/hooks/useServiceWorkerMessages';
import { usePushNotifications } from '@/hooks/usePushNotifications';
import ParticipantList from '@/components/room/ParticipantList';
import RoomHeader from '@/components/room/RoomHeader';
import ShareModal from '@/components/room/ShareModal';
import MeetingPointModal from '@/components/room/MeetingPointModal';
import WaypointModal from '@/components/room/WaypointModal';
import ImportModal from '@/components/room/ImportModal';
import type { ImportedPlace } from '@/components/room/ImportModal';
import InstallBanner from '@/components/room/InstallBanner';
import JoinForm from '@/components/room/JoinForm';
import type { Participant, ParticipantLocation, Waypoint } from '@/types';

// Dynamic import for map to avoid SSR issues with MapLibre
const DualMapView = dynamic(() => import('@/components/map/DualMapView'), {
  ssr: false,
  loading: () => (
    <div className="w-full h-full bg-rmaps-dark flex items-center justify-center">
      <div className="text-white/60">Loading map...</div>
    </div>
  ),
});

export default function RoomPage() {
  const params = useParams();
  const router = useRouter();
  const slug = params.slug as string;
  const { did: encryptIdDid, token: authToken } = useAuthStore();

  const [showShare, setShowShare] = useState(false);
  const [showParticipants, setShowParticipants] = useState(true);
  const [showMeetingPoint, setShowMeetingPoint] = useState(false);
  const [showImport, setShowImport] = useState(false);
  const [currentUser, setCurrentUser] = useState<{ name: string; emoji: string } | null>(null);
  const [selectedParticipant, setSelectedParticipant] = useState<Participant | null>(null);
  const [selectedWaypoint, setSelectedWaypoint] = useState<Waypoint | null>(null);
  const [shouldAutoStartSharing, setShouldAutoStartSharing] = useState(false);
  const [zoomToLocation, setZoomToLocation] = useState<{ latitude: number; longitude: number } | null>(null);
  const [needsJoin, setNeedsJoin] = useState(false);

  // Load user and sharing preference from localStorage
  useEffect(() => {
    const stored = localStorage.getItem('rmaps_user');
    if (stored) {
      setCurrentUser(JSON.parse(stored));
      // Save this as the last visited room
      localStorage.setItem('rmaps_last_room', slug);
      // Check if user had location sharing enabled for this room
      const sharingPref = localStorage.getItem(`rmaps_sharing_${slug}`);
      if (sharingPref === 'true') {
        setShouldAutoStartSharing(true);
      }
    } else {
      // Show join form instead of redirecting
      setNeedsJoin(true);
    }
  }, [slug]);

  // Handle joining from the inline form
  const handleJoin = (name: string, emoji: string) => {
    const user = { name, emoji };
    localStorage.setItem('rmaps_user', JSON.stringify(user));
    localStorage.setItem('rmaps_last_room', slug);
    setCurrentUser(user);
    setNeedsJoin(false);
  };

  // Room hook (only initialize when we have user info)
  const {
    isConnected,
    isLoading,
    error,
    participants,
    waypoints,
    currentParticipantId,
    roomName,
    updateLocation,
    updateIndoorPosition,
    clearLocation,
    setStatus,
    addWaypoint,
    removeWaypoint,
    leave,
    setLocationRequestCallback,
  } = useRoom({
    slug,
    userName: currentUser?.name || '',
    userEmoji: currentUser?.emoji || '👤',
    encryptIdDid,
    authToken,
  });

  // Use refs to avoid stale closures in callbacks
  const isConnectedRef = useRef(isConnected);
  const updateLocationRef = useRef(updateLocation);

  useEffect(() => {
    isConnectedRef.current = isConnected;
  }, [isConnected]);

  useEffect(() => {
    updateLocationRef.current = updateLocation;
  }, [updateLocation]);

  // Stable callback that always uses latest refs - also persists location
  const handleLocationUpdate = useCallback((location: ParticipantLocation) => {
    console.log('Location update received:', location.latitude, location.longitude, 'connected:', isConnectedRef.current);
    if (isConnectedRef.current) {
      updateLocationRef.current(location);
      // Persist last known location for faster reload
      try {
        localStorage.setItem(`rmaps_last_location_${slug}`, JSON.stringify({
          latitude: location.latitude,
          longitude: location.longitude,
          accuracy: location.accuracy,
          timestamp: location.timestamp.toISOString(),
        }));
      } catch {
        // Ignore storage errors
      }
    }
  }, [slug]);

  // Location sharing hook
  const {
    isSharing,
    currentLocation,
    startSharing,
    stopSharing,
    requestUpdate,
  } = useLocationSharing({
    onLocationUpdate: handleLocationUpdate,
    updateInterval: 5000,
    highAccuracy: true,
  });

  // Service worker messages for background location sync
  useServiceWorkerMessages({
    onLocationRequest: () => {
      // Silent push notification requested location update
      console.log('Service worker requested location update');
      if (isSharing) {
        requestUpdate();
      }
    },
    onLocationSync: () => {
      // Device came back online, sync location
      console.log('Service worker requested location sync');
      if (isSharing) {
        requestUpdate();
      }
    },
  });

  // Push notifications for background pings
  const syncUrl = process.env.NEXT_PUBLIC_SYNC_URL;
  const { subscribe: subscribePush, isSubscribed: isPushSubscribed } = usePushNotifications({
    syncUrl,
    roomSlug: slug,
  });

  // Auto-subscribe to push when joining room (like location permission)
  const hasRequestedPushRef = useRef(false);
  useEffect(() => {
    if (isConnected && !isPushSubscribed && !hasRequestedPushRef.current && syncUrl) {
      hasRequestedPushRef.current = true;
      console.log('Auto-requesting push notification permission');
      subscribePush().catch((err) => {
        console.warn('Push subscription failed (user may have denied):', err.message);
      });
    }
  }, [isConnected, isPushSubscribed, subscribePush, syncUrl]);

  // Restore last known location immediately when connected
  const hasRestoredLocationRef = useRef(false);
  useEffect(() => {
    if (isConnected && !hasRestoredLocationRef.current) {
      hasRestoredLocationRef.current = true;
      try {
        const savedLocation = localStorage.getItem(`rmaps_last_location_${slug}`);
        if (savedLocation) {
          const loc = JSON.parse(savedLocation);
          // Only restore if less than 1 hour old
          const age = Date.now() - new Date(loc.timestamp).getTime();
          if (age < 60 * 60 * 1000) {
            console.log('Restoring last known location:', loc.latitude, loc.longitude);
            updateLocation({
              latitude: loc.latitude,
              longitude: loc.longitude,
              accuracy: loc.accuracy || 100,
              timestamp: new Date(loc.timestamp),
              source: 'gps',
            });
          }
        }
      } catch {
        // Ignore restore errors
      }
    }
  }, [isConnected, slug, updateLocation]);

  // Auto-start location sharing if user had it enabled before
  useEffect(() => {
    if (shouldAutoStartSharing && isConnected && !isSharing) {
      console.log('Auto-starting location sharing from saved preference');
      startSharing();
      setShouldAutoStartSharing(false); // Only auto-start once
    }
  }, [shouldAutoStartSharing, isConnected, isSharing, startSharing]);

  // Set up callback for when server requests location (via refresh button)
  useEffect(() => {
    if (isConnected) {
      setLocationRequestCallback(() => {
        console.log('Server requested location update');
        if (isSharing) {
          requestUpdate();
        }
      });
    }
  }, [isConnected, isSharing, requestUpdate, setLocationRequestCallback]);

  // Handler for toggling location sharing - persists preference
  const handleToggleSharing = useCallback(() => {
    if (isSharing) {
      console.log('Stopping location sharing and clearing location');
      stopSharing();
      clearLocation();
      // Save preference
      localStorage.setItem(`rmaps_sharing_${slug}`, 'false');
    } else {
      console.log('Starting location sharing');
      startSharing();
      // Save preference
      localStorage.setItem(`rmaps_sharing_${slug}`, 'true');
    }
  }, [isSharing, startSharing, stopSharing, clearLocation, slug]);

  // Track if we've centered on user's location yet
  const hasCenteredRef = useRef(false);

  // Log when we get location updates
  useEffect(() => {
    if (currentLocation && !hasCenteredRef.current) {
      console.log('First location acquired:', currentLocation.latitude, currentLocation.longitude);
      hasCenteredRef.current = true;
    }
  }, [currentLocation]);

  // Update status when app goes to background
  useEffect(() => {
    const handleVisibility = () => {
      if (document.hidden) {
        setStatus('away');
      } else {
        setStatus('online');
      }
    };

    document.addEventListener('visibilitychange', handleVisibility);
    return () => document.removeEventListener('visibilitychange', handleVisibility);
  }, [setStatus]);

  // Handle leaving room
  useEffect(() => {
    const handleBeforeUnload = () => {
      leave();
    };

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => {
      window.removeEventListener('beforeunload', handleBeforeUnload);
      leave();
    };
  }, [leave]);

  // Navigate to participant - zoom to their location on the map
  const handleNavigateTo = (participant: Participant) => {
    if (!participant.location) {
      console.log('No location for participant:', participant.name);
      return;
    }
    const { latitude, longitude } = participant.location;
    setZoomToLocation({ latitude, longitude });
    setSelectedParticipant(participant);
    setShowParticipants(false); // Close participant list to show map
  };

  // Show join form if user hasn't entered their name yet
  if (needsJoin) {
    return <JoinForm roomSlug={slug} onJoin={handleJoin} />;
  }

  // Loading state
  if (!currentUser || isLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-rmaps-dark">
        <div className="text-center">
          <div className="w-8 h-8 border-2 border-rmaps-primary border-t-transparent rounded-full animate-spin mx-auto mb-4" />
          <div className="text-white/60">Joining room...</div>
        </div>
      </div>
    );
  }

  // Error state
  if (error) {
    return (
      <div className="min-h-screen flex items-center justify-center p-4 bg-rmaps-dark">
        <div className="room-panel rounded-2xl p-6 max-w-md text-center">
          <h2 className="text-xl font-bold text-red-400 mb-2">Connection Error</h2>
          <p className="text-white/60 mb-4">{error}</p>
          <div className="flex gap-3 justify-center">
            <button onClick={() => window.location.reload()} className="btn-ghost">
              Retry
            </button>
            <a href="/" className="btn-primary">
              Go Home
            </a>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="h-screen w-screen flex flex-col overflow-hidden bg-rmaps-dark">
      {/* PWA Install Banner */}
      <InstallBanner />

      {/* Header */}
      <RoomHeader
        roomSlug={slug}
        participantCount={participants.length}
        isSharing={isSharing}
        onToggleSharing={handleToggleSharing}
        onShare={() => setShowShare(true)}
        onToggleParticipants={() => setShowParticipants(!showParticipants)}
        syncUrl={process.env.NEXT_PUBLIC_SYNC_URL}
      />

      {/* Main Content */}
      <div className="flex-1 relative">
        {/* Map */}
        <DualMapView
          participants={participants}
          waypoints={waypoints}
          currentUserId={currentParticipantId || undefined}
          currentLocation={currentLocation}
          eventId="39c3"
          isSharing={isSharing}
          onToggleSharing={handleToggleSharing}
          zoomToLocation={zoomToLocation}
          selectedParticipant={selectedParticipant}
          onSelectedParticipantChange={setSelectedParticipant}
          onParticipantClick={(p) => {
            setSelectedParticipant(p);
            setShowParticipants(false); // Hide list to show map with navigation panel
          }}
          onWaypointClick={(w) => {
            setSelectedWaypoint(w);
          }}
          onIndoorPositionSet={updateIndoorPosition}
        />

        {/* Participant Panel */}
        {showParticipants && (
          <div className="absolute bottom-0 left-0 right-0 md:top-0 md:right-auto md:w-80 md:bottom-auto md:h-full z-20">
            <ParticipantList
              participants={participants}
              currentUserId={currentUser.name}
              roomSlug={slug}
              syncUrl={process.env.NEXT_PUBLIC_SYNC_URL}
              onClose={() => setShowParticipants(false)}
              onNavigateTo={handleNavigateTo}
              onSetMeetingPoint={() => setShowMeetingPoint(true)}
              onImportPlaces={() => setShowImport(true)}
            />
          </div>
        )}

        {/* Floating "See Friends" button when participant list is hidden */}
        {!showParticipants && (
          <button
            onClick={() => setShowParticipants(true)}
            className="absolute bottom-6 left-4 md:top-4 md:bottom-auto flex items-center gap-2 px-4 py-2.5 rounded-full bg-rmaps-dark/90 backdrop-blur border border-white/20 hover:bg-rmaps-dark hover:border-white/30 transition-colors shadow-lg z-20"
          >
            <span className="text-lg">👥</span>
            <span className="text-sm font-medium">See Friends</span>
            <span className="text-xs text-white/60">({participants.length})</span>
          </button>
        )}

        {/* Connection status indicator */}
        {!isConnected && (
          <div className="absolute top-4 left-1/2 -translate-x-1/2 bg-yellow-500/90 text-black text-sm px-3 py-1.5 rounded-full z-30">
            Reconnecting...
          </div>
        )}
      </div>

      {/* Share Modal */}
      {showShare && (
        <ShareModal roomSlug={slug} onClose={() => setShowShare(false)} />
      )}

      {/* Meeting Point Modal */}
      {showMeetingPoint && (
        <MeetingPointModal
          currentLocation={currentLocation}
          onClose={() => setShowMeetingPoint(false)}
          onSetMeetingPoint={(waypoint) => {
            addWaypoint(waypoint);
            setShowMeetingPoint(false);
          }}
        />
      )}

      {/* Waypoint Detail Modal */}
      {selectedWaypoint && (
        <WaypointModal
          waypoint={selectedWaypoint}
          canDelete={true}
          onClose={() => setSelectedWaypoint(null)}
          onDelete={() => {
            removeWaypoint(selectedWaypoint.id);
            setSelectedWaypoint(null);
          }}
          onNavigate={() => {
            const { latitude, longitude } = selectedWaypoint.location;
            setZoomToLocation({ latitude, longitude });
            setSelectedWaypoint(null);
          }}
        />
      )}

      {/* Import Modal */}
      {showImport && (
        <ImportModal
          onClose={() => setShowImport(false)}
          onImport={(places: ImportedPlace[]) => {
            // Add each imported place as a waypoint
            places.forEach((place) => {
              addWaypoint({
                name: place.name,
                emoji: place.emoji,
                location: {
                  latitude: place.latitude,
                  longitude: place.longitude,
                },
                type: place.type,
              });
            });
          }}
        />
      )}
    </div>
  );
}
