"use client";

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useAtom } from "jotai";
import { useRouter, useParams } from "next/navigation";
import { useEffect } from "react";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";

import categoryApi from "@/shared/services/category";
import classificationApi from "@/shared/services/classification";
import mapProjectionSystemApi from "@/shared/services/map-projection-system";
import organizationApi from "@/shared/services/organization";
import mapSourceApi from "@/shared/services/map-source";
import mapsetApi from "@/shared/services/mapset";

import { MapsetInfoForm } from "../../_components/form/mapset-info-form";
import { MapsetMetadataForm } from "../../_components/form/mapset-metadata-form";
import { MapsetVersionForm } from "../../_components/form/mapset-version-form";
import MapsetTab from "../../_components/form/mapset-tab";

import { PaginatedResponse } from "@/shared/types/api-response";
import { MapsetSubmitPayload } from "@/shared/types/mapset";
import StatusValidation from "@/shared/config/status-validation";
import { activeTabAtom, mapsetFormAtom, MapsetFormState, MapsetFormTab } from "../../state";
import PageHeader from "../../../_components/page-header";
import { MapsetClassificationForm } from "../../_components/form/mapset-classification-form";
import { useAuthSession } from "@/shared/hooks/use-session";

interface SelectOption {
  id: string;
  name: string;
}

export default function EditMapsPageClient() {
  const router = useRouter();
  const params = useParams();
  const mapsetId = params.id as string;
  const queryClient = useQueryClient();
  const [activeTab, setActiveTab] = useAtom(activeTabAtom);
  const [formState, setFormState] = useAtom(mapsetFormAtom);

  const { session } = useAuthSession();
  const isDataManager = session?.user?.role?.name === "data_manager";

  const {
    data: mapset,
    isLoading: isLoadingMapset,
    refetch,
  } = useQuery({
    queryKey: ["mapset", mapsetId],
    queryFn: () => mapsetApi.getMapsetById(mapsetId),
    enabled: !!mapsetId && !!session?.user,
  });

  useEffect(() => {
    if (mapsetId && session?.user?.role?.name) {
      refetch();
    }
  }, [mapsetId, session, refetch]);

  const { data: projectionSystemsResponse, isLoading: isLoadingProjections } = useQuery({
    queryKey: ["projectionSystems"],
    queryFn: () => mapProjectionSystemApi.getMapProjectionSystems(),
    staleTime: 5 * 60 * 1000,
    refetchOnMount: false,
    enabled: !!session?.user,
  });

  const { data: categoriesResponse, isLoading: isLoadingCategories } = useQuery({
    queryKey: ["categories"],
    queryFn: () => categoryApi.getCategories(),
    staleTime: 5 * 60 * 1000,
    refetchOnMount: false,
    enabled: !!session?.user,
  });

  const { data: classificationsResponse, isLoading: isLoadingClassifications } = useQuery({
    queryKey: ["classifications"],
    queryFn: () => classificationApi.getClassifications(),
    staleTime: 5 * 60 * 1000,
    refetchOnMount: false,
    enabled: !!session?.user,
  });

  const { data: organizationsResponse, isLoading: isLoadingOrganizations } = useQuery({
    queryKey: ["organizations"],
    queryFn: () => organizationApi.getOrganizations(),
    staleTime: 5 * 60 * 1000,
    refetchOnMount: false,
    enabled: !!session?.user,
  });

  const { data: mapSourcesResponse, isLoading: isLoadingMapSources } = useQuery({
    queryKey: ["map-sources"],
    queryFn: () => mapSourceApi.getMapSources(),
    staleTime: 5 * 60 * 1000,
    refetchOnMount: false,
    enabled: !!session?.user,
  });

  useEffect(() => {
    if (mapset) {
      const geoserverSource = mapset.sources.find((source) => source.url?.includes("geoserver"));

      const geonetworkSource = mapset.sources.find((source) => source.url?.includes("geonetwork"));
      setFormState({
        info: {
          name: mapset.name,
          description: mapset.description,
          scale: mapset.scale,
          projection_system_id: mapset?.projection_system?.id,
          category_id: mapset?.category?.id,
          data_status: mapset.data_status,
          classification_id: mapset?.classification?.id,
          organization_id: mapset?.producer?.id,
          is_popular: mapset.is_popular,
          layer_type: mapset?.layer_type,
        },
        metadata: {
          source_id: geoserverSource?.id || null,
          layer_url: mapset.layer_url,
          metadata_source_id: geonetworkSource?.id || null,
          metadata_url: mapset.metadata_url,
        },
        classification: {
          coverage_level: mapset.coverage_level,
          coverage_area: mapset.coverage_area,
        },
        version: {
          data_update_period: mapset.data_update_period,
          data_version: mapset.data_version,
        },
      });
    }
  }, [mapset, setFormState]);

  useEffect(() => {
    if (session?.user && !mapset && !isLoadingMapset) {
      const currentUrl = window.location.pathname + window.location.search;
      router.replace(currentUrl);
    }
  }, [session, mapset, isLoadingMapset, router]);

  const isLoading =
    isLoadingMapset ||
    isLoadingProjections ||
    isLoadingCategories ||
    isLoadingClassifications ||
    isLoadingOrganizations ||
    isLoadingMapSources ||
    !projectionSystemsResponse ||
    !categoriesResponse ||
    !classificationsResponse ||
    !organizationsResponse ||
    !mapSourcesResponse;

  const mapDataToOptions = <T extends { id: string; name: string }>(response: PaginatedResponse<T[]> | undefined): SelectOption[] => {
    if (!response || !response.items) return [];
    return response.items.map((item) => ({ id: item.id, name: item.name }));
  };

  const projectionSystemOptions = mapDataToOptions(projectionSystemsResponse);
  const categoryOptions = mapDataToOptions(categoriesResponse);
  const classificationOptions = mapDataToOptions(classificationsResponse);
  const organizationOptions = mapDataToOptions(organizationsResponse);
  const mapSourceOptions = mapDataToOptions(mapSourcesResponse);

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const updateFormData = (tabKey: keyof MapsetFormState, data: any) => {
    setFormState({
      ...formState,
      [tabKey]: data,
    });
  };

  const handleContinue = () => {
    if (activeTab < MapsetFormTab.VERSION) {
      setActiveTab((prev) => prev + 1);
    }
  };

  const handlePrevious = () => {
    if (activeTab > MapsetFormTab.INFO) {
      setActiveTab(activeTab - 1);
    }
  };

  const updateMapsetMutation = useMutation({
    mutationFn: (mapsetData: MapsetSubmitPayload) => {
      return mapsetApi.updateMapset(mapsetId, mapsetData);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["mapsets"] });
      queryClient.invalidateQueries({ queryKey: ["mapset", mapsetId] });
      toast.success("Mapset berhasil diperbarui!");
      router.push("/admin/mapset");
    },
    onError: (error: Error) => {
      toast.error(error.message || "Terjadi kesalahan saat memperbarui data");
    },
  });

  const handleSubmitMapset = (versionData: { data_update_period: string; data_version: string }) => {
    updateFormData("version", versionData);

    const payload: MapsetSubmitPayload = {
      name: formState.info.name,
      description: formState.info.description,
      scale: formState.info.scale,
      projection_system_id: formState.info.projection_system_id,
      category_id: formState.info.category_id,
      data_status: formState.info.data_status,
      classification_id: formState.info.classification_id,
      producer_id: formState.info.organization_id,
      layer_type: formState.info.layer_type,
      source_id: [formState.metadata.source_id, formState.metadata.metadata_source_id].filter((id) => id !== "lainnya" && id !== null) as string[],
      layer_url: formState.metadata.layer_url,
      metadata_url: formState.metadata.metadata_url,
      coverage_level: formState.classification.coverage_level,
      coverage_area: formState.classification.coverage_area,
      data_update_period: versionData.data_update_period,
      data_version: versionData.data_version,
      is_popular: formState.info.is_popular || false,
      is_active: mapset?.is_active || true,
      regional_id: mapset?.regional.id || "01968b53-a910-7a67-bd10-975b8923b92e",
      status_validation: mapset?.status_validation || StatusValidation.ON_VERIFICATION,
    };

    updateMapsetMutation.mutate(payload);
  };

  if (isLoading || !mapset) {
    return (
      <div className="flex items-center justify-center min-h-[400px]">
        <div className="flex flex-col items-center space-y-2">
          <Loader2 className="h-8 w-8 animate-spin text-blue-500" />
          <p className="text-sm text-gray-500">Memuat data...</p>
        </div>
      </div>
    );
  }

  return (
    <div>
      <PageHeader className="bg-zinc-50" title="Ubah Mapset dan Metadata" description="Ubah mapset dan metadata untuk memperbarui data geospasial di Satu Peta." />
      <MapsetTab formState={formState} activeTab={activeTab} handleTabChange={(e: number) => setActiveTab(e)} />
      <div className="max-w-xl">
        {activeTab === MapsetFormTab.INFO && (
          <MapsetInfoForm
            initialData={formState.info}
            projectionSystems={projectionSystemOptions}
            categories={categoryOptions}
            classifications={classificationOptions}
            organizations={organizationOptions}
            isOrgFieldDisabled={isDataManager}
            onSubmit={(data) => {
              updateFormData("info", data);
              handleContinue();
            }}
          />
        )}
        {activeTab === MapsetFormTab.METADATA && (
          <MapsetMetadataForm
            initialData={formState.metadata}
            mapSources={mapSourceOptions}
            onSubmit={(data) => {
              updateFormData("metadata", data);
              handleContinue();
            }}
            onPrevious={handlePrevious}
          />
        )}
        {activeTab === MapsetFormTab.CLASSIFICATION && (
          <MapsetClassificationForm
            initialData={formState.classification}
            onSubmit={(data) => {
              updateFormData("classification", data);
              handleContinue();
            }}
            onPrevious={handlePrevious}
          />
        )}
        {activeTab === MapsetFormTab.VERSION && (
          <MapsetVersionForm
            initialData={formState.version}
            onSubmit={handleSubmitMapset}
            onPrevious={handlePrevious}
            isSubmitting={updateMapsetMutation.isPending}
            onDataChange={(data) => {
              updateFormData("version", data);
            }}
          />
        )}
      </div>
    </div>
  );
}
