import React, { useEffect, useState } from 'react';
import { MapContainer, TileLayer, Marker, CircleMarker, Popup, Polyline, LayerGroup, GeoJSON, } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import L, { LatLngBounds } from 'leaflet';
import Contacts from './Contacts';
import type { User, Node, Retailer, Maker, Product, Dispatch, DispatchStatus } from '../astroTypes';

import { useQuery, useMutation, useQueryClient, queryOptions } from "@tanstack/react-query";
import { useGetMakers, useGetDispatches, useGetRetailers, useGetUser, useGetMyself } from "../utils/hooks"

import { Button, buttonVariants } from './ui/Button';

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { LoginForm } from './LoginForm';
import { hasAuthCookie } from '@/utils/authUtils';

//Payload longitude and latitude are mislabeled in payload (lol)
const locationSwitcharoo = (location: number[]) => {
  if (location.length === 2) {
    const correctedLocation = [location[1], location[0]]
    return correctedLocation;
  }
  console.error("locationSwitcharoo: Location array malformed")
  return location
}


const dashArrays: Record<DispatchStatus, string> = {
  requested: '20, 10',
  accepted: '0, 0',
  archived: '1, 5',
}

const dashColors: Record<DispatchStatus, string> = {
  requested: '#000',
  accepted: '#000',
  archived: '#000',
}

const dashColorSelected: string = '#f87171' //same as tw red 400

const dashOpacities: Record<DispatchStatus, number> = {
  requested: 0.7,
  accepted: 0.7,
  archived: 0.5
}

interface NodeSelection {
  id: string,
  type: "maker" | "retailer" | "dispatch" | "none"
}

export const KiosMap = () => {

  const [authToken, setAuthToken] = useState('')

  const { data: makers, isLoading: isLoadingMakers } = useGetMakers();
  const { data: retailers, isLoading: isLoadingRetailers } = useGetRetailers();
  const { data: dispatches, isLoading: isLoadingDispatches } = useGetDispatches();

  const { data: myself, isLoading: isLoadingMyself } = useGetMyself(authToken);

  const [selectedNode, setSelectedNode] = useState<NodeSelection>({ id: "", type: "none" })

  let selectedMaker: Maker | undefined = undefined;
  let selectedRetailer: Retailer | undefined = undefined;
  let selectedDispatch: Dispatch | undefined = undefined;

  if (selectedNode.type === "maker" && makers) {
    selectedMaker = makers.find(maker => maker.id === selectedNode.id && selectedNode.type === "maker");
  }

  if (selectedNode.type === "retailer" && retailers) {
    selectedRetailer = retailers.find(retailer => retailer.id === selectedNode.id && selectedNode.type === "retailer");
  }

  if (selectedNode.type === "dispatch" && dispatches) {
    selectedDispatch = dispatches.find(dispatch => dispatch.id === selectedNode.id && selectedNode.type === "dispatch");
  }


  const handleSelectNode = (nodeId: string, typeParam: "maker" | "retailer" | "dispatch" | "none") => {
    setSelectedNode({ id: nodeId, type: typeParam })
    console.log("set id:", nodeId)
  }

  //params: dispatch: Dispatch, courier: User
  const handleAcceptRoute = () => {

  }

  const handleOpenCatalogue = () => {
  }

  //params
  const handleRequestProduct = () => {

  }

  const blackDotIcon = L.divIcon({
    className: 'bg-gray-950 rounded-full',
    iconSize: [20, 20],
    iconAnchor: [10, 10]
  });

  const selectedDotIcon = L.divIcon({
    className: 'bg-red-400 rounded-full ring-offset-2 ring-4 ring-red-400 ring-dashed',
    iconSize: [20, 20],
    iconAnchor: [10, 10]
  });



  const bounds = new LatLngBounds(
    [-90, -180], // Southwest corner
    [90, 180]    // Northeast corner
  );

  return (
    <div className='flex flex-col gap-4'>
      <Dialog>
        <div className="flex justify-between items-end px-4 gap-4">
          <img
            width={120}
            src="/kios-logo.png"
            alt="" />
      
          {(myself && myself.name) 
          ?
              <p>Logged in as: {myself.name}</p>
              : <p>Logged in</p>
          }
          {
            (!hasAuthCookie() && !authToken) &&
            <DialogTrigger
              className={`px-14 w-6 ${buttonVariants({ variant: "kios" })}`}
            >
              Login
            </DialogTrigger>
          }
        </div>

        <DialogContent>
          <DialogHeader>
            <DialogTitle className="text-4xl text-center">Login</DialogTitle>
            <LoginForm setAuthToken={setAuthToken} authToken={authToken}/>
          </DialogHeader>
        </DialogContent>
      </Dialog>

      <div className='w-full flex justify-center align-middle'>
        <div className=''>
          <div>
            <img src="/route-guide.png" width={300} className="absolute right-6 top-3/4 z-[998] border border-black" alt="" />
          </div>
        </div>
        {
          selectedNode.type !== 'none' && (
            <div className='absolute bg-white border-gray-950 border-2 z-[998] left-10 top-1/5 mt-24 p-4'>
              <div className='flex gap-8 flex-col'>
                {selectedMaker !== undefined && (
                  <div className='flex gap-4 flex-col'>
                    <Contacts
                      name={selectedMaker.name}
                      email={selectedMaker.email}
                      phoneNumber={selectedMaker.phoneNumber}
                      role={'maker'}
                    />
                    {(selectedMaker.stock !== undefined && selectedMaker.stock.length > 0) &&
                      <Dialog>
                        <DialogTrigger
                          className={buttonVariants({ variant: "kios" })}
                        >
                          See catalogue
                        </DialogTrigger>

                        <DialogContent className='lg:max-w-screen-lg overflow-y-scroll max-h-screen'>
                          <DialogHeader>
                            <DialogTitle className="text-4xl underline underline-offset-2">{selectedMaker.name}'s stock</DialogTitle>
                            <ul className='flex flex-col gap-4'>
                              {selectedMaker.stock.map((product, i) => {
                                return (
                                  <li className="flex flex-row gap-4">
                                    {product.picture.url &&
                                      <img
                                        width={160}
                                        src={product.picture.url}
                                        alt={product.picture.alt || ''} />
                                    }
                                    <div className="flex flex-col pb-4">
                                      <h3 className='text-4xl text-black py-2'>
                                        {product.name}
                                      </h3>
                                      {product.weight &&
                                        <p className='text-black text-lg'
                                        >Weight: {product.weight}</p>
                                      }
                                      <Button
                                        variant={'kios'}
                                        className='w-full mt-6'
                                        onClick={() => handleRequestProduct()}
                                      >
                                        Request product
                                      </Button>
                                    </div>
                                  </li>
                                )
                              })}
                            </ul>
                          </DialogHeader>
                        </DialogContent>
                      </Dialog>
                    }
                  </div>
                )}

                {selectedRetailer !== undefined && (
                  <>
                    <Contacts
                      name={selectedRetailer.name}
                      email={selectedRetailer.email}
                      phoneNumber={selectedRetailer.phoneNumber}
                      role={'retailer'}
                    />
                  </>
                )}

                {selectedDispatch !== undefined && (
                  <div className='flex flex-col gap-8'>
                    <div>
                      <h2 className='text-xl font-bold underline-offset-2 underline py-2'>
                        Product{selectedDispatch.products.length > 1 && 's'}
                      </h2>
                      {selectedDispatch.products.map((product, i) => {
                        return (
                          <div className='flex flex-row items-center gap-4'>
                            <img
                              src={product.picture.url}
                              alt={product.picture.alt}
                              className='border-2 border-black'
                              width={60}
                            />
                            <h3 className='font-bold text-xl'>{product.name}</h3>
                          </div>
                        )
                      })}
                    </div>


                    <Contacts
                      name={selectedDispatch.maker.name}
                      email={selectedDispatch.maker.email}
                      phoneNumber={selectedDispatch.maker.phoneNumber}
                      role={'maker'}
                    />

                    <Contacts
                      name={selectedDispatch.retailer.name}
                      email={selectedDispatch.retailer.email}
                      phoneNumber={selectedDispatch.retailer.phoneNumber}
                      role={'retailer'}
                    />

                    {selectedDispatch.courier !== undefined ? (

                      <Contacts
                        name={selectedDispatch.courier.name}
                        email={selectedDispatch.courier.email}
                        phoneNumber={selectedDispatch.courier.phoneNumber}
                        role={'courier'}
                      />
                    ) :
                      <div>
                        <h2 className='text-xl font-bold underline-offset-2 underline py-2'>No courier!</h2>
                        <Button
                          variant={"kios"}
                          onClick={() => handleAcceptRoute()}
                        >
                          Accept route as courier
                        </Button>
                      </div>
                    }
                  </div>
                )}
              </div>
            </div>
          )
        }

        <MapContainer
          id="map"
          center={[-6.1815, 106.8228]}
          zoom={3}
          maxBounds={bounds} // Restrict panning beyond these bounds
          maxBoundsViscosity={0.9} // How strongly to snap the map's bounds to the restricted area
          style={{ height: '800px', width: '100%' }}
        >
          <TileLayer url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
            maxZoom={19}
            eventHandlers={{
              click: () => handleSelectNode("", "none")
            }}
            attribution='&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
          />

          {(makers && !isLoadingMakers) &&
            <LayerGroup>
              {makers.map((maker: any, index: number) => (
                <Marker
                  eventHandlers={{
                    click: () => handleSelectNode(maker.id, "maker")
                  }}
                  key={maker.id}
                  position={[locationSwitcharoo(maker.location)[0], locationSwitcharoo(maker.location)[1]]}
                  icon={selectedNode.id === maker.id ? selectedDotIcon : blackDotIcon}
                >
                  {/* <Popup>{maker.name}</Popup> */}
                </Marker>
              ))}
            </LayerGroup>
          }

          {(retailers && !isLoadingRetailers) &&
            <LayerGroup>
              {retailers.map((retailer: any, index: number) => (
                <Marker
                  eventHandlers={{
                    click: () => handleSelectNode(retailer.id, "retailer")
                  }}
                  key={retailer.id}
                  position={[locationSwitcharoo(retailer.location)[0], locationSwitcharoo(retailer.location)[1]]}
                  icon={selectedNode.id === retailer.id ? selectedDotIcon : blackDotIcon}
                >
                  {/* <Popup>{retailer.name}</Popup> */}
                </Marker>
              ))}
            </LayerGroup>
          }

          {(dispatches && !isLoadingDispatches) &&
            <LayerGroup>
              {dispatches.map((dispatch: any, index: number) => {

                if (dispatch.maker && dispatch.retailer) {

                  const start = locationSwitcharoo(dispatch.maker.location);
                  const end = locationSwitcharoo(dispatch.retailer.location);


                  let productsString = '';
                  dispatch.products.forEach((product: any, i: number) => {
                    productsString += product.productTitle + (i + 1 < dispatch.products.length ? ', ' : '');
                  });

                  //status type should already be inferred when list of dispatches is created, weird that is is required
                  const status: DispatchStatus = dispatch.status;

                  const dashArray: string = dashArrays[status]
                  const dashColor: string = dashColors[status]
                  const dashOpacity: number = dashOpacities[status]

                  return (
                    <Polyline
                      eventHandlers={{
                        click: () => handleSelectNode(dispatch.id, "dispatch")
                      }}
                      key={dispatch.id}
                      positions={[[start[0], start[1]], [end[0], end[1]]]}
                      pathOptions={{ color: selectedNode.id === dispatch.id ? dashColorSelected : dashColor }}
                      opacity={dashOpacity}
                      dashArray={dashArray} />
                  );
                }
              })}
            </LayerGroup>
          }
        </MapContainer >
      </div>
    </div>
  );
};

