import { useEffect } from 'react';

import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import {
  AdvancedHttpSettings,
  Auth,
  AuthMethod,
  ConfigSection,
  ConnectionSettings,
  convertLegacyAuthProps,
  DataSourceDescription,
} from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { Alert, Divider, SecureSocksProxySettings, Stack } from '@grafana/ui';

import { ElasticsearchOptions, ElasticsearchSecureJsonData } from '../types';

import { ApiKeyConfig } from './ApiKeyConfig';
import { DataLinks } from './DataLinks';
import { ElasticDetails } from './ElasticDetails';
import { LogsConfig } from './LogsConfig';
import { coerceOptions, isValidOptions } from './utils';

export type Props = DataSourcePluginOptionsEditorProps<ElasticsearchOptions, ElasticsearchSecureJsonData>;

export const ConfigEditor = (props: Props) => {
  const { options, onOptionsChange } = props;

  useEffect(() => {
    if (!isValidOptions(options)) {
      onOptionsChange(coerceOptions(options));
    }
  }, [onOptionsChange, options]);

  const authProps = convertLegacyAuthProps({
    config: options,
    onChange: onOptionsChange,
  });
  authProps.customMethods = [
    {
      id: 'custom-api-key',
      label: 'API Key',
      description: 'API Key authentication',
      component: <ApiKeyConfig {...props} />,
    },
  ];
  authProps.selectedMethod = options.jsonData.apiKeyAuth ? 'custom-api-key' : authProps.selectedMethod;

  if (config.sigV4AuthEnabled) {
    authProps.customMethods = [
      ...authProps.customMethods,
      {
        id: 'custom-sigv4',
        label: 'SigV4 auth',
        description: 'AWS Signature Version 4 authentication',
        component: <SIGV4ConnectionConfig inExperimentalAuthComponent={true} {...props} />,
      },
    ];
    authProps.selectedMethod = options.jsonData.sigV4Auth ? 'custom-sigv4' : authProps.selectedMethod;
  }

  return (
    <>
      {options.access === 'direct' && (
        <Alert title="Error" severity="error">
          Browser access mode in the Elasticsearch datasource is no longer available. Switch to server access mode.
        </Alert>
      )}
      <DataSourceDescription
        dataSourceName="Elasticsearch"
        docsLink="https://grafana.com/docs/grafana/latest/datasources/elasticsearch"
        hasRequiredFields={false}
      />
      <Divider spacing={4} />
      <ConnectionSettings config={options} onChange={onOptionsChange} urlPlaceholder="http://localhost:9200" />
      <Divider spacing={4} />
      <Auth
        {...authProps}
        onAuthMethodSelect={(method) => {
          onOptionsChange({
            ...options,
            basicAuth: method === AuthMethod.BasicAuth,
            withCredentials: method === AuthMethod.CrossSiteCredentials,
            jsonData: {
              ...options.jsonData,
              sigV4Auth: method === 'custom-sigv4',
              apiKeyAuth: method === 'custom-api-key',
              oauthPassThru: method === AuthMethod.OAuthForward,
            },
          });
        }}
      />
      <Divider spacing={4} />
      <ConfigSection
        title="Additional settings"
        description="Additional settings are optional settings that can be configured for more control over your data source."
        isCollapsible={true}
        isInitiallyOpen
      >
        <Stack gap={5} direction="column">
          <AdvancedHttpSettings config={options} onChange={onOptionsChange} />
          {config.secureSocksDSProxyEnabled && (
            <SecureSocksProxySettings options={options} onOptionsChange={onOptionsChange} />
          )}
          <ElasticDetails value={options} onChange={onOptionsChange} />
          <LogsConfig
            value={options.jsonData}
            onChange={(newValue) =>
              onOptionsChange({
                ...options,
                jsonData: newValue,
              })
            }
          />
          <DataLinks
            value={options.jsonData.dataLinks}
            onChange={(newValue) => {
              onOptionsChange({
                ...options,
                jsonData: {
                  ...options.jsonData,
                  dataLinks: newValue,
                },
              });
            }}
          />
        </Stack>
      </ConfigSection>
    </>
  );
};
