"use client"

import { Typography, Grid, Dialog, DialogTitle, DialogContent, Box, Button } from "@mui/material"
import { mainColor, outlinedColor } from "@/shared/components/table/styles"
import { addPointFormFields } from "../utils/form-fields-trajet"
import type { FormFieldType } from "@/shared/types/common"
import FormField from "@/shared/components/form/form-field"
import { useState, useEffect } from "react"
import { MOCK_PASSENGERS, type IAddPoint } from "@/shared/types/trajet"
import { INITIAL_ADD_POINT_DATA } from "@/shared/_mock/_trajets"
import dynamic from "next/dynamic"
import { RouteMarker, LatLng, MapType } from '@/shared/types/Maps'
import { useFormik } from 'formik'
import { addPointValidationSchema } from '../utils/add-point-validation-schema'
import { useTrajetStore } from "@/shared/api/stores/trajetStore"
import { StatusColor } from '@/shared/sections/chauffeur/planingChauffeur/utils/schedule-utils'
import { GoogleMap, DirectionsRenderer } from '@react-google-maps/api'
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"



const MapView = dynamic(() => import('@/shared/components/google-maps/mapsPoints'), {
  ssr: false,
});

interface Props {
  open: boolean
  onClose: () => void
  trajetId: string
  onPointAdded?: (point: RouteMarker) => void
}


export default function AddPointModal({ open, onClose, trajetId, onPointAdded }: Props) {
  const { getTrajetById, addTripPoint } = useTrajetStore();
  const [selectedLocation, setSelectedLocation] = useState<{ lat: number, lng: number } | null>(null);
  const [mapMarkers, setMapMarkers] = useState<RouteMarker[]>([]);
  const [directionsResult, setDirectionsResult] = useState<google.maps.DirectionsResult | null>(null);
  const [isAddressSelected, setIsAddressSelected] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const formik = useFormik<IAddPoint>({
    initialValues: INITIAL_ADD_POINT_DATA,
    validationSchema: addPointValidationSchema,
    onSubmit: () => { }
  });

  useEffect(() => {
    if (open && trajetId) {
      loadExistingPoints();
    }
  }, [open, trajetId]);

  const loadExistingPoints = async () => {
    try {
      const trajet = await getTrajetById(trajetId);
      if (trajet?.points?.length) {
        const existingMarkers = trajet.points.map((point: any, index: number) => ({
          id: point.id,
          position: {
            lat: parseFloat(point.latitude),
            lng: parseFloat(point.longitude)
          },
          title: point.label,
          icon: getMarkerIcon(index, trajet?.points?.length || 0),
          order: index + 1,
          color: StatusColor.PRIMARY
        }));
        setMapMarkers(existingMarkers);
        if (existingMarkers.length >= 2) {
          calculateRoute(existingMarkers);
        }
      }
    } catch (error) {
      setError(error as string);
    }
  };

  const handleMapClick = async (event: google.maps.MapMouseEvent) => {
    if (!event.latLng) return;

    const newPosition = {
      lat: event.latLng.lat(),
      lng: event.latLng.lng()
    };

    setSelectedLocation(newPosition);

    // Update address fields using reverse geocoding
    const geocoder = new google.maps.Geocoder();
    try {
      const result = await geocoder.geocode({ location: newPosition });
      if (result.results[0]) {
        const address = result.results[0];

        // Parse address components
        const streetNumber = address.address_components.find(c => c.types.includes('street_number'))?.long_name || '';
        const route = address.address_components.find(c => c.types.includes('route'))?.long_name || '';
        const city = address.address_components.find(c => c.types.includes('locality'))?.long_name || '';
        const postalCode = address.address_components.find(c => c.types.includes('postal_code'))?.long_name || '';

        formik.setValues({
          ...formik.values,
          endPointAddress: {
            address: `${streetNumber} ${route}`.trim(),
            city,
            postalCode,
            country: 'France',
            lat: newPosition.lat,
            lng: newPosition.lng
          }
        });

        updateMarkersAndRoute(newPosition, `${streetNumber} ${route}`.trim());
      }
    } catch (error) {
      setError(error as string);
    }
  };

  const handleAddressChange = async (address: string) => {
    if (!address) return;

    const geocoder = new google.maps.Geocoder();
    try {
      const result = await geocoder.geocode({ address: `${address}, Marseille, France` });
      if (result.results[0]) {
        const location = result.results[0].geometry.location;
        const newPosition = {
          lat: location.lat(),
          lng: location.lng()
        };

        setSelectedLocation(newPosition);
        updateMarkersAndRoute(newPosition, address);
      }
    } catch (error) {
      setError(error as string);
    }
  };

  const updateMarkersAndRoute = async (position: LatLng, title: string) => {
    const newMarkers = [...mapMarkers];
    if (newMarkers.length > 0) {
      newMarkers[newMarkers.length - 1].icon = '/assets/icons/maps/dynamic/circuit-point.svg';
    }

    const newMarker: RouteMarker = {
      id: `point-${Date.now()}`,
      position,
      title,
      icon: '/assets/icons/maps/dynamic/circuit-end.svg',
      color: StatusColor.PRIMARY
    };

    newMarkers.push(newMarker);
    setMapMarkers(newMarkers);

    if (newMarkers.length >= 2) {
      await calculateRoute(newMarkers);
    }
  };

  const calculateRoute = async (markers: RouteMarker[]) => {
    if (!window.google || markers.length < 2) return;

    const directionsService = new google.maps.DirectionsService();
    try {
      const result = await directionsService.route({
        origin: new google.maps.LatLng(markers[0].position.lat, markers[0].position.lng),
        destination: new google.maps.LatLng(
          markers[markers.length - 1].position.lat,
          markers[markers.length - 1].position.lng
        ),
        waypoints: markers.slice(1, -1).map(marker => ({
          location: new google.maps.LatLng(marker.position.lat, marker.position.lng),
          stopover: true
        })),
        travelMode: google.maps.TravelMode.DRIVING,
        optimizeWaypoints: false
      });

      setDirectionsResult(result);
    } catch (error) {
      console.error('Error calculating route:', error);
    }
  };

  const getMarkerIcon = (index: number, total: number) => {
    if (index === 0) return '/assets/icons/maps/dynamic/circuit-start.svg';
    if (index === total - 1) return '/assets/icons/maps/dynamic/circuit-end.svg';
    return '/assets/icons/maps/dynamic/circuit-point.svg';
  };

  const handleValidateClick = async () => {
    try {
      if (!selectedLocation) {
        alert('Veuillez sélectionner un emplacement sur la carte');
        return;
      }

      const values = formik.values;
      const selectedPassenger = MOCK_PASSENGERS.find(p => p.id.toString() === values.user);

      const pointRequest = {
        tripId: trajetId,
        title: values.endPoint || selectedPassenger?.name || '',
        label: values.endPoint || selectedPassenger?.name || '',
        passengerId: selectedPassenger?.id,
        passengerName: selectedPassenger?.name,
        usage: 'STOP' as const,
        address: {
          fullAddress: values.endPointAddress.address || "Address not specified"
        },
        latitude: selectedLocation.lat,
        longitude: selectedLocation.lng,
        coordinates: [selectedLocation.lng, selectedLocation.lat] as [number, number],
        sequenceOrder: (mapMarkers.length || 0) + 1,
        arrivalTime: "08:15",
        departureTime: "08:20",
        distanceFromPreviousPoint: 0,
        timeFromPreviousPoint: 0,
        isTemporaryForUser: Boolean(values.user)
      };

      await addTripPoint(pointRequest);

      const newMarker: RouteMarker = {
        id: `point-${Date.now()}`,
        position: {
          lat: selectedLocation.lat,
          lng: selectedLocation.lng
        },
        title: values.endPoint || selectedPassenger?.name || '',
        icon: '/assets/icons/maps/dynamic/circuit-end.svg',
        color: StatusColor.PRIMARY
      };

      if (onPointAdded) {
        onPointAdded(newMarker);
      }

      onClose();
    } catch (error) {
      alert('Erreur lors de l\'ajout du point');
    }
  };

  const renderField = (field: FormFieldType<IAddPoint>) => {
    if (field.name === 'user') {
      return (
        <FormField
          field={{
            ...field,
            type: 'select',
            options: MOCK_PASSENGERS.map(p => ({
              value: p.id.toString(),
              label: p.name
            }))
          }}
          value={formik.values.user}
          onChange={(name, value) => formik.setFieldValue(name, value)}
          error={formik.touched.user ? formik.errors.user : undefined}
          onBlur={formik.handleBlur}
          isReadOnly={false}
        />
      );
    }

    if (field.name === 'endPointAddress') {
      return (
        <FormField
          field={field}
          value={formik.values.endPointAddress.address}
          onChange={(name, value) => {
            formik.setFieldValue(name, { ...formik.values.endPointAddress, address: value });
            handleAddressChange(value);
          }}
          error={formik.touched.endPointAddress ? formik.errors.endPointAddress as string : undefined}
          onBlur={formik.handleBlur}
          isReadOnly={false}
        />
      );
    }

    return (
      <FormField
        field={field}
        value={formik.values[field.name as keyof IAddPoint]}
        onChange={(name, value) => formik.setFieldValue(name, value)}
        error={formik.touched[field.name as keyof IAddPoint] ? formik.errors[field.name as keyof IAddPoint] as string : undefined}
        onBlur={formik.handleBlur}
        isReadOnly={false}
      />
    );
  };

  return (
    <Dialog open={open} onClose={onClose} fullWidth maxWidth="xl">
      <DialogTitle>
        <Typography variant="h5" color="primary.main">Ajout d&apos;un point</Typography>
      </DialogTitle>
      <DialogContent>
        <Box sx={{ my: 2, p: 1.5, bgcolor: "primary.lighter", borderRadius: "12px" }}>
          <Typography color="primary.main">
            vous ne devez renseigner qu&apos;un seul champ parmis les 4
          </Typography>
        </Box>

        <form>
          <Grid container spacing={2}>
            {addPointFormFields.map((field, index) => (
              <Grid item key={index} xs={12}>
                {renderField(field)}
              </Grid>
            ))}

            <Grid item xs={12}>
              <Box sx={{ width: '100%', height: '360px', border: '1px solid #e0e0e0', borderRadius: 1 }}>
                <MapView
                  height="360px"
                  width="100%"
                  Submodule={MapType.CIRCUIT}
                  routes={[]}
                  onMapClick={handleMapClick}
                  markers={mapMarkers}
                  defaultCenter={{ lat: 43.296482, lng: 5.369780 }}
                  defaultZoom={13}
                >

                  <ConditionalComponent isValid={!!directionsResult}>
                    <DirectionsRenderer
                      directions={directionsResult!}
                      options={{
                        suppressMarkers: true,
                        preserveViewport: true,
                        polylineOptions: {
                          strokeColor: StatusColor.PRIMARY,
                          strokeOpacity: 0.7,
                          strokeWeight: 5,
                        },
                      }}
                    />
                  </ConditionalComponent>
                </MapView>
              </Box>
            </Grid>

            <Grid item xs={12}>
              <Box display="flex" justifyContent="flex-end" gap={2}>
                <Button
                  variant="outlined"
                  onClick={onClose}
                  sx={outlinedColor}
                >
                  Annuler
                </Button>
                <Button
                  onClick={handleValidateClick}
                  variant="contained"
                  sx={mainColor}
                >
                  Valider
                </Button>
              </Box>
            </Grid>
          </Grid>
        </form>
      </DialogContent>
    </Dialog>
  );
}

