import 'maplibre-gl/dist/maplibre-gl.css';

import React, {
  forwardRef,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';

import {
  Save,
  XIcon,
} from 'lucide-react';
import maplibregl from 'maplibre-gl';
import { Protocol } from 'pmtiles';
import { IoPinSharp } from 'react-icons/io5';
import Map, { Marker } from 'react-map-gl/maplibre';

import { rpc } from '@/api/request';
import { GeopointType } from '@/api/types';
import { Button } from '@/components/ui/button';
import {
  MobileFab,
  MobileLink,
  MobileNavbar,
  MobilePage,
  MobilePopup,
} from '@/components/ui/mobile';
import { SystemWindowDialog } from '@/components/ui/system-window-dialog';
import { Lang } from '@/lang/Lang';
import { cn } from '@/lib/utils';
import useAppConfigStore, { useAppConfig } from '@/stores/appConfig';

const MAP_PROTOMAP_STYLE_LIGHT =
  'https://s3.twcstorage.ru/cp98834-apptor_storage/protomap/2gislight.json';

const MAP_PROTOMAP_STYLE_DARK =
  'https://s3.twcstorage.ru/cp98834-apptor_storage/protomap/2gisdark.json';


export const geoSelectMapCommandRef = React.createRef<GeoSelectMapCommandRefProps>();

type GeoSelectMapCommandRefProps = {
  open: (onSelect: (item: GeopointType) => void, init?: GeopointType) => void;
  close: () => void;
}

function SelectedAddressBlock({
  findItem,
  loading,
  className,
}: {
  findItem: GeopointType | null;
  loading: boolean;
  className?: string;
}) {
  return (
    <div
      className={cn('shrink-0 border-b px-4 py-3', loading && 'animate-pulse', className)}
    >
      <div className="font-medium">{findItem?.name ?? findItem?.address}</div>
      {findItem?.context ? (
        <div className="text-sm text-gray-500">{findItem.context}</div>
      ) : null}
    </div>
  );
}

export const GeoSelectMapCommand = forwardRef<GeoSelectMapCommandRefProps, {}>((_, ref) => {



  const { isMobile } = useAppConfigStore();


  const [findItem, setFindItem] = useState<GeopointType | null>(null);

  const [open, setOpen] = useState(false);

  const onSelectRef = useRef<((item: GeopointType) => void) | null>(null);
  useImperativeHandle(ref, () => ({
    open: (onSelect: (item: GeopointType) => void, init?: GeopointType) => {
      setFindItem(init ?? null);
      setOpen(true);
      onSelectRef.current = onSelect;
    },
    close: () => {
      setOpen(false);
    }
  }));






  const { isDarkTheme } = useAppConfigStore();

  const [clickCoords, setClickCoords] = useState<{ lng: number, lat: number } | null>(null);

  const { color } = useAppConfig();

  useEffect(() => {
    if (clickCoords) {


      rpc.geocode({
        byCoords: {
          latitude: clickCoords.lat,
          longitude: clickCoords.lng,
        },
      }).then((res) => {
        setFindItem(res?.result?.[0] ?? null);
      }).finally(() => {
        setClickCoords(null);
      })

    }
  }, [clickCoords]);

  useEffect(() => {
    let protocol = new Protocol();
    maplibregl.addProtocol("pmtiles", protocol.tile);
    return () => {
      maplibregl.removeProtocol("pmtiles");
    }
  }, []);

  if (isMobile) {
    return <MobilePopup opened={open} onBackdropClick={() => setOpen(false)} >
      <MobilePage className="flex flex-col">
        <MobileNavbar
          title={Lang.key('select_address_on_map')}
          right={<MobileLink onClick={() => setOpen(false)}><XIcon /></MobileLink>}
        />

        <SelectedAddressBlock
          findItem={findItem}
          loading={clickCoords != null}
          className="text-center"
        />

        <Map
          initialViewState={{
            longitude: findItem?.lng ?? 0,
            latitude: findItem?.lat ?? 0,
            zoom: 14,
          }}
          onClick={(e) => {
            const { lng, lat } = e.lngLat;
            setClickCoords({ lng, lat });
          }}
          style={{
            width: '100%',
            flex: 1,
            minHeight: 0,
          }}
          // Растровые тайлы OSM
          mapStyle={isDarkTheme ? MAP_PROTOMAP_STYLE_DARK : MAP_PROTOMAP_STYLE_LIGHT}
        >
          {!clickCoords && findItem?.lat != null && findItem?.lng != null && (
            <Marker
              longitude={findItem.lng}
              latitude={findItem.lat}
              anchor="bottom"
            >
              <IoPinSharp color={color} size={40} />
            </Marker>
          )}

          {clickCoords && (
            <Marker
              longitude={clickCoords.lng}
              latitude={clickCoords.lat}
              anchor="bottom"

            >
              <IoPinSharp
                className='animate-pulse'
                color={color} size={40} />
            </Marker>
          )}
        </Map>

        <div className='text-xs text-gray-500 p-2 text-center'>{Lang.key("click_on_map_to_select_location")}</div>


        <MobileFab
          disabled={!findItem || clickCoords != null}
          text={Lang.key("save")}
          className='fixed left-1/2 bottom-safe-4 transform -translate-x-1/2 z-20'
          icon={<Save size={20} />}
          onClick={() => {
            if (onSelectRef.current) {
              onSelectRef.current(findItem!);
            }
            setOpen(false);
          }}
        />



      </MobilePage>
    </MobilePopup>
  }

  return (

    <SystemWindowDialog
      open={open}
      onOpenChange={setOpen}
      title={Lang.key('select_address_on_map')}
      width="80vw"
      height="80vh"
      allowFullscreen
      bodyClassName="p-0 overflow-hidden flex flex-col"
      footer={
        <div className='flex flex-row gap-2 w-full justify-between items-center'>
          <div className='text-xs text-gray-500'>
            {Lang.key("click_on_map_to_select_location")}
          </div>
          <Button
            disabled={!findItem || clickCoords != null}
            variant="outline"
            onClick={() => {
              if (onSelectRef.current) {
                onSelectRef.current(findItem!);
              }
              setOpen(false);
            }}
          >
            <Save size={20} /> {Lang.key("save")}
          </Button>
        </div>
      }
    >
      <SelectedAddressBlock
        findItem={findItem}
        loading={clickCoords != null}
      />
      <Map
        initialViewState={{
          longitude: findItem?.lng ?? 0,
          latitude: findItem?.lat ?? 0,
          zoom: 14,
        }}
        onClick={(e) => {
          const { lng, lat } = e.lngLat;
          setClickCoords({ lng, lat });
        }}
        style={{
          width: '100%',
          flex: 1,
          minHeight: 0,
        }}
        // Растровые тайлы OSM
        mapStyle={isDarkTheme ? MAP_PROTOMAP_STYLE_DARK : MAP_PROTOMAP_STYLE_LIGHT}
      >
        {!clickCoords && findItem?.lat != null && findItem?.lng != null && (
          <Marker
            longitude={findItem.lng}
            latitude={findItem.lat}
            anchor="bottom"
          >
            <IoPinSharp color={color} size={40} />
          </Marker>
        )}

        {clickCoords && (
          <Marker
            longitude={clickCoords.lng}
            latitude={clickCoords.lat}
            anchor="bottom"

          >
            <IoPinSharp
              className='animate-pulse'
              color={color} size={40} />
          </Marker>
        )}
      </Map>
    </SystemWindowDialog>
  );
}
);

export default GeoSelectMapCommand;
