import { groupBy, startCase } from 'lodash';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { copyToClipboard } from '../../helpers/copy-to-clipboard';
import { SilkeColorTheme } from '../../silke-theme-provider';
import { SilkeBox } from '../silke-box';
import { SilkeButton } from '../silke-button';
import { SilkeColorPickerButton } from '../silke-color-picker';
import { SilkeText, SilkeTitle } from '../silke-text';
import { SilkeTextField } from '../silke-text-field';

type SilkeThemeEditorProps = {
  theme: SilkeColorTheme;
  search?: string;
  onChange: (theme: SilkeColorTheme) => void;
};

export function SilkeThemeEditor({ theme, search, onChange }: SilkeThemeEditorProps) {
  const colors: string[] = useMemo(
    () => [
      'color-accent-60',
      'color-accent-50',
      'color-accent-40',
      'color-accent-30',
      'color-accent-20',
      'color-accent-10',
      'color-error-60',
      'color-error-50',
      'color-error-40',
      'color-error-30',
      'color-error-20',
      'color-error-10',
      'color-warning-60',
      'color-warning-50',
      'color-warning-40',
      'color-warning-30',
      'color-warning-20',
      'color-warning-10',
      'color-success-60',
      'color-success-50',
      'color-success-40',
      'color-success-30',
      'color-success-20',
      'color-success-10',
      'color-neutral-0',
      'color-neutral-40',
      'color-neutral-30',
      'color-neutral-20',
      'color-neutral-10',
      'color-neutral-5',
      'color-neutral-100',
      'color-neutral-90',
      'color-neutral-80',
      'color-neutral-70',
      'color-neutral-60',
      'color-neutral-50',
      'color-support-secondary-60',
      'color-support-secondary-50',
      'color-support-secondary-40',
      'color-support-secondary-30',
      'color-support-secondary-20',
      'color-support-secondary-10',
      'color-support-primary-60',
      'color-support-primary-50',
      'color-support-primary-40',
      'color-support-primary-30',
      'color-support-primary-20',
      'color-support-primary-10',
      'color-brand-primary-60',
      'color-brand-primary-bright',
      'color-brand-primary-30',
      'color-brand-primary-10',
      'color-brand-secondary-bright',
      'color-brand-secondary-30',
      'color-brand-secondary-10',
      'color-brand-secondary-60',
      'color-brand-tertiary-bright',
      'color-brand-tertiary-60',
      'color-brand-tertiary-30',
      'color-brand-tertiary-10',
      'color-brand-quaternary-60',
      'color-brand-quaternary-30',
      'color-brand-quaternary-10',
    ],
    [],
  );

  const ref = useRef<HTMLDivElement>(null);
  const [currentColors, setCurrentColors] = useState<SilkeColorTheme>({});
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const computed = getComputedStyle(el);
    const current: SilkeColorTheme = {};
    for (const color of colors) {
      current[color as keyof SilkeColorTheme] = computed.getPropertyValue('--' + color);
    }

    setCurrentColors(current);
  }, [colors]);

  const group = useMemo(() => {
    const filteredColors = search ? colors.filter((c) => c.search(search) !== -1) : colors;
    return groupBy(filteredColors, (color) => color.replace('color-', '').split('-')[0]);
  }, [search, colors]);

  return (
    <SilkeBox column gap ref={ref} fill flex>
      <SilkeBox hAlign="end">
        <SilkeButton
          size="base"
          label="Copy CSS code"
          onClick={() => {
            let s = '';
            let group = '';
            for (const color of colors) {
              const colorGroup = startCase(color).split(' ').slice(1, -1).join('/');
              if (colorGroup !== group) {
                group = colorGroup;
                s += `\n//${colorGroup}\n`;
              }
              const value =
                theme?.[color as keyof SilkeColorTheme] ||
                currentColors[color as keyof SilkeColorTheme];
              s += `"${color}" ${value},\n`;
            }

            copyToClipboard(s.slice(0, -2) + ';');
          }}
        />
      </SilkeBox>
      {Object.entries(group).map(([groupName, colors]) => (
        <SilkeBox column gap="s" key={groupName}>
          <SilkeTitle kind="xs">{startCase(groupName)}</SilkeTitle>
          {colors.map((color) => (
            <SilkeBox gap="s" key={color} vAlign="end">
              <SilkeColorPickerButton
                value={
                  theme?.[color as keyof SilkeColorTheme] ||
                  currentColors[color as keyof SilkeColorTheme] ||
                  'black'
                }
                noVariables
                onChange={(value) => {
                  onChange({ ...theme, [color]: value });
                }}
              />
              <SilkeTextField
                label={startCase(color).split(' ').slice(1).join('/')}
                value={
                  theme?.[color as keyof SilkeColorTheme] ||
                  currentColors[color as keyof SilkeColorTheme] ||
                  'black'
                }
                onChange={(value: string) => {
                  onChange({ ...theme, [color]: value });
                }}
              />
            </SilkeBox>
          ))}
        </SilkeBox>
      ))}
    </SilkeBox>
  );
}
