import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import {
  BaseControl,
  ColorPalette,
  PanelBody,
  RangeControl,
  SelectControl,
  TabPanel,
  ToggleControl,
  __experimentalNumberControl as NumberControl
} from '@wordpress/components';
import { useEffect, useRef, useState } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import ServerSideRender from '@wordpress/server-side-render';
import { __ } from '@wordpress/i18n';
import Big from 'big.js';

import type { RateCardAttributes } from './types';
import { getCurrencies } from '../../currencies';
import { initChartsIn } from '../../frontend/shared/sparkline';
import { CurrencyRichSelect } from '../shared/CurrencyRichSelect';
import { SourceCurrencyNotice } from '../shared/SourceCurrencyNotice';
import {
  THEME_SWATCHES,
  THEME_KEY_BY_COLOR,
} from '../shared/accentThemes';
import '../shared/editorGlobals';
import {
  normalizeAmountInput,
  useAvailableCodes,
  resolveSelectedTheme,
  buildSourceOptions,
  parseSourceValue,
} from '../shared/editorUtils';

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

const currencies = getCurrencies();

export const RateCardEdit = ({ attributes, setAttributes }: EditProps) => {
  const wrapRef = useRef<HTMLDivElement>(null);
  const blockProps = useBlockProps({ ref: wrapRef });
  const editorUi = window.crtodayEditorCurrenciesUi ?? {};
  const editorLabels = editorUi.labels ?? {};
  const selectedTheme = resolveSelectedTheme(attributes.accentTheme);
  const availableCodes = useAvailableCodes(attributes.sourceId, attributes.deal);

  /* Chart data availability check */
  const [chartAvailable, setChartAvailable] = useState<boolean | null>(null);
  useEffect(() => {
    setChartAvailable(null);
    const controller = new AbortController();
    apiFetch<Array<{ ts: number; rate: number }>>({
      path: addQueryArgs('/crtoday/v1/chart', {
        source: attributes.sourceId,
        deal: attributes.deal,
        from: attributes.from,
        to: attributes.to,
        period: '24h',
      }),
      signal: controller.signal,
    })
      .then((points) => setChartAvailable(Array.isArray(points) && points.length >= 3))
      .catch(() => setChartAvailable(false));
    return () => controller.abort();
  }, [attributes.sourceId, attributes.deal, attributes.from, attributes.to]);

  /* Re-init sparkline charts whenever ServerSideRender updates the DOM */
  useEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    initChartsIn(el);
    const obs = new MutationObserver(() => initChartsIn(el));
    obs.observe(el, { childList: true, subtree: true });
    return () => obs.disconnect();
  }, []);

  return (
    <div {...blockProps}>
      <InspectorControls>
        <TabPanel
          tabs={[
            { name: 'settings', title: __('Settings', 'currencyrate-today-currency-blocks') },
            { name: 'display', title: __('Display', 'currencyrate-today-currency-blocks') },
            { name: 'style', title: __('Style', 'currencyrate-today-currency-blocks') },
          ]}
        >
          {(tab) =>
            tab.name === 'settings' ? (
              <>
                <PanelBody title={__('Data settings', 'currencyrate-today-currency-blocks')} initialOpen>
                  <SelectControl __next40pxDefaultSize={true} 
                    label={__('Data source', 'currencyrate-today-currency-blocks')}
                    help={__('For daily mid-market rates, use CurrencyRate (default).', 'currencyrate-today-currency-blocks')}
                    value={`${attributes.sourceId}:${attributes.deal}`}
                    options={buildSourceOptions(editorLabels)}
                    onChange={(value) => {
                      if (!value) return;
                      const { sourceId, deal } = parseSourceValue(value);
                      setAttributes({ sourceId, deal });
                    }}
                  />

                  <SourceCurrencyNotice
                    availableCodes={availableCodes}
                    selectedCodes={[attributes.from, attributes.to]}
                  />

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

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

                  <NumberControl __next40pxDefaultSize={true} 
                    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 __next40pxDefaultSize={true} 
                    label={__('Adjustment (%)', 'currencyrate-today-currency-blocks')}
                    help={__('Applies percentage to the final displayed values.', '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 === 'display' ? (
              <>
                <PanelBody title={__('Presentation', 'currencyrate-today-currency-blocks')} initialOpen>
                  <RangeControl __next40pxDefaultSize={true} 
                    label={__('Decimals', 'currencyrate-today-currency-blocks')}
                    value={attributes.decimals}
                    min={0}
                    max={8}
                    onChange={(decimals) => setAttributes({ decimals: Number(decimals) })}
                  />

                  <ToggleControl 
                    label={__('Transparent', 'currencyrate-today-currency-blocks')}
                    help={__('Remove background, border, shadow and theme — use this when placing inside a custom container', 'currencyrate-today-currency-blocks')}
                    checked={attributes.seamless}
                    onChange={(seamless) => setAttributes({ seamless })}
                  />

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

                  <SelectControl __next40pxDefaultSize={true} 
                    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 RateCardAttributes['theme'] })}
                  />

                  <RangeControl __next40pxDefaultSize={true} 
                    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 __next40pxDefaultSize={true} 
                    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 RateCardAttributes['currencyLabelMode'] })
                    }
                  />

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

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

                  <ToggleControl 
                    label={__('Show chart', 'currencyrate-today-currency-blocks')}
                    help={
                      chartAvailable === false
                        ? __('Not enough historical data for this source / pair.', 'currencyrate-today-currency-blocks')
                        : __('Show a mini chart with period tabs below the rate.', 'currencyrate-today-currency-blocks')
                    }
                    checked={attributes.showChart && chartAvailable !== false}
                    disabled={chartAvailable === false || chartAvailable === null}
                    onChange={(showChart) => setAttributes({ showChart })}
                  />

                  <ToggleControl 
                    label={__("Show day's range", 'currencyrate-today-currency-blocks')}
                    help={__('Display the 24-hour low–high range with a progress bar.', 'currencyrate-today-currency-blocks')}
                    checked={attributes.showRange}
                    onChange={(showRange) => setAttributes({ showRange })}
                  />

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

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

                  <ToggleControl 
                    label={__('Full width', 'currencyrate-today-currency-blocks')}
                    help={
                      attributes.fullWidth
                        ? __('Stretches to fill width', 'currencyrate-today-currency-blocks')
                        : __('Shrinks to fit content', 'currencyrate-today-currency-blocks')
                    }
                    checked={attributes.fullWidth}
                    onChange={(fullWidth) => setAttributes({ fullWidth })}
                  />
                </PanelBody>
              </>
            ) : tab.name === 'style' ? (
              <>
                {attributes.seamless ? (
                  <PanelBody title={__('Style', 'currencyrate-today-currency-blocks')} initialOpen>
                    <p style={{ color: 'var(--wp-components-color-foreground-disabled, #757575)' }}>
                      {__('Style options are not available in seamless mode.', 'currencyrate-today-currency-blocks')}
                    </p>
                  </PanelBody>
                ) : (
                <PanelBody title={__('Style', 'currencyrate-today-currency-blocks')} initialOpen>
                  <SelectControl __next40pxDefaultSize={true} 
                    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 RateCardAttributes['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 __next40pxDefaultSize={true} 
                      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/rate-card" attributes={attributes} />
    </div>
  );
};
