import { useRef } from 'react';
import { useLanguage } from './LanguageContext';
import { CircleMarker, Marker, Popup } from 'react-leaflet';
import { Button, Checkbox, FormControl, InputLabel, ListItemText, MenuItem, Select, Slider, Typography, type SelectChangeEvent } from '@mui/material';
import { purposes } from '../constants/purposes';
import { translations } from '../constants/translations';
import { pointIconBlue, pointIconGreen, pointIconRed } from '../icons/PointIcons';
import { TiDelete } from 'react-icons/ti';
import type { FlightPoint, MovingPointInfo } from '../types';
import type L from 'leaflet';

interface MapPointProps {
  map: HTMLElement | null;
  point: FlightPoint;
  points: FlightPoint[];
  index: number;
  setDraggablePoints: React.Dispatch<React.SetStateAction<FlightPoint[]>>;
  setPoints: React.Dispatch<React.SetStateAction<FlightPoint[]>>;
  setMovingPoint: React.Dispatch<React.SetStateAction<MovingPointInfo | null>>;
  removePoint: (id: string) => void;
}

export default function MapPoint({
  map,
  point,
  points,
  index,
  setDraggablePoints,
  setPoints,
  setMovingPoint,
  removePoint,
}: MapPointProps) {
  const { targetLanguage } = useLanguage();
  const t = translations[targetLanguage];
  const markerRef = useRef<L.Marker>(null);

  const handleDrag = (e: L.LeafletEvent) => {
    const updatedPoints = [...points];
    updatedPoints[index] = {
      ...updatedPoints[index],
      position: (e.target as L.Marker).getLatLng(),
    };
    setDraggablePoints(updatedPoints);
  };

  const handleDragEnd = (e: L.LeafletEvent) => {
    const updatedPoints = [...points];
    updatedPoints[index] = {
      ...updatedPoints[index],
      position: (e.target as L.Marker).getLatLng(),
    };
    setPoints(updatedPoints);
  };

  const setPointPosition = (e: L.LeafletEvent) => {
    const marker = markerRef.current;
    if (!marker || !map) return;

    const markerElement = (marker as unknown as { _icon: HTMLElement })._icon;
    if (!markerElement) return;

    const mapRect = map.getBoundingClientRect();
    const markerRect = markerElement.getBoundingClientRect();

    const screenWidth = window.innerWidth;
    let displacementX = 150;
    let displacementY = 150;
    if (screenWidth < 1024) {
      displacementX = 70;
      displacementY = 70;
    }

    const offsetX = markerRect.left - mapRect.left + markerRect.width > mapRect.width / 2
      ? -displacementX : displacementX + 50;
    const offsetY = markerRect.top + markerRect.height > mapRect.height / 2
      ? -displacementY : displacementY;

    const x = markerRect.left - mapRect.left + offsetX;
    const y = markerRect.top - mapRect.top + offsetY;

    setMovingPoint({
      x,
      y,
      latlng: (e.target as L.Marker).getLatLng(),
    });
  };

  const handleChangeAltitude = (newAltitude: number) => {
    const updatedPoints = [...points];
    updatedPoints[index] = { ...updatedPoints[index], altitude: newAltitude };
    setPoints(updatedPoints);
  };

  const handlePurposeChange = (e: SelectChangeEvent<string[]>) => {
    const value = e.target.value;
    const updatedPoints = [...points];
    updatedPoints[index] = {
      ...updatedPoints[index],
      meta: typeof value === 'string' ? value.split(',') : value,
    };
    setPoints(updatedPoints);
  };

  return (
    <Marker
      key={point.id}
      position={point.position}
      icon={index === 0 ? pointIconGreen : index === points.length - 1 ? pointIconRed : pointIconBlue}
      draggable={true}
      eventHandlers={{
        drag: (event) => handleDrag(event),
        dragend: (event) => handleDragEnd(event),
        move: (e) => setPointPosition(e),
        moveend: () => { setMovingPoint(null); },
      }}
      ref={markerRef}
    >
      <CircleMarker center={point.position} radius={35} stroke={false} />
      <Popup className='popup'>
        {t.point} {index + 1}
        <br />
        <Typography variant='subtitle2'>{t.height} </Typography>
        <Slider
          value={point.altitude}
          onChange={(_e, value) => handleChangeAltitude(value as number)}
          min={0}
          max={3000}
          step={1}
          valueLabelDisplay="auto"
          className='popup-slider'
        />
        <br />
        <FormControl fullWidth margin="none">
          <InputLabel id="popup-purpose-label" className="form-label">{t.purpose}</InputLabel>
          <Select
            labelId="popup-purpose-label"
            label={t.purpose}
            multiple
            value={point.meta}
            onChange={(e) => handlePurposeChange(e as SelectChangeEvent<string[]>)}
            renderValue={(selected) => (selected as string[]).map(val => t.options[val]).join(', ')}
            style={{ height: '40px' }}
          >
            {purposes.map((option) => (
              <MenuItem key={option.value} value={option.value}>
                <Checkbox checked={point.meta.indexOf(option.value) > -1} />
                <ListItemText primary={t.options[option.value]} />
              </MenuItem>
            ))}
          </Select>
        </FormControl>
        <Button onClick={() => { removePoint(point.id); }}>
          {t.removePoint}
          <TiDelete size={24} />
        </Button>
      </Popup>
    </Marker>
  );
}
