"use client";

import React from 'react';
import Link from 'next/link';
import { useNearestChargePoint } from '@/modules/chargepointModule/map/hooks/useNearestChargePoint';
import { Card, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button/Button';
import Badge from '@/components/ui/badge/Badge';
import Alert from '@/components/ui/alert/Alert';
import { 
  Zap, 
  RefreshCw, 
  MapPin, 
  Navigation, 
  Eye,
  Loader2,
  AlertTriangle,
  MapPinOff,
  Wifi,
  WifiOff,
  Plug,
  Send,
  Square
} from 'lucide-react';
import type { ChargePoint } from '@/types/chargepoint/chargepoint';
import { cn } from '@/lib/utils.client';
import ConnectorTypeIcon from '@/modules/chargepointModule/detail/components/ConnectorTypeIcon';

// State machine type
type WidgetState = 
  | 'idle' 
  | 'requesting-permission' 
  | 'loading' 
  | 'success' 
  | 'error' 
  | 'denied' 
  | 'unsupported' 
  | 'empty';

type GeoPermissionState = 'prompt' | 'granted' | 'denied' | 'unsupported';

interface UserLocation {
  lat: number;
  lng: number;
}

export function NearestChargerWidget() {
  const [state, setState] = React.useState<WidgetState>('idle');
  const [permission, setPermission] = React.useState<GeoPermissionState>('prompt');
  const [error, setError] = React.useState<string | null>(null);
  const [userLocation, setUserLocation] = React.useState<UserLocation | null>(null);
  const { nearest, fetchNearest, setNearest } = useNearestChargePoint();

  // Calculate distance using Haversine formula
  const calculateDistance = React.useCallback((lat1: number, lon1: number, lat2: number, lon2: number): number => {
    const R = 6371; // Earth's radius in km
    const dLat = (lat2 - lat1) * Math.PI / 180;
    const dLon = (lon2 - lon1) * Math.PI / 180;
    const a = 
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
      Math.sin(dLon / 2) * Math.sin(dLon / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c; // Distance in km
  }, []);

  const formatDistance = React.useCallback((distanceKm: number): string => {
    if (distanceKm < 1) {
      return `${Math.round(distanceKm * 1000)}m`;
    }
    return `${distanceKm.toFixed(1)}km`;
  }, []);

  const distance = React.useMemo(() => {
    if (!nearest?.coordinates || !userLocation) return null;
    const [lat, lng] = nearest.coordinates;
    return calculateDistance(userLocation.lat, userLocation.lng, lat, lng);
  }, [nearest, userLocation, calculateDistance]);

  const resolvePermission = React.useCallback(async (): Promise<GeoPermissionState> => {
    if (typeof navigator === 'undefined' || !('geolocation' in navigator)) {
      return 'unsupported';
    }
    try {
      if ('permissions' in navigator && (navigator as any).permissions?.query) {
        const status = await (navigator as any).permissions.query({ name: 'geolocation' as PermissionName });
        return status.state as GeoPermissionState;
      }
    } catch {
      // Permission API not supported, fallback to prompt
    }
    return 'prompt';
  }, []);

  const requestAndFetch = React.useCallback(async (opts?: { forceRequest?: boolean }) => {
    const forceRequest = opts?.forceRequest === true;
    setError(null);
    
    try {
      const permissionState = await resolvePermission();
      setPermission(permissionState);

      // Handle denied/unsupported states
      if (!forceRequest && (permissionState === 'denied' || permissionState === 'unsupported')) {
        setState(permissionState === 'denied' ? 'denied' : 'unsupported');
        return;
      }

      // Request location
      setState('requesting-permission');
      
      await new Promise<void>((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(
          async (pos) => {
            try {
              setState('loading');
              const { latitude, longitude } = pos.coords;
              setUserLocation({ lat: latitude, lng: longitude });
              
              const cp = await fetchNearest(latitude, longitude, 50000, { online: true });
              
              if (cp) {
                setNearest(cp);
                setState('success');
              } else {
                setState('empty');
              }
              resolve();
            } catch (e: any) {
              setError(e?.message || 'Failed to fetch nearest station');
              setState('error');
              reject(e instanceof Error ? e : new Error(e?.message || 'Unknown error'));
            }
          },
          (err) => {
            const errorMessage = (err as any)?.message || 'Location permission denied';
            setError(errorMessage);
            setPermission('denied');
            setState('denied');
            reject(err instanceof Error ? err : new Error(errorMessage));
          },
          { enableHighAccuracy: false, maximumAge: 60000, timeout: 10000 }
        );
      });
    } catch (e: any) {
      setError(e?.message || 'Unable to get location');
      setState('error');
    }
  }, [resolvePermission, fetchNearest, setNearest]);

  React.useEffect(() => {
    requestAndFetch({ forceRequest: false });
  }, [requestAndFetch]);

  const handleRetry = React.useCallback(() => {
    requestAndFetch({ forceRequest: true });
  }, [requestAndFetch]);

  return (
    <div className="w-full h-full">
      <Card className="h-full flex flex-col bg-gradient-to-br from-brand-600 to-brand-700 text-white border-brand-500/50 shadow-lg">
        {/* Header */}
        <div className="flex items-center justify-between mb-3 px-4 pt-4">
          <div className="flex items-center gap-2 sm:gap-3">
              <CardTitle className="text-sm sm:text-base mb-0 text-white dark:text-white font-normal">
                Nearest Station
              </CardTitle>
          </div>
          <Button
            variant="outline"
            size="sm"
            onClick={handleRetry}
            aria-label="Refresh location"
            disabled={state === 'loading' || state === 'requesting-permission'}
            className="border-white/30 bg-white/10 hover:bg-white/15 text-white"
          >
            <RefreshCw 
              className={cn(
                "h-4 w-4 sm:h-5 sm:w-5",
                (state === 'loading' || state === 'requesting-permission') && "animate-spin"
              )} 
              aria-hidden="true"
            />
          </Button>
        </div>

        {/* Content - State-based rendering */}
        <div className="flex items-center justify-center py-4 px-4 pb-4">
          {state === 'loading' || state === 'requesting-permission' ? (
            <LoadingState />
          ) : state === 'denied' || state === 'unsupported' ? (
            <PermissionDeniedState 
              state={state} 
              onRetry={handleRetry} 
            />
          ) : state === 'error' ? (
            <ErrorState error={error} onRetry={handleRetry} />
          ) : state === 'empty' ? (
            <EmptyState onRetry={handleRetry} />
          ) : state === 'success' && nearest ? (
            <SuccessState 
              nearest={nearest} 
              distance={distance} 
              formatDistance={formatDistance}
            />
          ) : (
            <LoadingState />
          )}
        </div>
      </Card>
    </div>
  );
}

// Loading State Component
function LoadingState() {
  return (
    <div className="flex flex-col items-center gap-3 sm:gap-4" role="status" aria-live="polite">
      <Loader2 className="h-8 w-8 sm:h-10 sm:w-10 text-brand-400 dark:text-brand-400 animate-spin" aria-hidden="true" />
      <p className="text-sm sm:text-base font-medium text-white dark:text-white text-center px-4">
        Finding nearest charger...
      </p>
      <span className="sr-only">Loading nearest charging station</span>
    </div>
  );
}

// Permission Denied State Component
function PermissionDeniedState({ 
  state, 
  onRetry 
}: { 
  state: 'denied' | 'unsupported';
  onRetry: () => void;
}) {
  return (
    <div className="w-full px-4">
      <Alert
        variant={state === 'unsupported' ? 'warning' : 'error'}
        title={state === 'unsupported' ? 'Location Not Available' : 'Location Access Needed'}
        message={
          state === 'unsupported'
            ? 'Your device does not support location services.'
            : 'Please enable location access to find the nearest charging station.'
        }
        showLink={false}
      />
      <div className="mt-4 flex justify-center">
        <Button
          variant="primary"
          size="sm"
          onClick={onRetry}
          startIcon={<RefreshCw className="h-4 w-4" />}
        >
          Enable Location
        </Button>
      </div>
    </div>
  );
}

// Error State Component
function ErrorState({ 
  error, 
  onRetry 
}: { 
  error: string | null;
  onRetry: () => void;
}) {
  return (
    <div className="w-full px-4">
      <Alert
        variant="error"
        title="Unable to Locate"
        message={error || 'Failed to get your location. Please try again.'}
        showLink={false}
      />
      <div className="mt-4 flex justify-center">
        <Button
          variant="primary"
          size="sm"
          onClick={onRetry}
          startIcon={<RefreshCw className="h-4 w-4" />}
        >
          Try Again
        </Button>
      </div>
    </div>
  );
}

// Empty State Component
function EmptyState({ onRetry }: { onRetry: () => void }) {
  return (
    <div className="text-center px-4">
      <div className="w-12 h-12 sm:w-14 sm:h-14 mx-auto mb-3 sm:mb-4 rounded-full bg-gray-800 dark:bg-gray-800 flex items-center justify-center">
        <MapPinOff className="h-6 w-6 sm:h-7 sm:w-7 text-gray-400 dark:text-gray-400" aria-hidden="true" />
      </div>
      <p className="text-sm sm:text-base font-semibold text-white dark:text-white mb-2">
        No stations nearby
      </p>
      <p className="text-xs sm:text-sm text-gray-400 dark:text-gray-400 mb-4">
        We couldn't find any charging stations within 50km of your location.
      </p>
      <Button
        variant="outline"
        size="sm"
        onClick={onRetry}
        startIcon={<RefreshCw className="h-4 w-4" />}
        className="border-gray-700 hover:bg-gray-800 text-white"
      >
        Search Again
      </Button>
    </div>
  );
}

// Success State Component
function SuccessState({ 
  nearest, 
  distance, 
  formatDistance,
}: { 
  nearest: ChargePoint;
  distance: number | null;
  formatDistance: (distance: number) => string;
}) {
  // Calculate available connectors
  const totalConnectors = nearest.connectors?.length || 0;
  const availableConnectors = nearest.connectors?.filter((c: any) => c.status === 'Available').length || 0;
  
  // Calculate max power
  const maxPower = nearest.connectors?.length 
    ? Math.max(...(nearest.connectors.map((c: any) => c.power || 0)))
    : 0;
  
  // Get connector type from first connector
  const firstConnector = nearest.connectors && nearest.connectors.length > 0 ? nearest.connectors[0] : null;
  const connectorType = firstConnector?.type || 'N/A';
  
  // v1 chargepoints do not include a separate location payload; use metadata when available.
  const getAddress = () => {
    return (nearest.meta_data as any)?.street_and_number || 
           (nearest.meta_data as any)?.address || 
           (nearest.meta_data as any)?.city || 
           'Address not available';
  };
  
  const address = getAddress();
  const locationText = distance !== null 
    ? `${formatDistance(distance)} away • ${address}`
    : address;

  return (
    <div className="w-full space-y-4">
      {/* Station Name with Share Button */}
      <div className="flex items-start justify-between gap-3">
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 mb-1 flex-wrap">
            <h3 className="text-xl sm:text-2xl font-bold text-white dark:text-white truncate">
              {nearest.name}
            </h3>
            {/* Online/Offline Indicator */}
            <div className="flex items-center gap-1.5 flex-shrink-0">
              {nearest.online ? (
                <div className="flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-green-500/20 border border-green-400/30">
                  <div className="h-2 w-2 rounded-full bg-green-400 animate-pulse" />
                  <span className="text-xs font-medium text-green-200">Online</span>
                </div>
              ) : (
                <div className="flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-red-500/20 border border-red-400/30">
                  <WifiOff className="h-3 w-3 text-red-300" />
                  <span className="text-xs font-medium text-red-200">Offline</span>
                </div>
              )}
            </div>
          </div>
        </div>
        {nearest.coordinates && (
          <Button
            variant="outline"
            size="sm"
            asChild
            className="flex-shrink-0 border-white/30 bg-white/10 hover:bg-white/15 text-white rounded-lg"
          >
            <a
              href={`https://www.google.com/maps/dir/?api=1&destination=${nearest.coordinates[0]},${nearest.coordinates[1]}`}
              target="_blank"
              rel="noopener noreferrer"
              className="p-2"
            >
              <Send className="h-4 w-4" />
            </a>
          </Button>
        )}
      </div>

      {/* Location Info */}
      <div className="flex items-center gap-2 text-sm text-white dark:text-white">
        <MapPin className="h-4 w-4 flex-shrink-0" aria-hidden="true" />
        <span className="text-sm">{locationText}</span>
      </div>

      {/* Info Cards - Available, Max Power, Connector Type */}
      <div className="grid grid-cols-3 gap-3">
        {/* Available Card */}
        <div className="rounded-lg p-3 border border-white/15 bg-white/10 backdrop-blur">
          <div className="flex items-center justify-center mb-2">
            <div className="h-6 w-6 rounded bg-white/20 flex items-center justify-center">
              <Plug className="h-3 w-3 text-white" />
            </div>
          </div>
          <p className="text-xs text-gray-200/80 dark:text-gray-200/80 text-center mb-1">Available</p>
          <p className="text-lg font-bold text-white dark:text-white text-center">
            {availableConnectors}/{totalConnectors}
          </p>
        </div>

        {/* Max Power Card */}
        <div className="rounded-lg p-3 border border-white/15 bg-white/10 backdrop-blur">
          <div className="flex items-center justify-center mb-2">
            <div className="h-6 w-6 rounded bg-white/20 flex items-center justify-center">
              <Zap className="h-3 w-3 text-white" />
            </div>
          </div>
          <p className="text-xs text-gray-200/80 dark:text-gray-200/80 text-center mb-1">Max Power</p>
          <p className="text-lg font-bold text-white dark:text-white text-center">
            {maxPower}kW
          </p>
        </div>

        {/* Connector Type Card */}
        <div className="rounded-lg p-3 border border-white/15 bg-white/10 backdrop-blur">
          <div className="flex items-center justify-center mb-2">
            <div className="h-6 w-6 rounded bg-white/20 flex items-center justify-center">
              {firstConnector ? (
                <ConnectorTypeIcon 
                  type={connectorType} 
                  size={12} 
                  className="flex-shrink-0" 
                />
              ) : (
                <Square className="h-3 w-3 text-white" />
              )}
            </div>
          </div>
          <p className="text-xs text-gray-200/80 dark:text-gray-200/80 text-center mb-1">Connector Type</p>
          <p className="text-lg font-bold text-white dark:text-white text-center">
            {connectorType}
          </p>
        </div>
      </div>

      {/* Start Navigation Button */}
      {nearest.coordinates && (
        <Button
          variant="outline"
          size="md"
          asChild
          className="w-full bg-white dark:bg-white text-brand-600 dark:text-brand-600 hover:bg-gray-100 dark:hover:bg-gray-100 border-0 rounded-lg font-medium"
        >
          <a
            href={`https://www.google.com/maps/dir/?api=1&destination=${nearest.coordinates[0]},${nearest.coordinates[1]}`}
            target="_blank"
            rel="noopener noreferrer"
          >
            Start Navigation
          </a>
        </Button>
      )}
    </div>
  );
}

export default NearestChargerWidget;
