"use client";

import "./ReportForm.scss";
import "leaflet/dist/leaflet.css";
import Image from "next/image";
import {
  MapContainer,
  Marker,
  TileLayer,
  useMapEvents,
} from "react-leaflet";
import clip from "./icons/clip.svg";
import arrow_right from "./icons/arrow-right.svg";
import pin_image from "./icons/pin-image.svg";
import { ChangeEventHandler, useState } from "react";
import { Icon } from "leaflet";
import pin_icon from "./icons/pin_icon.svg";
import axios, { AxiosError } from "axios";
import { apiInstance } from "@/shared/config/apiConfig";
import { useSession } from "next-auth/react";
import { IDisplayMap } from "@/shared/types/map-type";
import { useRouter } from "next/navigation";
import Loader from "@/shared/ui/components/Loader/Loader";

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

const ReportForm = () => {
  const session = useSession();
  const router = useRouter();
  const [latLng, setLatLng] = useState<ILatLng[]>([]);
  const [displayLatLng, setDisplayLatLng] = useState<string[]>([]);
  const [images, setImages] = useState<File[]>([]);
  const position = {
    lat: 42.8746,
    lng: 74.606,
  };
  const [loader, setLoader] = useState<boolean>(false);
  const [locationWarning, setLocationWarning] = useState<string>("");
  const [descriptionWarning, setDescriptionWarning] =
    useState<string>("");
  const [imageWarning, setImageWarning] = useState<string>("");
  const [error, setError] = useState<string>("");

  const customIcon = new Icon({
    iconUrl: pin_icon.src,
    iconSize: [32, 32],
  });

  const handleImages: ChangeEventHandler<HTMLInputElement> = (e) => {
    if (e.target.files) {
      const getArrayFromObject = Array.from(e.target.files);
      setImages(getArrayFromObject);
    }
  };

  const deleteImage = (name: string) => {
    setImages((prev) => prev.filter((img) => img.name !== name));
  };

  const createReport: React.MouseEventHandler<
    HTMLFormElement
  > = async (e) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);

    if (displayLatLng.length === 0) {
      setDescriptionWarning("");
      setImageWarning("");
      setError("");
      setLocationWarning("Выберите хотя бы одну точку!");
      return;
    }

    if (!formData.get("description")) {
      setLocationWarning("");
      setImageWarning("");
      setError("");

      setDescriptionWarning("Пожалуйста опишите свое обращение");
      return;
    }

    if (images.length === 0) {
      setLocationWarning("");
      setDescriptionWarning("");
      setError("");

      setImageWarning("Загрузите по меньшей мере одну фотографию");
      return;
    }

    setLocationWarning("");
    setDescriptionWarning("");
    setError("");
    setImageWarning("");

    const Authorization = `Bearer ${session.data?.access_token}`;
    const config = {
      headers: {
        Authorization,
      },
    };

    images.forEach((image) => {
      formData.append("image", image);
    });
    formData.append("latitude1", latLng[0].lat.toString());
    formData.append("longitude1", latLng[0].lng.toString());
    formData.append("latitude2", latLng[1].lat.toString());
    formData.append("longitude2", latLng[1].lng.toString());

    try {
      setLoader(true);
      const res = await apiInstance.post(
        "/report/create/",
        formData,
        config
      );

      if ([200, 201].includes(res.status)) {
        router.push("/");
      }
    } catch (error: unknown) {
      if (error instanceof AxiosError) {
        setError(error.message);
      } else {
        setError("Произошла непредвиденная ошибка");
      }
    } finally {
      setLoader(false);
    }
  };

  const MapPins = (e: any) => {
    useMapEvents({
      click(e) {
        if (latLng.length < 2) {
          setLatLng([...latLng, e.latlng]);

          axios
            .get(
              `https://nominatim.openstreetmap.org/reverse?lat=${e.latlng.lat}&lon=${e.latlng.lng}&format=json`
            )
            .then((res) =>
              setDisplayLatLng([
                ...displayLatLng,
                res.data.display_name,
              ])
            )
            .catch((error) => console.log(error));
        }
      },
    });

    const removeMarker = (latLng: { lat: number; lng: number }) => {
      setLatLng((prev) => prev.filter((l) => l !== latLng));

      axios
        .get<IDisplayMap>(
          `https://nominatim.openstreetmap.org/reverse?lat=${latLng.lat}&lon=${latLng.lng}&format=json`
        )
        .then((res) =>
          setDisplayLatLng((prev) =>
            prev.filter((loc) => loc !== res.data.display_name)
          )
        )
        .catch((error) => console.log(error));
    };

    return latLng.map((l) => (
      <Marker
        eventHandlers={{
          click: () => {
            removeMarker(l);
          },
        }}
        key={l.lat}
        icon={customIcon}
        position={l}
      />
    ));
  };

  return (
    <form onSubmit={createReport} className="report-form">
      <div className="report-form__input">
        <label>Адрес</label>
        <input
          value={displayLatLng.join("; ")}
          disabled
          placeholder="Отметьте точки на карте"
          type="text"
        />
        {locationWarning ? <p>{locationWarning}</p> : null}
      </div>

      <div className="report-form__map">
        <MapContainer
          center={position}
          zoom={14}
          scrollWheelZoom={false}
        >
          <TileLayer
            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          <MapPins />
        </MapContainer>

        <div className="report-form__info">
          <h4>Как отметить участок дороги? </h4>
          <Image src={pin_image} alt="Pin Image" />
          <p>
            Поставьте булавку и начните рисовать участок дороги{" "}
            <span>
              (он может состоять из любого количества ломаных линий)
            </span>
          </p>
          <p>Чтобы удалить отрезок нажмите на точки повторно.</p>
        </div>
      </div>

      <div className="report-form__input">
        <label>Добавьте описание проблемы</label>
        <textarea name="description" placeholder="Введите описание" />
        {descriptionWarning ? <p>{descriptionWarning}</p> : null}
      </div>

      <div className="report-form__add-images">
        <label>Добавьте фотографии</label>
        <p>
          Загрузите до 5 фотографии, связанные с дорогой, которую Вы
          хотите отметить. Фотографии помогут лучше понять проблему.
        </p>
        <label
          className="report-form__upload"
          htmlFor="report-form-upload"
        >
          <Image src={clip} alt="Paper Clip Icon" />
          Прикрепить файл
          <span>(до 5 МБ)</span>
        </label>
        {imageWarning ? (
          <p className="report-form__add-images-error">
            {imageWarning}
          </p>
        ) : null}

        <input
          onChange={handleImages}
          multiple
          type="file"
          id="report-form-upload"
        />
        {images.length ? (
          <div className="report-form__images">
            {images.map((image) => (
              <div key={image.name}>
                <img
                  src={URL.createObjectURL(image)}
                  alt="Report Image"
                />
                <button onClick={() => deleteImage(image.name)}>
                  удалить
                </button>
              </div>
            ))}
          </div>
        ) : null}
      </div>
      <button disabled={loader} type="submit">
        {loader ? <Loader /> : "Отправить на модерацию"}
        <Image src={arrow_right} alt="Arrow Right Icon" />
      </button>
      {error ? <p className="report-form__error">{error}</p> : null}
    </form>
  );
};

export default ReportForm;
