import { useState, useMemo, useEffect } from 'react';
import { default as log } from '@/logger';
import { useFileBrowserContext } from '@/contexts/FileBrowserContext';
import { usePreferencesContext } from '@/contexts/PreferencesContext';
import { useProxiedPathContext } from '@/contexts/ProxiedPathContext';
import { useExternalBucketContext } from '@/contexts/ExternalBucketContext';
import {
  useZarrMetadataQuery,
  useOmeZarrThumbnailQuery
} from '@/queries/zarrQueries';
import type { OpenWithToolUrls, ZarrMetadata } from '@/queries/zarrQueries';
import {
  generateNeuroglancerStateForDataURL,
  generateNeuroglancerStateForZarrArray,
  generateNeuroglancerStateForOmeZarr,
  determineLayerType
} from '@/omezarr-helper';
import { buildUrl } from '@/utils';
import * as zarr from 'zarrita';

export type { OpenWithToolUrls, ZarrMetadata };
export type PendingToolKey = keyof OpenWithToolUrls | null;
export type ZarrArray = zarr.Array<any>;

export default function useZarrMetadata() {
  const { fileQuery } = useFileBrowserContext();
  const { currentDirProxiedPathQuery } = useProxiedPathContext();
  const { externalDataUrlQuery } = useExternalBucketContext();
  const {
    disableNeuroglancerStateGeneration,
    disableHeuristicalLayerTypeDetection,
    useLegacyMultichannelApproach
  } = usePreferencesContext();

  // Fetch Zarr metadata
  const zarrMetadataQuery = useZarrMetadataQuery({
    fspName: fileQuery.data?.currentFileSharePath?.name,
    currentFileOrFolder: fileQuery.data?.currentFileOrFolder,
    files: fileQuery.data?.files
  });

  const effectiveZarrVersion =
    zarrMetadataQuery.data?.availableVersions.includes('v3') ? 3 : 2;

  const metadata = zarrMetadataQuery.data?.metadata || null;
  const omeZarrUrl = zarrMetadataQuery.data?.omeZarrUrl || null;

  // Fetch thumbnail when OME-Zarr URL is available
  const thumbnailQuery = useOmeZarrThumbnailQuery(omeZarrUrl);
  const thumbnailSrc = thumbnailQuery.data || null;

  const [layerType, setLayerType] = useState<
    'auto' | 'image' | 'segmentation' | null
  >(null);

  useEffect(() => {
    if (!thumbnailSrc || disableHeuristicalLayerTypeDetection) {
      // Set layer type to 'image' if no thumbnail or detection disabled
      setLayerType('image');
      return;
    }

    const controller = new AbortController();

    const determineType = async (signal: AbortSignal) => {
      try {
        const determinedLayerType = await determineLayerType(
          !disableHeuristicalLayerTypeDetection,
          thumbnailSrc
        );
        if (signal.aborted) {
          return;
        }
        setLayerType(determinedLayerType);
      } catch (error) {
        if (!signal.aborted) {
          console.error('Error determining layer type:', error);
          setLayerType('image'); // Default fallback
        }
      }
    };

    determineType(controller.signal);

    return () => {
      controller.abort();
    };
  }, [thumbnailSrc, disableHeuristicalLayerTypeDetection]);

  const openWithToolUrls = useMemo(() => {
    if (!metadata) {
      return null;
    }
    const validatorBaseUrl = 'https://ome.github.io/ome-ngff-validator/';
    const neuroglancerBaseUrl = 'https://neuroglancer-demo.appspot.com/#!';
    const voleBaseUrl = 'https://volumeviewer.allencell.org/viewer';
    const avivatorBaseUrl = 'https://janeliascicomp.github.io/viv/';

    const url =
      externalDataUrlQuery.data || currentDirProxiedPathQuery.data?.url;
    const openWithToolUrls = {
      copy: url || ''
    } as OpenWithToolUrls;

    // Determine which tools should be available based on metadata type
    if (metadata?.multiscale) {
      // OME-Zarr - all urls for v2; no avivator for v3
      if (url) {
        if (effectiveZarrVersion === 2) {
          openWithToolUrls.avivator = buildUrl(avivatorBaseUrl, null, {
            image_url: url
          });
        } else {
          openWithToolUrls.avivator = null;
        }
        // Populate with actual URLs when proxied path is available
        openWithToolUrls.validator = buildUrl(validatorBaseUrl, null, {
          source: url
        });
        openWithToolUrls.vole = buildUrl(voleBaseUrl, null, {
          url
        });
        if (disableNeuroglancerStateGeneration) {
          openWithToolUrls.neuroglancer =
            neuroglancerBaseUrl +
            generateNeuroglancerStateForDataURL(url, effectiveZarrVersion);
        } else if (layerType) {
          try {
            openWithToolUrls.neuroglancer =
              neuroglancerBaseUrl +
              generateNeuroglancerStateForOmeZarr(
                url,
                effectiveZarrVersion,
                layerType,
                metadata.multiscale,
                metadata.arr,
                metadata.labels,
                metadata.omero,
                useLegacyMultichannelApproach
              );
          } catch (error) {
            log.error(
              'Error generating Neuroglancer state for OME-Zarr:',
              error
            );
            openWithToolUrls.neuroglancer =
              neuroglancerBaseUrl +
              generateNeuroglancerStateForDataURL(url, effectiveZarrVersion);
          }
        }
      } else {
        // No proxied URL - show all tools as available but empty
        openWithToolUrls.validator = '';
        openWithToolUrls.vole = '';
        // if this is a zarr version 2, then set the url to blank which will show
        // the icon before a data link has been generated. Setting it to null for
        // all other versions, eg zarr v3 means the icon will not be present before
        // a data link is generated.
        openWithToolUrls.avivator = effectiveZarrVersion === 2 ? '' : null;
        openWithToolUrls.neuroglancer = '';
      }
    } else {
      // Non-OME Zarr - only Neuroglancer available
      if (url) {
        openWithToolUrls.validator = null;
        openWithToolUrls.vole = null;
        openWithToolUrls.avivator = null;
        if (disableNeuroglancerStateGeneration) {
          openWithToolUrls.neuroglancer =
            neuroglancerBaseUrl +
            generateNeuroglancerStateForDataURL(url, effectiveZarrVersion);
        } else if (layerType) {
          openWithToolUrls.neuroglancer =
            neuroglancerBaseUrl +
            generateNeuroglancerStateForZarrArray(
              url,
              effectiveZarrVersion,
              layerType
            );
        }
      } else {
        // No proxied URL - only show Neuroglancer as available but empty
        openWithToolUrls.validator = null;
        openWithToolUrls.vole = null;
        openWithToolUrls.avivator = null;
        openWithToolUrls.neuroglancer = '';
      }
    }

    return openWithToolUrls;
  }, [
    metadata,
    currentDirProxiedPathQuery.data?.url,
    externalDataUrlQuery.data,
    disableNeuroglancerStateGeneration,
    useLegacyMultichannelApproach,
    layerType,
    effectiveZarrVersion
  ]);

  return {
    zarrMetadataQuery,
    thumbnailQuery,
    openWithToolUrls,
    layerType,
    availableVersions: zarrMetadataQuery.data?.availableVersions || []
  };
}
