// Import necessary modules and components
import { useState } from "react";
import { TownDatasourceProd } from "../../data/datasource/api/town_datasource";
import { TownRepositoryProd } from "../../data/repository/town_repository";
import { FieldErrors, Resolver, SubmitHandler, useForm } from "react-hook-form";
import { Town } from "../../data/datasource/api/entities/town";
import { toast } from "react-toastify";
import axios, { AxiosError } from "axios";
import { showErrorAxios } from "../../core/utils/Messages";
import { useGetStatesList } from "./useGetStatesList";

// Initialize data source and repository
const townDatasource = new TownDatasourceProd();
const townRepository = new TownRepositoryProd(townDatasource);

// Define resolver for form validation
const resolver: Resolver<Town> = async (data) => {
  const errors: FieldErrors<Town> = {};

  // Validate town name
  if (!data.name) {
    errors.name = {
      type: "required",
      message: "El nombre del pueblo es requerido",
    };
  } else if (data.name.length > 255) {
    errors.name = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 255 caracteres",
    };
  }

  // Validate state ID
  if (!data.idState) {
    errors.state = {
      type: "required",
      message: "Debe seleccionar el estado al que pertenece el pueblo",
    };
  }

  // Validate Spanish description
  if (!data.descriptionES) {
    errors.descriptionES = {
      type: "required",
      message: "La descripción del pueblo en español es requerida",
    };
  } else if (data.descriptionES.length > 1024) {
    errors.descriptionES = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 1024 caracteres",
    };
  }

  // Validate English description
  if (!data.descriptionEN) {
    errors.descriptionEN = {
      type: "required",
      message: "La descripción del pueblo en inglés es requerida",
    };
  } else if (data.descriptionEN.length > 1024) {
    errors.descriptionEN = {
      type: "maxLength",
      message: "El tamaño no debe sobrepasar los 1024 caracteres",
    };
  }

  // Validate image URL
  if (!data.imageURL) {
    errors.imageURL = {
      type: "required",
      message: "Debe seleccionar la imagen representativa del pueblo",
    };
  }

  return {
    values: Object.keys(errors).length > 0 ? {} : data,
    errors: errors,
  };
};

// Custom hook for town-related operations
export const useTown = (
  forceRenderList?: () => void,
  closeActualWindow?: () => void
) => {
  // Initialize form and state management
  const {
    register,
    handleSubmit,
    formState: { errors },
    setValue,
  } = useForm<Town>({ resolver });
  const [townsList, setTownsList] = useState<Town[]>([]);
  const { getStateById } = useGetStatesList();

  // Function to handle town registration
  const onSubmitRegister: SubmitHandler<Town> = (data: Town) => {
    const fetch = async () => {
      try {
        await townRepository.registerTown(data);
        if (forceRenderList && closeActualWindow) {
          forceRenderList();
          closeActualWindow();
        }
      } catch (error: any) {
        let errorMessage: string = "Ha ocurrido un error";
        if (axios.isAxiosError(error)) {
          error as AxiosError;
          switch (error.code) {
            case axios.AxiosError.ERR_BAD_REQUEST:
              errorMessage = "Acceso no autorizado";
              break;
            case axios.AxiosError.ERR_NETWORK:
              errorMessage = "Conexión con el servidor fallida";
              break;
          }
        }
        throw new Error(errorMessage);
      }
    };
    toast.promise(fetch(), {
      pending: "Subiendo datos...",
      success: "Los datos se han subido correctamente",
      error: {
        render({ data }) {
          return (data as Error).message;
        },
      },
    });
  };

  // Function to handle town update
  const onSubmitUpdate: SubmitHandler<Town> = (data: Town) => {
    const fetch = async () => {
      try {
        await townRepository.updateTown(data);
        if (forceRenderList && closeActualWindow) {
          forceRenderList();
          closeActualWindow();
        }
      } catch (error: any) {
        let errorMessage: string = "Ha ocurrido un error";
        if (axios.isAxiosError(error)) {
          error as AxiosError;
          switch (error.code) {
            case axios.AxiosError.ERR_BAD_REQUEST:
              errorMessage = "Acceso no autorizado";
              break;
            case axios.AxiosError.ERR_NETWORK:
              errorMessage = "Conexión con el servidor fallida";
              break;
          }
        }
        throw new Error(errorMessage);
      }
    };
    toast.promise(fetch(), {
      pending: "Subiendo datos...",
      success: "Los datos se han subido correctamente",
      error: {
        render({ data }) {
          return (data as Error).message;
        },
      },
    });
  };

  // Function to get towns by state
  const getTownsByState = async (stateId: number, stateName: string) => {
    try {
      const towns = await townRepository.getTownsByState(stateId, stateName);
      setTownsList(towns);
    } catch (error: any) {
      if (axios.isAxiosError(error)) {
        error as AxiosError;
        showErrorAxios(error);
      }
    }
  };

  // Function to get town by ID
  const getTownById = async (idTown: number): Promise<Town | null> => {
    try {
      const town = await townRepository.getTown(idTown);
      const state = await getStateById(town.idState);
      if (state) {
        town.state = state.name;
      }
      return town;
    } catch (error: any) {
      if (axios.isAxiosError(error)) {
        error as AxiosError;
        showErrorAxios(error);
      }
    }
    return null;
  };

  return {
    register,
    handleSubmit,
    errors,
    onSubmitRegister,
    onSubmitUpdate,
    setValue,
    townsList,
    getTownsByState,
    setTownsList,
    getTownById,
  };
};
