/*!
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import { useQueryClient } from "@tanstack/react-query";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useLocation, useNavigate, useParams } from "react-router-dom";

import { useDagRunServiceTriggerDagRun, useDagServiceGetDagsUiKey } from "openapi/queries";
import type { TriggerDagRunResponse } from "openapi/requests/types.gen";
import type { DagRunTriggerParams } from "src/components/TriggerDag/types";
import { toaster } from "src/components/ui";
import { SearchParamsKeys } from "src/constants/searchParams";
import { gridQueryKeys } from "src/queries/gridViewQueryKeys";
import { createErrorToaster } from "src/utils";

export const useTrigger = ({ dagId, onSuccessConfirm }: { dagId: string; onSuccessConfirm: () => void }) => {
  const queryClient = useQueryClient();
  const [error, setError] = useState<unknown>(undefined);
  const { t: translate } = useTranslation("components");
  const navigate = useNavigate();
  const location = useLocation();
  const { dagId: selectedDagId } = useParams();

  const onSuccess = async (dagRun: TriggerDagRunResponse) => {
    await Promise.all([
      queryClient.invalidateQueries({ queryKey: [useDagServiceGetDagsUiKey] }),
      ...gridQueryKeys(dagId).map((key) => queryClient.invalidateQueries({ queryKey: key })),
    ]);

    toaster.create({
      description: translate("triggerDag.toaster.success.description"),
      title: translate("triggerDag.toaster.success.title"),
      type: "success",
    });
    onSuccessConfirm();

    // Only redirect if we're already on the dag page.
    // Preserve search params so layout state (Grid limit, filters) survives the navigation,
    // but drop the Grid date window — carrying an older ceiling forward would hide the
    // newly triggered run, which sits at the current time.
    if (selectedDagId === dagRun.dag_id) {
      const params = new URLSearchParams(location.search);

      params.delete(SearchParamsKeys.RUN_AFTER_LTE);
      params.delete(SearchParamsKeys.RUN_AFTER_GTE);
      const search = params.toString();

      void Promise.resolve(
        navigate({
          pathname: `/dags/${dagRun.dag_id}/runs/${dagRun.dag_run_id}`,
          search: search === "" ? "" : `?${search}`,
        }),
      );
    }
  };

  const onError = (apiError: unknown) => {
    createErrorToaster(apiError, { titleKey: "components:triggerDag.toaster.error.title" }, translate);
    setError(apiError);
  };

  const { isPending, mutate } = useDagRunServiceTriggerDagRun({
    onError,
    onSuccess,
  });

  const triggerDagRun = (dagRunRequestBody: DagRunTriggerParams) => {
    const parsedConfig = JSON.parse(dagRunRequestBody.conf) as Record<string, unknown>;

    const logicalDate = dagRunRequestBody.logicalDate ? new Date(dagRunRequestBody.logicalDate) : undefined;
    const formattedLogicalDate = logicalDate?.toISOString() ?? null;

    const dataIntervalStart = dagRunRequestBody.dataIntervalStart
      ? new Date(dagRunRequestBody.dataIntervalStart)
      : undefined;
    const formattedDataIntervalStart = dataIntervalStart?.toISOString() ?? null;

    const dataIntervalEnd = dagRunRequestBody.dataIntervalEnd
      ? new Date(dagRunRequestBody.dataIntervalEnd)
      : undefined;
    const formattedDataIntervalEnd = dataIntervalEnd?.toISOString() ?? null;

    const checkDagRunId = dagRunRequestBody.dagRunId === "" ? undefined : dagRunRequestBody.dagRunId;
    const checkNote = dagRunRequestBody.note === "" ? undefined : dagRunRequestBody.note;

    mutate({
      dagId,
      requestBody: {
        conf: parsedConfig,
        dag_run_id: checkDagRunId,
        data_interval_end: formattedDataIntervalEnd,
        data_interval_start: formattedDataIntervalStart,
        logical_date: formattedLogicalDate,
        note: checkNote,
        partition_key: dagRunRequestBody.partitionKey ?? null,
      },
    });
  };

  return {
    error,
    isPending,
    triggerDagRun,
  };
};
