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

import { locationUtil } from '@grafana/data';
import { config, getDataSourceSrv, locationService, reportInteraction } from '@grafana/runtime';
import { Button, Drawer, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui';
import { OwnerReference } from 'app/api/clients/folder/v1beta1';
import { useCreateFolder } from 'app/api/clients/folder/v1beta1/hooks';
import { useAppNotification } from 'app/core/copy/appNotification';
import {
  CONTENT_KINDS,
  DashboardLibraryInteractions,
  SOURCE_ENTRY_POINTS,
} from 'app/features/dashboard/dashgrid/DashboardLibrary/interactions';
import { RepoType } from 'app/features/provisioning/Wizard/types';
import { NewProvisionedFolderForm } from 'app/features/provisioning/components/Folders/NewProvisionedFolderForm';
import { useIsProvisionedInstance } from 'app/features/provisioning/hooks/useIsProvisionedInstance';
import { getReadOnlyTooltipText } from 'app/features/provisioning/utils/tooltip';
import {
  getImportPhrase,
  getNewDashboardPhrase,
  getNewFolderPhrase,
  getNewPhrase,
  getNewTemplateDashboardPhrase,
} from 'app/features/search/tempI18nPhrases';
import { FolderDTO } from 'app/types/folders';

import { ManagerKind } from '../../apiserver/types';

import { NewFolderForm } from './NewFolderForm';

interface Props {
  parentFolder?: FolderDTO;
  canCreateFolder: boolean;
  canCreateDashboard: boolean;
  isReadOnlyRepo: boolean;
  repoType?: RepoType;
}

export default function CreateNewButton({
  parentFolder,
  canCreateDashboard,
  canCreateFolder,
  isReadOnlyRepo,
  repoType,
}: Props) {
  const [isOpen, setIsOpen] = useState(false);
  const location = useLocation();
  const [newFolder] = useCreateFolder();
  const [showNewFolderDrawer, setShowNewFolderDrawer] = useState(false);
  const notifyApp = useAppNotification();
  const isProvisionedInstance = useIsProvisionedInstance();

  const handleVisibleChange = () => {
    if (!isOpen) {
      reportInteraction('grafana_create_new_button_menu_opened', {
        from: location.pathname,
      });
    }
    setIsOpen(!isOpen);
  };

  let renderPreBuiltDashboardAction = false;
  if (config.featureToggles.dashboardTemplates) {
    const testDataSources = getDataSourceSrv().getList({ type: 'grafana-testdata-datasource' });
    renderPreBuiltDashboardAction = testDataSources.length > 0;
  }

  const onCreateFolder = async (folderName: string, teamOwnerRefs?: OwnerReference[]) => {
    try {
      const folder = await newFolder({
        title: folderName,
        parentUid: parentFolder?.uid,
        teamOwnerReferences: teamOwnerRefs,
      });

      const depth = parentFolder ? (parentFolder.parents?.length || 0) + 1 : 0;
      reportInteraction('grafana_manage_dashboards_folder_created', {
        is_subfolder: Boolean(parentFolder?.uid),
        folder_depth: depth,
      });

      if (!folder.error) {
        notifyApp.success('Folder created');
      } else {
        notifyApp.error('Failed to create folder');
      }

      if (folder.data) {
        locationService.push(locationUtil.stripBaseFromUrl(folder.data.url));
      }
    } finally {
      setShowNewFolderDrawer(false);
    }
  };

  const newMenu = (
    <Menu>
      {canCreateDashboard && (
        <>
          <MenuItem
            label={getNewDashboardPhrase()}
            onClick={() =>
              reportInteraction('grafana_menu_item_clicked', {
                url: buildUrl('/dashboard/new', parentFolder?.uid),
                from: location.pathname,
              })
            }
            url={buildUrl('/dashboard/new', parentFolder?.uid)}
          />
          {renderPreBuiltDashboardAction && (
            <MenuItem
              label={getNewTemplateDashboardPhrase()}
              onClick={() =>
                DashboardLibraryInteractions.entryPointClicked({
                  entryPoint: SOURCE_ENTRY_POINTS.BROWSE_DASHBOARDS_PAGE,
                  contentKind: CONTENT_KINDS.TEMPLATE_DASHBOARD,
                })
              }
              url={buildUrl('/dashboards?templateDashboards=true&source=createNewButton', parentFolder?.uid)}
            />
          )}
        </>
      )}
      {canCreateFolder && <MenuItem onClick={() => setShowNewFolderDrawer(true)} label={getNewFolderPhrase()} />}
      {canCreateDashboard && !isProvisionedInstance && parentFolder?.managedBy !== ManagerKind.Repo && (
        <MenuItem
          label={getImportPhrase()}
          onClick={() =>
            reportInteraction('grafana_menu_item_clicked', {
              url: buildUrl('/dashboard/import', parentFolder?.uid),
              from: location.pathname,
            })
          }
          url={buildUrl('/dashboard/import', parentFolder?.uid)}
        />
      )}
    </Menu>
  );

  return (
    <>
      <Dropdown overlay={newMenu} onVisibleChange={handleVisibleChange}>
        <Button
          disabled={isReadOnlyRepo}
          tooltip={isReadOnlyRepo ? getReadOnlyTooltipText({ isLocal: repoType === 'local' }) : undefined}
          variant="secondary"
        >
          {getNewPhrase()}
          <Icon name={isOpen ? 'angle-up' : 'angle-down'} />
        </Button>
      </Dropdown>
      {showNewFolderDrawer && (
        <Drawer
          title={getNewFolderPhrase()}
          subtitle={parentFolder?.title ? `Location: ${parentFolder.title}` : undefined}
          onClose={() => setShowNewFolderDrawer(false)}
          size="sm"
        >
          {parentFolder?.managedBy === ManagerKind.Repo || isProvisionedInstance ? (
            <NewProvisionedFolderForm onDismiss={() => setShowNewFolderDrawer(false)} parentFolder={parentFolder} />
          ) : (
            <NewFolderForm
              onConfirm={onCreateFolder}
              onCancel={() => setShowNewFolderDrawer(false)}
              parentFolder={parentFolder}
            />
          )}
        </Drawer>
      )}
    </>
  );
}

/**
 *
 * @param url without any parameters
 * @param folderUid  folder id
 * @returns url with paramter if folder is present
 */
function buildUrl(url: string, folderUid: string | undefined) {
  const baseUrl = folderUid ? url + '?folderUid=' + folderUid : url;
  return config.appSubUrl ? config.appSubUrl + baseUrl : baseUrl;
}
