import { useMemo } from 'react';
import { useLocation } from 'react-router-dom-v5-compat';

import { GrafanaPlugin, NavModelItem, PluginIncludeType, PluginType } from '@grafana/data';
import { config } from '@grafana/runtime';
import { contextSrv } from 'app/core/core';
import { AccessControlAction } from 'app/types';

import { usePluginConfig } from '../hooks/usePluginConfig';
import { CatalogPlugin, PluginTabIds, PluginTabLabels } from '../types';

type ReturnType = {
  error: Error | undefined;
  loading: boolean;
  navModel: NavModelItem;
  activePageId: PluginTabIds | string;
};

function getCurrentPageId(
  pageId: PluginTabIds | undefined,
  isNarrowScreen: boolean | undefined,
  defaultTab: string
): PluginTabIds | string {
  if (!isNarrowScreen && pageId === PluginTabIds.PLUGINDETAILS) {
    return defaultTab;
  }
  return pageId || defaultTab;
}

export const usePluginDetailsTabs = (
  plugin?: CatalogPlugin,
  pageId?: PluginTabIds,
  isNarrowScreen?: boolean
): ReturnType => {
  const { loading, error, value: pluginConfig } = usePluginConfig(plugin);
  const { pathname } = useLocation();
  const defaultTab = useDefaultPage(plugin, pluginConfig);
  const isPublished = Boolean(plugin?.isPublished);

  const currentPageId = getCurrentPageId(pageId, isNarrowScreen, defaultTab);

  const navModelChildren = useMemo(() => {
    const canConfigurePlugins = plugin && contextSrv.hasPermissionInMetadata(AccessControlAction.PluginsWrite, plugin);
    const navModelChildren: NavModelItem[] = [];
    // currently the versions available of core plugins are not consistent
    if (isPublished && !plugin?.isCore) {
      navModelChildren.push({
        text: PluginTabLabels.VERSIONS,
        id: PluginTabIds.VERSIONS,
        icon: 'history',
        url: `${pathname}?page=${PluginTabIds.VERSIONS}`,
        active: PluginTabIds.VERSIONS === currentPageId,
      });
    }
    // currently there is not changelog available for core plugins
    if (isPublished && plugin?.details?.changelog && !plugin.isCore) {
      navModelChildren.push({
        text: PluginTabLabels.CHANGELOG,
        id: PluginTabIds.CHANGELOG,
        icon: 'rocket',
        url: `${pathname}?page=${PluginTabIds.CHANGELOG}`,
        active: PluginTabIds.CHANGELOG === currentPageId,
      });
    }

    if (isPublished && isNarrowScreen && config.featureToggles.pluginsDetailsRightPanel) {
      navModelChildren.push({
        text: PluginTabLabels.PLUGINDETAILS,
        id: PluginTabIds.PLUGINDETAILS,
        icon: 'info-circle',
        url: `${pathname}?page=${PluginTabIds.PLUGINDETAILS}`,
        active: PluginTabIds.PLUGINDETAILS === currentPageId,
      });
    }

    // Not extending the tabs with the config pages if the plugin is not installed
    if (!pluginConfig) {
      return navModelChildren;
    }

    if (config.featureToggles.externalServiceAccounts && (plugin?.iam || plugin?.details?.iam)) {
      navModelChildren.push({
        text: PluginTabLabels.IAM,
        icon: 'shield',
        id: PluginTabIds.IAM,
        url: `${pathname}?page=${PluginTabIds.IAM}`,
        active: PluginTabIds.IAM === currentPageId,
      });
    }

    if (
      config.featureToggles.panelTitleSearch &&
      (pluginConfig.meta.type === PluginType.panel || pluginConfig.meta.type === PluginType.datasource)
    ) {
      navModelChildren.push({
        text: PluginTabLabels.USAGE,
        icon: 'list-ul',
        id: PluginTabIds.USAGE,
        url: `${pathname}?page=${PluginTabIds.USAGE}`,
        active: PluginTabIds.USAGE === currentPageId,
      });
    }

    if (config.featureToggles.datasourceConnectionsTab && plugin?.type === PluginType.datasource) {
      navModelChildren.push({
        text: PluginTabLabels.DATASOURCE_CONNECTIONS,
        icon: 'database',
        id: PluginTabIds.DATASOURCE_CONNECTIONS,
        url: `${pathname}?page=${PluginTabIds.DATASOURCE_CONNECTIONS}`,
        active: PluginTabIds.DATASOURCE_CONNECTIONS === currentPageId,
      });
    }

    if (!canConfigurePlugins) {
      return navModelChildren;
    }

    if (pluginConfig.meta.type === PluginType.app) {
      if (pluginConfig.angularConfigCtrl) {
        navModelChildren.push({
          text: 'Config',
          icon: 'cog',
          id: PluginTabIds.CONFIG,
          url: `${pathname}?page=${PluginTabIds.CONFIG}`,
          active: PluginTabIds.CONFIG === currentPageId,
        });
      }

      if (pluginConfig.configPages) {
        for (const configPage of pluginConfig.configPages) {
          navModelChildren.push({
            text: configPage.title,
            icon: configPage.icon,
            id: configPage.id,
            url: `${pathname}?page=${configPage.id}`,
            active: configPage.id === currentPageId,
          });
        }
      }

      if (pluginConfig.meta.includes?.find((include) => include.type === PluginIncludeType.dashboard)) {
        navModelChildren.push({
          text: 'Dashboards',
          icon: 'apps',
          id: PluginTabIds.DASHBOARDS,
          url: `${pathname}?page=${PluginTabIds.DASHBOARDS}`,
          active: PluginTabIds.DASHBOARDS === currentPageId,
        });
      }
    }

    return navModelChildren;
  }, [plugin, pluginConfig, pathname, isPublished, currentPageId, isNarrowScreen]);

  const navModel: NavModelItem = {
    text: plugin?.name ?? '',
    img: plugin?.info.logos.small,
    url: pathname,
    children: [
      {
        text: PluginTabLabels.OVERVIEW,
        icon: 'file-alt',
        id: PluginTabIds.OVERVIEW,
        url: `${pathname}?page=${PluginTabIds.OVERVIEW}`,
        active: PluginTabIds.OVERVIEW === currentPageId,
      },
      ...navModelChildren,
    ],
  };

  return {
    error,
    loading,
    navModel,
    activePageId: currentPageId,
  };
};

function useDefaultPage(plugin: CatalogPlugin | undefined, pluginConfig: GrafanaPlugin | undefined | null) {
  if (!plugin || !pluginConfig) {
    return PluginTabIds.OVERVIEW;
  }

  const hasAccess = contextSrv.hasPermissionInMetadata(AccessControlAction.PluginsWrite, plugin);

  if (!hasAccess || pluginConfig.meta.type !== PluginType.app) {
    return PluginTabIds.OVERVIEW;
  }

  if (pluginConfig.angularConfigCtrl) {
    return PluginTabIds.CONFIG;
  }

  if (pluginConfig.configPages?.length) {
    return pluginConfig.configPages[0].id;
  }

  return PluginTabIds.OVERVIEW;
}
