import { faWindowClose } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useEffect, useState } from "react";
import "./assets/css/styles.css";
import {
  MapGoogleComponent,
  Position,
} from "../../../components/map/map_google";
import { usePlace } from "../../../../domain/useCase/usePlace";
import { languaguesList } from "../../../../core/constants/languages";
import { LoadingScreen } from "../../../components/loading_screen/loading_screen";
import { MultipleImagesDropzone } from "../../../components/multiple_images_dropzone/multiple_images_dropzone";
import {
  AvailableDays,
  availableDaysList,
  EmptyPlace,
  Place,
} from "../../../../data/datasource/api/entities/place";
import { Category } from "../../../../data/datasource/api/entities/category";
import { GeocodingGoogle } from "../../../components/geocoding/geocoding_google";
import { APIProvider } from "@vis.gl/react-google-maps";
import { LoadingSpinner } from "../../../components/loading_spinner/loading_spinner";
import { MapBoxComponent } from "../../../components/map/map_mapbox";
import { GeocodingMapbox } from "../../../components/geocoding/geocoding_mapbox";

// Interface for component props
interface props {
  setWindowVisibility: (visibility: boolean) => void;
  categoriesList: Category[];
  idTown: number;
  forceRenderList: () => void;
  isRegister: boolean;
  form?: Place;
}

// Main component for registering or updating a place
export const AdminPanelPlaceRegister = ({
  setWindowVisibility,
  idTown,
  categoriesList,
  forceRenderList,
  isRegister,
  form,
}: props) => {
  // Destructure and initialize hooks and state variables
  const {
    register,
    handleSubmit,
    errors,
    setValue,
    languageDescriptionIndexSelected,
    descriptions,
    setDescriptions,
    setLanguageDescriptionIndexSelected,
    updateTimeForm,
    availableDays,
    setAvailableDays,
    resetField,
    categoriesId,
    setCategoriesId,
    getPlaceById,
    onSubmitRegister,
    onSubmitUpdate,
    clearErrors,
    getValues,
  } = usePlace(forceRenderList, setWindowVisibility);
  const [clickedCategories, setClickedCategories] = useState<boolean[]>(
    new Array(categoriesList.length).fill(false)
  );
  const [isLoading, setIsLoading] = useState(false);
  const [actualPlace, setActualPlace] = useState<Place | null>(null);
  const [openHourInput, setOpenHourInput] = useState("");
  const [closeHourInput, setCloseHourInput] = useState("");

  // Maps state variables
  const [position, setPosition] = useState<Position | null>(null);
  const [isSearching, setIsSearching] = useState(false);

  // Function to handle category click
  const onClickCategory = (idCategory: number) => {
    const index = categoriesId.indexOf(idCategory);
    const indexList = categoriesList.findIndex(
      (category) => category.idCategory === idCategory
    );
    const clickedCategoriesBackup = clickedCategories.map(
      (clickedCategory, index) => {
        if (index === indexList) {
          return !clickedCategory;
        } else {
          return clickedCategory;
        }
      }
    );
    if (index > -1) {
      setCategoriesId(categoriesId.filter((cat) => cat !== idCategory));
    } else {
      setCategoriesId([...categoriesId, idCategory]);
    }
    setClickedCategories(clickedCategoriesBackup);
  };

  // Effect to fetch data on component mount
  useEffect(() => {
    setIsLoading(true);
    const fetchData = async () => {
      setValue("idTown", idTown);
      if (!isRegister && form) {
        const placeGetted = await getPlaceById(form.idPlace || 0);
        if (placeGetted) {
          setActualPlace(placeGetted);
          setValue("idPlace", placeGetted.idPlace);
          setValue("name", placeGetted.name);
          setValue("descriptions", placeGetted.descriptions);
          setDescriptions(placeGetted.descriptions || ["", ""]);
          setValue("openAt", placeGetted.openAt);
          setOpenHourInput(
            placeGetted.openAt < 10
              ? `0${placeGetted.openAt}:00`
              : `${placeGetted.openAt}:00`
          );
          setCloseHourInput(
            placeGetted.closeAt < 10
              ? `0${placeGetted.closeAt}:00`
              : `${placeGetted.closeAt}:00`
          );
          setValue("closeAt", placeGetted.closeAt);
          setValue("available", placeGetted.available);
          setAvailableDays(placeGetted.available);
          setPosition({
            latitude: Number(placeGetted.latitude),
            longitude: Number(placeGetted.longitude),
          });
          setValue("address", placeGetted.address);
          const clickedCategoriesBackup: boolean[] = [];
          categoriesList.forEach((category) => {
            if (placeGetted.categoriesId.indexOf(category.idCategory) > -1) {
              clickedCategoriesBackup.push(true);
            } else {
              clickedCategoriesBackup.push(false);
            }
          });
          setClickedCategories(clickedCategoriesBackup);
          setCategoriesId(placeGetted.categoriesId);
        }
      } else {
        setValue("available", availableDays, { shouldValidate: true });
      }
    };
    fetchData();
    setIsLoading(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className="place_register_wrap">
      <div className="place_register_header">
        Registra el lugar
        <FontAwesomeIcon
          icon={faWindowClose}
          className="close_btn"
          onClick={() => setWindowVisibility(false)}
        />
      </div>
      <div className="place_register_body">
        {isLoading || (!isRegister && actualPlace === null) ? (
          <LoadingScreen />
        ) : (
          <form
            onSubmit={handleSubmit(
              isRegister ? onSubmitRegister : onSubmitUpdate
            )}
          >
            <div className="inputs_container">
              <div className="input">
                <div className="input_header">Nombre del lugar</div>
                <input type="text" {...register("name")} autoComplete="off" maxLength={255}/>
                <p className="error">{errors.name?.message}</p>
              </div>

              <div className="input">
                <div className="input_header">
                  Descripción del lugar
                  <select
                    name="language_description_select"
                    onChange={(e) =>
                      setLanguageDescriptionIndexSelected(
                        Number(e.target.value)
                      )
                    }
                  >
                    {languaguesList.map((language, index) => {
                      return (
                        <option key={index} value={index}>
                          {language}
                        </option>
                      );
                    })}
                  </select>
                </div>
                {languaguesList.map((language, index) => {
                  if (index === languageDescriptionIndexSelected) {
                    return (
                      <textarea
                        id={index.toString()}
                        className="place_description"
                        value={descriptions[index]}
                        key={language}
                        maxLength={1024}
                        onChange={(e) => {
                          const updatedDescriptionsList = [...descriptions];
                          updatedDescriptionsList[index] = e.target.value;
                          setDescriptions(updatedDescriptionsList);
                          setValue("descriptions", updatedDescriptionsList, {
                            shouldValidate: true,
                          });
                        }}
                      />
                    );
                  }
                  return null;
                })}
                <p className="error">{errors.descriptions?.message}</p>
              </div>

              <div className="input">
                <div className="input_header">Horario</div>
                <div className="input_body">
                  <div>
                    Hora de apertura
                    <input
                      type="time"
                      autoComplete="off"
                      value={openHourInput}
                      onChange={(event) => {
                        setOpenHourInput(event.target.value);
                        updateTimeForm(event.target.value, true);
                      }}
                    />
                  </div>

                  <div>
                    Hora de cierre
                    <input
                      type="time"
                      autoComplete="off"
                      value={closeHourInput}
                      onChange={(event) => {
                        setCloseHourInput(event.target.value);
                        updateTimeForm(event.target.value, false);
                      }}
                    />
                  </div>
                </div>
                <p className="error">
                  {errors.openAt?.message || errors.closeAt?.message}
                </p>
                Dias disponibles
                <div
                  style={{
                    width: "100%",
                    display: "flex",
                    justifyContent: "center",
                  }}
                >
                  <div>
                    <select
                      name="days_select"
                      onChange={(e) => {
                        const selectedOption =
                          availableDaysList[Number(e.target.value)];
                        setAvailableDays(selectedOption.option);
                        resetField("startDate");
                        resetField("endDate");
                        setValue("available", selectedOption.option, {
                          shouldValidate: true,
                        });
                      }}
                    >
                      {availableDaysList.map((option, index) => {
                        return (
                          <option
                            key={index}
                            selected={option.option === actualPlace?.available}
                            value={index}
                          >
                            {option.name}
                          </option>
                        );
                      })}
                    </select>
                  </div>

                  <div>
                    {availableDays === AvailableDays.CUSTOM && (
                      <div
                        style={{
                          width: "100%",
                          display: "flex",
                          justifyContent: "center",
                          alignItems: "center",
                        }}
                      >
                        Inicio
                        <input
                          type="date"
                          defaultValue={actualPlace?.startDate
                            ?.toString()
                            .substring(0, 10)}
                          {...register("startDate")}
                        />
                        Cierre
                        <input
                          type="date"
                          defaultValue={actualPlace?.endDate
                            ?.toString()
                            .substring(0, 10)}
                          {...register("endDate")}
                        />
                      </div>
                    )}
                  </div>
                </div>
                <p className="error">
                  {errors.available?.message ||
                    errors.startDate?.message ||
                    errors.endDate?.message}
                </p>
              </div>

              <div className="input">
                <div className="input_header">Categorías</div>
                <div className="categories_cnt">
                  <div className="categories_grid">
                    {categoriesList.map((category, index) => {
                      return (
                        <div
                          className="category_item"
                          key={index}
                          onClick={() => onClickCategory(category.idCategory)}
                          style={
                            clickedCategories[index]
                              ? { border: "2px solid blue" }
                              : { border: "1px solid black" }
                          }
                        >
                          {category.nameES + "  " + category.idCategory}
                        </div>
                      );
                    })}
                  </div>
                </div>
                <p className="error">{errors.categoriesId?.message}</p>
              </div>

              <MultipleImagesDropzone
                setValue={setValue}
                imagesList={actualPlace?.imagesList}
              />
              <p className="error">{errors.imagesList?.message}</p>
              <input type="submit" />
            </div>

            <div className="map_container">
              <div className="google_map">
                {/* Asegúrate de crear el archivo de variables de entorno (.env) en el directorio raíz e 
                incluye la siguiente variable*/}
                {/* 
                  USA LO SIGUIENTE SI DESEA USAR LOS MAPAS DE GOOGLE

                  <APIProvider
                  apiKey={process.env.REACT_APP_GOOGLE_API_KEY || ""}
                >
                  <GeocodingGoogle
                    getValues={getValues}
                    register={register}
                    errors={errors}
                    setLoading={setIsSearching}
                    setPosition={setPosition}
                  />
                  {isSearching && <LoadingSpinner />}
                  <div className="map_component">
                    <MapGoogleComponent
                      setValue={setValue}
                      isLoading={isSearching}
                      position={position}
                      setPosition={setPosition}
                      clearErrors={clearErrors}
                    />
                  </div>
                </APIProvider>
                  */}
                <GeocodingMapbox
                  getValues={getValues}
                  register={register}
                  errors={errors}
                  setLoading={setIsSearching}
                  setPosition={setPosition}
                />
                <MapBoxComponent
                  setValue={setValue}
                  position={position}
                  isLoading={isSearching}
                  setPosition={setPosition}
                  clearErrors={clearErrors}
                />
              </div>
              <div className="map_error_cnt">
                <p className="error">{errors.latitude?.message}</p>
              </div>
            </div>
          </form>
        )}
      </div>
    </div>
  );
};
