import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import {
  BaseControl,
  ColorPalette,
  PanelBody,
  RangeControl,
  SelectControl,
  TabPanel,
  TextControl,
  ToggleControl,
  __experimentalNumberControl as NumberControl
} from '@wordpress/components';
import ServerSideRender from '@wordpress/server-side-render';
import { __ } from '@wordpress/i18n';
import Big from 'big.js';

import type { FxAttributes } from './types';
import { getCurrencies } from '../../currencies';
import { CurrencyMultiRichSelect, CurrencyRichSelect } from '../shared/CurrencyRichSelect';
import {
  ACCENT_THEME_PRESETS,
  DEFAULT_ACCENT_THEME_KEY,
} from '../shared/accentThemes';

type SourceOption = {
  id: string;
  label: string;
  group: 'builtin' | 'local';
};

declare global {
  interface Window {
    crtodaySourceOptions?: SourceOption[];
  }
}

type EditProps = {
  attributes: FxAttributes;
  setAttributes: (next: Partial<FxAttributes>) => void;
};

const currencies = getCurrencies();

const normalizeAmountInput = (value: string): string => {
  const compact = value.trim().replace(/\s+/g, '');
  if (compact === '') {
    return '';
  }

  const commaCount = (compact.match(/,/g) || []).length;
  const dotCount = (compact.match(/\./g) || []).length;

  if (commaCount > 0 && dotCount > 0) {
    return compact.replace(/,/g, '');
  }

  if (commaCount > 0) {
    return compact.replace(',', '.');
  }

  return compact;
};

const THEME_SWATCHES = ACCENT_THEME_PRESETS.map((preset) => ({
  name: preset.name,
  color: preset.light.primary,
}));

const THEME_KEY_BY_COLOR = Object.fromEntries(
  ACCENT_THEME_PRESETS.map((preset) => [preset.light.primary.toLowerCase(), preset.key])
);

export const Edit = ({ attributes, setAttributes }: EditProps) => {
  const blockProps = useBlockProps();
  const editorUi = window.crtodayEditorCurrenciesUi ?? {};
  const editorLabels = editorUi.labels ?? {};
  const selectedTheme =
    ACCENT_THEME_PRESETS.find((preset) => preset.key === attributes.accentTheme) ??
    ACCENT_THEME_PRESETS.find((preset) => preset.key === DEFAULT_ACCENT_THEME_KEY) ??
    ACCENT_THEME_PRESETS[0];

  /* Resolve the current source label for the placeholder */
  const resolvedSourceLabel = (() => {
    const sources: SourceOption[] = window.crtodaySourceOptions ?? [];
    const key = `${attributes.sourceId}:${attributes.deal}`;
    const match = sources.find((s) => s.id === key);
    if (match) {
      /* Strip the trailing " (BASE)" from the label */
      return match.label.replace(/\s*\([A-Z]{3}\)$/, '');
    }
    return attributes.sourceId;
  })();

  return (
    <div {...blockProps}>
      <InspectorControls>
        <TabPanel
          tabs={[
            { name: 'settings', title: __('Settings', 'currencyrate-today-currency-blocks') },
            { name: 'display', title: __('Display', 'currencyrate-today-currency-blocks') },
            { name: 'button', title: __('Button', 'currencyrate-today-currency-blocks') }
          ]}
        >
          {(tab) =>
            tab.name === 'settings' ? (
              <>
                <PanelBody title={__('Data settings', 'currencyrate-today-currency-blocks')} initialOpen>
                  <SelectControl
                    label={__('Data source', 'currencyrate-today-currency-blocks')}
                    help={__('Select the rate source for this block. Manage sources in Settings → Live Exchange Rates → Sources.', 'currencyrate-today-currency-blocks')}
                    value={`${attributes.sourceId}:${attributes.deal}`}
                    options={(() => {
                      const sources: SourceOption[] = window.crtodaySourceOptions ?? [];
                      const builtinGroup = sources.filter((s) => s.group === 'builtin');
                      const localGroup = sources.filter((s) => s.group === 'local');
                      const options: Array<{ label: string; value: string }> = [];

                      if (builtinGroup.length > 0) {
                        options.push({ label: `── ${editorLabels.sourceGroupBuiltIn ?? ''} ──`, value: '' });
                        builtinGroup.forEach((s) => options.push({ label: s.label, value: s.id }));
                      }
                      if (localGroup.length > 0) {
                        options.push({ label: `── ${editorLabels.sourceGroupLocal ?? ''} ──`, value: '' });
                        localGroup.forEach((s) => options.push({ label: s.label, value: s.id }));
                      }
                      return options;
                    })()}
                    onChange={(value) => {
                      if (!value) return;
                      const [sourceId, ...dealParts] = value.split(':');
                      const deal = dealParts.join(':') || 'DEFAULT';
                      setAttributes({ sourceId, deal });
                    }}
                  />

                  <CurrencyRichSelect
                    label={__('Base currency', 'currencyrate-today-currency-blocks')}
                    value={attributes.base}
                    currencies={currencies}
                    onChange={(base) => setAttributes({ base })}
                  />

                  <CurrencyMultiRichSelect
                    label={__('Target currencies', 'currencyrate-today-currency-blocks')}
                    values={attributes.symbols}
                    currencies={currencies}
                    onChange={(symbols) => setAttributes({ symbols })}
                  />

                  <SelectControl
                    label={__('Cache refresh interval', 'currencyrate-today-currency-blocks')}
                    help={__('How often the widget checks the cache. API interval is set in plugin settings.', 'currencyrate-today-currency-blocks')}
                    value={attributes.intervalMin === 30 ? '30' : attributes.intervalMin === 60 ? '60' : '15'}
                    options={[
                      { label: __('15 minutes', 'currencyrate-today-currency-blocks'), value: '15' },
                      { label: __('30 minutes', 'currencyrate-today-currency-blocks'), value: '30' },
                      { label: __('60 minutes', 'currencyrate-today-currency-blocks'), value: '60' }
                    ]}
                    onChange={(value) => setAttributes({ intervalMin: Number(value) as FxAttributes['intervalMin'] })}
                  />

                  <ToggleControl
                    label={__('Invert rates', 'currencyrate-today-currency-blocks')}
                    help={
                      attributes.invertRates
                        ? __('Showing target → base direction', 'currencyrate-today-currency-blocks')
                        : __('Showing base → target direction', 'currencyrate-today-currency-blocks')
                    }
                    checked={attributes.invertRates}
                    onChange={(invertRates) => setAttributes({ invertRates })}
                  />

                  <NumberControl
                    label={__('Amount', 'currencyrate-today-currency-blocks')}
                    help={__('Multiply rates by this amount', 'currencyrate-today-currency-blocks')}
                    value={attributes.amount}
                    min={0.01}
                    max={999999999}
                    step={0.01}
                    onChange={(value) => {
                      const normalized = normalizeAmountInput(String(value ?? ''));

                      if (normalized === '') {
                        return;
                      }

                      try {
                        const parsed = new Big(normalized);
                        if (parsed.gt(0)) {
                          setAttributes({ amount: parsed.toString() });
                        }
                      } catch {
                        return;
                      }
                    }}
                  />

                  <NumberControl
                    label={__('Adjustment (%)', 'currencyrate-today-currency-blocks')}
                    help={__('Applies percentage to the final displayed values. Supports minus and plus.', 'currencyrate-today-currency-blocks')}
                    value={String(attributes.adjustmentPercent ?? 0)}
                    min={-100}
                    max={100}
                    step={0.05}
                    onChange={(value) => {
                      const parsed = Number(value ?? 0);
                      if (Number.isFinite(parsed)) {
                        setAttributes({ adjustmentPercent: parsed });
                      }
                    }}
                  />
                </PanelBody>
              </>
            ) : tab.name === 'button' ? (
              <>
                <PanelBody title={__('Row CTA button', 'currencyrate-today-currency-blocks')} initialOpen>
                  <ToggleControl
                    label={__('Enable row CTA', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showCtaButton}
                    onChange={(showCtaButton) => setAttributes({ showCtaButton })}
                  />

                  <TextControl
                    label={__('Button text', 'currencyrate-today-currency-blocks')}
                    value={attributes.ctaButtonText}
                    maxLength={40}
                    disabled={!attributes.showCtaButton}
                    onChange={(ctaButtonText) => setAttributes({ ctaButtonText })}
                  />

                  <TextControl
                    label={__('URL template', 'currencyrate-today-currency-blocks')}
                    value={attributes.ctaUrlTemplate}
                    disabled={!attributes.showCtaButton}
                    placeholder={editorLabels.exchangeUrlPlaceholder ?? ''}
                    help={__(
                      'Use placeholders: {amount}, {from}, {to}, {result}, {bid}, {ask}.',
                      'currencyrate-today-currency-blocks'
                    )}
                    onChange={(ctaUrlTemplate) => setAttributes({ ctaUrlTemplate })}
                  />
                </PanelBody>
              </>
            ) : (
              <>
                <PanelBody title={__('Presentation', 'currencyrate-today-currency-blocks')} initialOpen>
                  <RangeControl
                    label={__('Decimals', 'currencyrate-today-currency-blocks')}
                    value={attributes.decimals}
                    min={0}
                    max={8}
                    onChange={(decimals) => setAttributes({ decimals: Number(decimals) })}
                  />

                  <ToggleControl
                    label={__('Seamless', 'currencyrate-today-currency-blocks')}
                    help={__('Remove background, border, shadow and theme for embedding into custom containers', 'currencyrate-today-currency-blocks')}
                    checked={attributes.seamless}
                    onChange={(seamless) => setAttributes({ seamless })}
                  />

                  <SelectControl
                    label={__('Theme', 'currencyrate-today-currency-blocks')}
                    value={attributes.theme}
                    disabled={attributes.seamless}
                    options={[
                      { label: __('Auto', 'currencyrate-today-currency-blocks'), value: 'auto' },
                      { label: __('Light', 'currencyrate-today-currency-blocks'), value: 'light' },
                      { label: __('Dark', 'currencyrate-today-currency-blocks'), value: 'dark' }
                    ]}
                    onChange={(theme) => setAttributes({ theme: theme as FxAttributes['theme'] })}
                  />

                  <RangeControl
                    label={__('Corner radius', 'currencyrate-today-currency-blocks')}
                    value={attributes.radius}
                    min={0}
                    max={32}
                    disabled={attributes.seamless}
                    onChange={(radius) => setAttributes({ radius: Number(radius) })}
                  />

                  <ToggleControl
                    label={__('Enable shadow', 'currencyrate-today-currency-blocks')}
                    checked={attributes.shadow}
                    disabled={attributes.seamless}
                    onChange={(shadow) => setAttributes({ shadow })}
                  />

                  <SelectControl
                    label={__('Currency labels', 'currencyrate-today-currency-blocks')}
                    value={attributes.currencyLabelMode}
                    options={[
                      { label: __('Code', 'currencyrate-today-currency-blocks'), value: 'code' },
                      { label: __('Name', 'currencyrate-today-currency-blocks'), value: 'name' }
                    ]}
                    onChange={(currencyLabelMode) =>
                      setAttributes({ currencyLabelMode: currencyLabelMode as FxAttributes['currencyLabelMode'] })
                    }
                  />

                  <ToggleControl
                    label={__('Show currency symbols', 'currencyrate-today-currency-blocks')}
                    help={__('Uses native symbol resolution with plugin fallback map for unsupported currencies', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showCurrencySymbols}
                    onChange={(showCurrencySymbols) => setAttributes({ showCurrencySymbols })}
                  />

                  <TextControl
                    label={__('Source label', 'currencyrate-today-currency-blocks')}
                    help={__('Custom label shown on the widget. Leave empty to use the source name.', 'currencyrate-today-currency-blocks')}
                    value={attributes.sourceLabel}
                    placeholder={resolvedSourceLabel}
                    maxLength={20}
                    onChange={(sourceLabel) => setAttributes({ sourceLabel })}
                  />

                  <ToggleControl
                    label={__('Show timestamp', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showTimestamp}
                    onChange={(showTimestamp) => setAttributes({ showTimestamp })}
                  />

                  <ToggleControl
                    label={__('Show 24h change', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showChange}
                    onChange={(showChange) => setAttributes({ showChange })}
                  />

                  <ToggleControl
                    label={__('Compact mode', 'currencyrate-today-currency-blocks')}
                    help={__('Smaller rows and tighter spacing', 'currencyrate-today-currency-blocks')}
                    checked={attributes.compactMode}
                    onChange={(compactMode) => setAttributes({ compactMode })}
                  />

                  <ToggleControl
                    label={__('Show flags', 'currencyrate-today-currency-blocks')}
                    help={__('Show flags next to currencies', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showFlags}
                    onChange={(showFlags) => setAttributes({ showFlags })}
                  />

                  <ToggleControl
                    label={__('Attribution', 'currencyrate-today-currency-blocks')}
                    help={__('Show optional credit link in widget footer.', 'currencyrate-today-currency-blocks')}
                    checked={attributes.attribution}
                    onChange={(attribution) => setAttributes({ attribution })}
                  />

                  <ToggleControl
                    label={__('Fit to content width', 'currencyrate-today-currency-blocks')}
                    help={
                      attributes.fitWidth
                        ? __('Shrinks to fit content', 'currencyrate-today-currency-blocks')
                        : __('Stretches to fill width', 'currencyrate-today-currency-blocks')
                    }
                    checked={attributes.fitWidth}
                    onChange={(fitWidth) => setAttributes({ fitWidth })}
                  />

                  <ToggleControl
                    label={__('Enable JSON-LD', 'currencyrate-today-currency-blocks')}
                    help={__('Adds ExchangeRateSpecification structured data snippets for visible rates.', 'currencyrate-today-currency-blocks')}
                    checked={attributes.enableStructuredData}
                    onChange={(enableStructuredData) => setAttributes({ enableStructuredData })}
                  />
                </PanelBody>
                {!attributes.seamless && (
                <PanelBody title={__('Style', 'currencyrate-today-currency-blocks')} initialOpen={false}>
                  <SelectControl
                    label={__('Accent display', 'currencyrate-today-currency-blocks')}
                    value={attributes.accentMode}
                    options={[
                      { label: __('Top stripe', 'currencyrate-today-currency-blocks'), value: 'stripe' },
                      { label: __('Solid color border', 'currencyrate-today-currency-blocks'), value: 'color-border' },
                      { label: __('None', 'currencyrate-today-currency-blocks'), value: 'none' }
                    ]}
                    onChange={(accentMode) =>
                      setAttributes({ accentMode: accentMode as FxAttributes['accentMode'] })
                    }
                  />

                  <BaseControl
                    label={__('Theme preset', 'currencyrate-today-currency-blocks')}
                    help={selectedTheme.name}
                  >
                    <ColorPalette
                      colors={THEME_SWATCHES}
                      value={selectedTheme.light.primary}
                      disableCustomColors
                      onChange={(color?: string) => {
                        if (!color) {
                          return;
                        }

                        const accentTheme = THEME_KEY_BY_COLOR[color.toLowerCase()];
                        if (accentTheme) {
                          setAttributes({ accentTheme });
                        }
                      }}
                    />
                  </BaseControl>

                  {attributes.accentMode === 'stripe' && (
                    <RangeControl
                      label={__('Gradient angle', 'currencyrate-today-currency-blocks')}
                      value={attributes.accentAngle}
                      min={0}
                      max={360}
                      onChange={(accentAngle) =>
                        setAttributes({ accentAngle: Number(accentAngle ?? 135) })
                      }
                    />
                  )}
                </PanelBody>
                )}
              </>
            )
          }
        </TabPanel>
      </InspectorControls>

      <ServerSideRender block="crtoday/exchange-rates" attributes={attributes} />
    </div>
  );
};
