/**
 * 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 { useCallback, useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import { useToasts } from 'src/components/MessageToasts/withToasts';
import { last } from 'lodash';
import contentDisposition from 'content-disposition';
import {
  logging,
  t,
  SupersetClient,
  SupersetApiError,
} from '@superset-ui/core';
import {
  LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE,
  LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_PDF,
} from 'src/logger/LogUtils';
import { RootState } from 'src/dashboard/types';
import { getDashboardUrlParams } from 'src/utils/urlUtils';
import { DownloadScreenshotFormat } from '../components/menu/DownloadMenuItems/types';

const RETRY_INTERVAL = 3000;
const MAX_RETRIES = 30;

export const useDownloadScreenshot = (
  dashboardId: number,
  logEvent?: Function,
) => {
  const activeTabs = useSelector(
    (state: RootState) => state.dashboardState.activeTabs || undefined,
  );
  const anchor = useSelector(
    (state: RootState) =>
      last(state.dashboardState.directPathToChild) || undefined,
  );
  const dataMask = useSelector(
    (state: RootState) => state.dataMask || undefined,
  );

  const { addDangerToast, addSuccessToast, addInfoToast } = useToasts();

  const currentIntervalIds = useRef<NodeJS.Timeout[]>([]);

  const stopIntervals = useCallback(
    (message?: 'success' | 'failure') => {
      currentIntervalIds.current.forEach(clearInterval);

      if (message === 'failure') {
        addDangerToast(
          t('The screenshot could not be downloaded. Please, try again later.'),
        );
      }
      if (message === 'success') {
        addSuccessToast(t('The screenshot has been downloaded.'));
      }
    },
    [addDangerToast, addSuccessToast],
  );

  const downloadScreenshot = useCallback(
    (format: DownloadScreenshotFormat) => {
      let retries = 0;

      const toastIntervalId = setInterval(
        () =>
          addInfoToast(
            t(
              'The screenshot is being generated. Please, do not leave the page.',
            ),
            { noDuplicate: true },
          ),
        RETRY_INTERVAL,
      );

      currentIntervalIds.current = [
        ...(currentIntervalIds.current || []),
        toastIntervalId,
      ];

      const checkImageReady = (cacheKey: string) =>
        SupersetClient.get({
          endpoint: `/api/v1/dashboard/${dashboardId}/screenshot/${cacheKey}/?download_format=${format}`,
          headers: { Accept: 'application/pdf, image/png' },
          parseMethod: 'raw',
        })
          .then((response: Response) => {
            const disposition = response.headers.get('Content-Disposition');
            let fileName = `screenshot.${format}`; // default filename

            if (disposition) {
              try {
                const parsed = contentDisposition.parse(disposition);
                if (parsed?.parameters?.filename) {
                  fileName = parsed.parameters.filename;
                }
              } catch (error) {
                console.warn(
                  'Failed to parse Content-Disposition header:',
                  error,
                );
              }
            }

            return response.blob().then(blob => ({ blob, fileName }));
          })
          .then(({ blob, fileName }) => {
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = fileName;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
            stopIntervals('success');
          })
          .catch(err => {
            if ((err as SupersetApiError).status === 404) {
              throw new Error('Image not ready');
            }
          });

      const fetchImageWithRetry = (cacheKey: string) => {
        if (retries >= MAX_RETRIES) {
          stopIntervals('failure');
          logging.error('Max retries reached');
          return;
        }
        checkImageReady(cacheKey).catch(() => {
          retries += 1;
        });
      };

      SupersetClient.post({
        endpoint: `/api/v1/dashboard/${dashboardId}/cache_dashboard_screenshot/`,
        jsonPayload: {
          anchor,
          activeTabs,
          dataMask,
          urlParams: getDashboardUrlParams(['edit']),
        },
      })
        .then(({ json }) => {
          const cacheKey = json?.cache_key;
          if (!cacheKey) {
            throw new Error('No image URL in response');
          }
          const retryIntervalId = setInterval(() => {
            fetchImageWithRetry(cacheKey);
          }, RETRY_INTERVAL);
          currentIntervalIds.current.push(retryIntervalId);
          fetchImageWithRetry(cacheKey);
        })
        .catch(error => {
          logging.error(error);
          stopIntervals('failure');
        })
        .finally(() => {
          logEvent?.(
            format === DownloadScreenshotFormat.PNG
              ? LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_IMAGE
              : LOG_ACTIONS_DASHBOARD_DOWNLOAD_AS_PDF,
          );
        });
    },
    [
      dashboardId,
      anchor,
      activeTabs,
      dataMask,
      addInfoToast,
      stopIntervals,
      logEvent,
    ],
  );

  useEffect(
    () => () => {
      if (currentIntervalIds.current.length > 0) {
        stopIntervals();
      }
      currentIntervalIds.current = [];
    },
    [stopIntervals],
  );

  return downloadScreenshot;
};
