import React, { CSSProperties, useState } from 'react';
import { SilkeBox, SilkeButton, SilkeDivider, useFormField, useSilkeCSSContext } from '..';
import { isVariableV2, SilkeColorPicker } from '../silke-color-picker';
import { SilkeSwatches } from '../silke-color-swatches';
import { FormFieldProps } from '../silke-form';
import { SilkeGradientSlider } from './silke-gradient-slider';
import { SilkeGradient, useGradientModel } from './silke-gradient-utils';
import styles from './silke-gradient-picker.module.scss';
import { SilkeGradientPosition } from './silke-gradient-position';
import { isGradient } from '@vev/utils';

type SilkeGradientPickerProps = FormFieldProps<string>;

export function SilkeGradientPicker({ ...props }: SilkeGradientPickerProps) {
  const { value, onChange } = useFormField(props);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const { variablesv2 } = useSilkeCSSContext();

  const variable = variablesv2.find((v) => `var(--vev-${v.key})` === value);
  const gradientValue = variable?.value || value || 'linear-gradient(90deg, #000, #fff)';

  const [gradient, setGradient] = useGradientModel(gradientValue);
  const { color } = gradient.stops[selectedIndex] || { color: '#000' };

  const handleChange = (gradient: SilkeGradient) => {
    const css = setGradient(gradient);
    onChange(css);
  };

  const handleColorChange = (color: string) => {
    if (isVariableV2(color)) {
      const variable = variablesv2.find((v) => color.includes(v.key));
      if (variable) {
        // Check if the variable is a gradient, if so, replace whole gradient with the variable
        if (isGradient(variable.value)) {
          onChange(`var(--vev-${variable.key})`);
          return;
        }
      }
    }

    const newGradient = { ...gradient };
    newGradient.stops = newGradient.stops.slice();
    newGradient.stops[selectedIndex] = { ...newGradient.stops[selectedIndex], color };
    handleChange(newGradient);
  };

  const handleType = (type: 'linear' | 'radial') => handleChange({ type, stops: gradient.stops });

  const handleReverse = () =>
    handleChange({
      ...gradient,
      stops: gradient.stops.map((s) => ({ ...s, position: 1 - s.position })),
    });

  const handleGradientSwatchSelect = (
    swatchValue: string,
    type: 'color' | 'gradient' | 'variable',
  ) => {
    if (type === 'gradient') {
      // Replace entire gradient
      onChange(swatchValue);
    } else {
      // Replace color of current gradient stop
      handleColorChange(swatchValue);
    }
  };

  return (
    <SilkeBox column className={styles.root} style={{ '--index': selectedIndex } as CSSProperties}>
      <SilkeBox gap="s" vAlign="center">
        <SilkeButton
          size="s"
          flex
          kind="ghost"
          label="Linear"
          selected={gradient.type === 'linear'}
          onClick={() => handleType('linear')}
        />
        <SilkeButton
          flex
          kind="ghost"
          size="s"
          label="Radial"
          selected={gradient.type === 'radial'}
          onClick={() => handleType('radial')}
        />
      </SilkeBox>
      <SilkeBox vPad="s" vAlign="center" gap="s">
        <SilkeGradientSlider
          value={gradient}
          selected={selectedIndex}
          onChange={handleChange}
          onSelected={setSelectedIndex}
        />
        <SilkeButton size="s" kind="ghost" icon="arrow.left.arrow.right" onClick={handleReverse} />
        <SilkeGradientPosition gradient={gradient} onChange={handleChange} />
      </SilkeBox>

      <SilkeColorPicker
        value={color}
        hideSwatches
        hidePalettes
        noVariables
        onChange={handleColorChange}
      />

      <SilkeBox column vPad="s" gap="s">
        <SilkeDivider dark />
        <SilkeSwatches
          selected={value || 'linear-gradient(90deg, #000, #fff)'}
          gradient
          onSelect={handleGradientSwatchSelect}
        />
      </SilkeBox>
    </SilkeBox>
  );
}
