import type {Location} from 'history';
import omit from 'lodash/omit';

import type {Crumb} from 'sentry/components/breadcrumbs';
import {t} from 'sentry/locale';
import type {Organization} from 'sentry/types/organization';
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import type {
  RoutableModuleNames,
  URLBuilder,
} from 'sentry/views/insights/common/utils/useModuleURL';
import {
  DOMAIN_VIEW_BASE_TITLE,
  DOMAIN_VIEW_BASE_URL,
} from 'sentry/views/insights/pages/settings';
import {DOMAIN_VIEW_TITLES} from 'sentry/views/insights/pages/types';
import type {DomainView} from 'sentry/views/insights/pages/useFilters';
import {MODULE_TITLES} from 'sentry/views/insights/settings';
import {ModuleName} from 'sentry/views/insights/types';
import {getTransactionSummaryBaseUrl} from 'sentry/views/performance/transactionSummary/utils';
import {getPerformanceBaseUrl} from 'sentry/views/performance/utils';

import Tab from '../../transactionSummary/tabs';

export const enum TraceViewSources {
  TRACES = 'traces',
  METRICS = 'metrics',
  DISCOVER = 'discover',
  PROFILING_FLAMEGRAPH = 'profiling_flamegraph',
  REQUESTS_MODULE = 'requests_module',
  QUERIES_MODULE = 'queries_module',
  ASSETS_MODULE = 'assets_module',
  APP_STARTS_MODULE = 'app_starts_module',
  SCREEN_LOADS_MODULE = 'screen_loads_module',
  WEB_VITALS_MODULE = 'web_vitals_module',
  CACHES_MODULE = 'caches_module',
  QUEUES_MODULE = 'queues_module',
  LLM_MODULE = 'llm_module',
  SCREEN_LOAD_MODULE = 'screen_load_module',
  MOBILE_SCREENS_MODULE = 'mobile_screens_module',
  SCREEN_RENDERING_MODULE = 'screen_rendering_module',
  PERFORMANCE_TRANSACTION_SUMMARY = 'performance_transaction_summary',
  PERFORMANCE_TRANSACTION_SUMMARY_PROFILES = 'performance_transaction_summary_profiles',
  ISSUE_DETAILS = 'issue_details',
  FEEDBACK_DETAILS = 'feedback_details',
}

// Ideally every new entry to ModuleName, would require a new source to be added here so we don't miss any.
const TRACE_SOURCE_TO_MODULE: Partial<Record<TraceViewSources, ModuleName>> = {
  app_starts_module: ModuleName.APP_START,
  assets_module: ModuleName.RESOURCE,
  caches_module: ModuleName.CACHE,
  llm_module: ModuleName.AI,
  queries_module: ModuleName.DB,
  requests_module: ModuleName.HTTP,
  screen_loads_module: ModuleName.SCREEN_LOAD,
  web_vitals_module: ModuleName.VITAL,
  queues_module: ModuleName.QUEUE,
  screen_load_module: ModuleName.SCREEN_LOAD,
  screen_rendering_module: ModuleName.SCREEN_RENDERING,
  mobile_screens_module: ModuleName.MOBILE_SCREENS,
};

function getBreadCrumbTarget(
  path: string,
  query: Location['query'],
  organization: Organization
) {
  return {
    pathname: normalizeUrl(`/organizations/${organization.slug}/${path}`),
    // Remove traceView specific query parameters that are not needed when navigating back.
    query: {...omit(query, ['node', 'fov', 'timestamp', 'eventId'])},
  };
}

function getPerformanceBreadCrumbs(
  organization: Organization,
  location: Location,
  view?: DomainView
) {
  const crumbs: Crumb[] = [];

  const performanceUrl = getPerformanceBaseUrl(organization.slug, view, true);
  const transactionSummaryUrl = getTransactionSummaryBaseUrl(
    organization.slug,
    view,
    true
  );

  if (view) {
    crumbs.push({
      label: DOMAIN_VIEW_BASE_TITLE,
      to: undefined,
    });
  }

  crumbs.push({
    label: (view && DOMAIN_VIEW_TITLES[view]) || t('Performance'),
    to: getBreadCrumbTarget(performanceUrl, location.query, organization),
  });

  switch (location.query.tab) {
    case Tab.EVENTS:
      crumbs.push({
        label: t('All Events'),
        to: getBreadCrumbTarget(
          `${transactionSummaryUrl}/events`,
          location.query,
          organization
        ),
      });
      break;
    case Tab.TAGS:
      crumbs.push({
        label: t('Tags'),
        to: getBreadCrumbTarget(
          `${transactionSummaryUrl}/tags`,
          location.query,
          organization
        ),
      });
      break;
    case Tab.SPANS:
      crumbs.push({
        label: t('Spans'),
        to: getBreadCrumbTarget(
          `${transactionSummaryUrl}/spans`,
          location.query,
          organization
        ),
      });

      const {spanSlug} = location.query;
      if (spanSlug) {
        crumbs.push({
          label: t('Span Summary'),
          to: getBreadCrumbTarget(
            `${transactionSummaryUrl}/spans/${spanSlug}`,
            location.query,
            organization
          ),
        });
      }
      break;
    case Tab.AGGREGATE_WATERFALL:
      crumbs.push({
        label: t('Transaction Summary'),
        to: getBreadCrumbTarget(
          `${transactionSummaryUrl}/aggregateWaterfall`,
          location.query,
          organization
        ),
      });
      break;
    default:
      crumbs.push({
        label: t('Transaction Summary'),
        to: getBreadCrumbTarget(`${transactionSummaryUrl}`, location.query, organization),
      });
      break;
  }

  crumbs.push({
    label: t('Trace View'),
  });

  return crumbs;
}

function getIssuesBreadCrumbs(organization: Organization, location: Location) {
  const crumbs: Crumb[] = [];

  crumbs.push({
    label: t('Issues'),
    to: getBreadCrumbTarget(`issues`, location.query, organization),
  });

  if (location.query.groupId) {
    crumbs.push({
      label: t('Issue Details'),
      to: getBreadCrumbTarget(
        `issues/${location.query.groupId}`,
        location.query,
        organization
      ),
    });
  }

  crumbs.push({
    label: t('Trace View'),
  });

  return crumbs;
}

function getInsightsModuleBreadcrumbs(
  location: Location,
  organization: Organization,
  moduleURLBuilder: URLBuilder,
  view?: DomainView
) {
  const crumbs: Crumb[] = [];

  if (view && DOMAIN_VIEW_TITLES[view]) {
    crumbs.push({
      label: DOMAIN_VIEW_BASE_TITLE,
      to: undefined,
    });
    crumbs.push({
      label: DOMAIN_VIEW_TITLES[view],
      to: getBreadCrumbTarget(
        `${DOMAIN_VIEW_BASE_URL}/${view}/`,
        location.query,
        organization
      ),
    });
  } else {
    crumbs.push({
      label: t('Insights'),
    });
  }

  let moduleName: RoutableModuleNames | undefined = undefined;

  if (
    typeof location.query.source === 'string' &&
    TRACE_SOURCE_TO_MODULE[location.query.source]
  ) {
    moduleName = TRACE_SOURCE_TO_MODULE[location.query.source] as RoutableModuleNames;
    crumbs.push({
      label: MODULE_TITLES[moduleName],
      to: moduleURLBuilder(moduleName),
    });
  }

  switch (moduleName) {
    case ModuleName.HTTP:
      crumbs.push({
        label: t('Domain Summary'),
        to: getBreadCrumbTarget(
          `${moduleURLBuilder(moduleName, view)}/domains`,
          location.query,
          organization
        ),
      });
      break;
    case ModuleName.DB:
      if (location.query.groupId) {
        crumbs.push({
          label: t('Query Summary'),
          to: getBreadCrumbTarget(
            `${moduleURLBuilder(moduleName, view)}/spans/span/${location.query.groupId}`,
            location.query,
            organization
          ),
        });
      } else {
        crumbs.push({
          label: t('Query Summary'),
        });
      }
      break;
    case ModuleName.RESOURCE:
      if (location.query.groupId) {
        crumbs.push({
          label: t('Asset Summary'),
          to: getBreadCrumbTarget(
            `${moduleURLBuilder(moduleName)}/spans/span/${location.query.groupId}`,
            location.query,
            organization
          ),
        });
      } else {
        crumbs.push({
          label: t('Asset Summary'),
        });
      }
      break;
    case ModuleName.APP_START:
      crumbs.push({
        label: t('Screen Summary'),
        to: getBreadCrumbTarget(
          `${moduleURLBuilder(moduleName, view)}/spans`,
          location.query,
          organization
        ),
      });
      break;
    case ModuleName.SCREEN_LOAD:
      crumbs.push({
        label: t('Screen Summary'),
        to: getBreadCrumbTarget(
          `${moduleURLBuilder(moduleName, view)}/spans`,
          location.query,
          organization
        ),
      });
      break;
    case ModuleName.VITAL:
      crumbs.push({
        label: t('Page Overview'),
        to: getBreadCrumbTarget(
          `${moduleURLBuilder(moduleName, view)}/overview`,
          location.query,
          organization
        ),
      });
      break;
    case ModuleName.QUEUE:
      crumbs.push({
        label: t('Destination Summary'),
        to: getBreadCrumbTarget(
          `${moduleURLBuilder(moduleName, view)}/destination`,
          location.query,
          organization
        ),
      });
      break;
    case ModuleName.AI:
      if (location.query.groupId) {
        crumbs.push({
          label: t('Pipeline Summary'),
          to: getBreadCrumbTarget(
            `${moduleURLBuilder(moduleName, view)}/pipeline-type/${location.query.groupId}`,
            location.query,
            organization
          ),
        });
      }
      break;
    case ModuleName.CACHE:
    default:
      break;
  }

  crumbs.push({
    label: t('Trace View'),
  });

  return crumbs;
}

export function getTraceViewBreadcrumbs(
  organization: Organization,
  location: Location,
  moduleUrlBuilder: URLBuilder,
  view?: DomainView
): Crumb[] {
  if (
    typeof location.query.source === 'string' &&
    TRACE_SOURCE_TO_MODULE[location.query.source]
  ) {
    return getInsightsModuleBreadcrumbs(location, organization, moduleUrlBuilder, view);
  }

  switch (location.query.source) {
    case TraceViewSources.TRACES:
      return [
        {
          label: t('Traces'),
          to: getBreadCrumbTarget(`traces`, location.query, organization),
        },
        {
          label: t('Trace View'),
        },
      ];
    case TraceViewSources.DISCOVER:
      return [
        {
          label: t('Discover'),
          to: getBreadCrumbTarget(`discover/homepage`, location.query, organization),
        },
        {
          label: t('Trace View'),
        },
      ];
    case TraceViewSources.METRICS:
      return [
        {
          label: t('Metrics'),
          to: getBreadCrumbTarget(`metrics`, location.query, organization),
        },
        {
          label: t('Trace View'),
        },
      ];
    case TraceViewSources.ISSUE_DETAILS:
      return getIssuesBreadCrumbs(organization, location);
    case TraceViewSources.PERFORMANCE_TRANSACTION_SUMMARY:
      return getPerformanceBreadCrumbs(organization, location, view);
    default:
      return [{label: t('Trace View')}];
  }
}
