import { useState, useMemo, useCallback, useRef } from 'react';
import { Button, Input, SegmentedTabs, FileInput } from '@cameleer/design-system';
import type { FileInputHandle } from '@cameleer/design-system';
import { Plus, Copy, Trash2, FileUp } from 'lucide-react';
import styles from './EnvEditor.module.css';
import {
  type EnvEntry,
  type Format,
  parseText,
  toText,
  detectFormat,
} from './env-convert';

interface EnvEditorProps {
  value: EnvEntry[];
  onChange: (entries: EnvEntry[]) => void;
  disabled?: boolean;
}

const FORMAT_TABS = [
  { label: 'Table', value: 'table' as const },
  { label: 'Properties', value: 'properties' as const },
  { label: 'YAML', value: 'yaml' as const },
  { label: '.env', value: 'env' as const },
];

type ViewMode = 'table' | Format;

export function EnvEditor({ value, onChange, disabled }: EnvEditorProps) {
  const [view, setView] = useState<ViewMode>('table');
  const [textDraft, setTextDraft] = useState<string | null>(null);
  const [showImport, setShowImport] = useState(false);
  const fileRef = useRef<FileInputHandle>(null);

  // When switching views, convert between formats
  const handleViewChange = useCallback(
    (next: string) => {
      const nextView = next as ViewMode;

      // If leaving a text view, commit the draft
      if (textDraft !== null && view !== 'table') {
        const parsed = parseText(textDraft, view as Format);
        onChange(parsed);
      }

      // If entering a text view, generate text from current entries
      if (nextView !== 'table') {
        setTextDraft(toText(value, nextView as Format));
      } else {
        setTextDraft(null);
      }

      setView(nextView);
    },
    [view, textDraft, value, onChange],
  );

  // Text for current format (memoized from entries when no draft)
  const displayText = useMemo(() => {
    if (textDraft !== null) return textDraft;
    if (view === 'table') return '';
    return toText(value, view as Format);
  }, [textDraft, value, view]);

  // Commit text on blur
  const handleTextBlur = useCallback(() => {
    if (textDraft !== null && view !== 'table') {
      const parsed = parseText(textDraft, view as Format);
      onChange(parsed);
    }
  }, [textDraft, view, onChange]);

  // Table row handlers
  const updateRow = useCallback(
    (i: number, field: 'key' | 'value', val: string) => {
      const next = [...value];
      next[i] = { ...next[i], [field]: val };
      onChange(next);
    },
    [value, onChange],
  );

  const deleteRow = useCallback(
    (i: number) => onChange(value.filter((_, j) => j !== i)),
    [value, onChange],
  );

  const addRow = useCallback(
    () => onChange([...value, { key: '', value: '' }]),
    [value, onChange],
  );

  // Copy to clipboard
  const handleCopy = useCallback(() => {
    const text = view === 'table' ? toText(value, 'env') : displayText;
    navigator.clipboard.writeText(text);
  }, [view, value, displayText]);

  // Clear all
  const handleClear = useCallback(() => {
    onChange([]);
    setTextDraft(view !== 'table' ? '' : null);
  }, [view, onChange]);

  // File import
  const handleImportFile = useCallback(() => {
    const file = fileRef.current?.file;
    if (!file) return;
    const reader = new FileReader();
    reader.onload = () => {
      const text = reader.result as string;
      const format = detectFormat(text);
      const parsed = parseText(text, format);
      // Merge with existing (dedupe by key, new values win)
      const existing = new Map(value.map((e) => [e.key, e]));
      for (const entry of parsed) {
        existing.set(entry.key, entry);
      }
      const merged = Array.from(existing.values());
      onChange(merged);
      fileRef.current?.clear();
      setShowImport(false);
      // If in text view, update the draft
      if (view !== 'table') {
        setTextDraft(toText(merged, view as Format));
      }
    };
    reader.readAsText(file);
  }, [value, onChange, view]);

  return (
    <div className={styles.wrap}>
      <div className={styles.toolbar}>
        <SegmentedTabs
          tabs={FORMAT_TABS}
          active={view}
          onChange={handleViewChange}
        />
        <div className={styles.actions}>
          <Button
            size="sm"
            variant="ghost"
            disabled={disabled}
            onClick={() => setShowImport(!showImport)}
            title="Import from file"
          >
            <FileUp size={14} />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handleCopy}
            title="Copy to clipboard"
          >
            <Copy size={14} />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            disabled={disabled}
            onClick={handleClear}
            title="Clear all"
          >
            <Trash2 size={14} />
          </Button>
        </div>
      </div>

      {showImport && (
        <div className={styles.importZone}>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
            <div style={{ flex: 1 }}>
              <FileInput
                ref={fileRef}
                accept=".properties,.yml,.yaml,.env,.cfg,.txt"
                placeholder="Drop .properties, .yaml, or .env file"
                icon={<FileUp size={16} />}
              />
            </div>
            <Button size="sm" variant="primary" onClick={handleImportFile}>
              Import
            </Button>
          </div>
        </div>
      )}

      {view === 'table' ? (
        <div className={styles.tableBody}>
          {value.map((entry, i) => (
            <div key={i} className={styles.row}>
              <Input
                disabled={disabled}
                value={entry.key}
                onChange={(e) => updateRow(i, 'key', e.target.value)}
                className={styles.rowKey}
                placeholder="KEY"
              />
              <Input
                disabled={disabled}
                value={entry.value}
                onChange={(e) => updateRow(i, 'value', e.target.value)}
                className={styles.rowValue}
                placeholder="value"
              />
              <button
                className={styles.deleteBtn}
                disabled={disabled}
                onClick={() => deleteRow(i)}
              >
                &times;
              </button>
            </div>
          ))}
          {value.length === 0 && !disabled && (
            <div className={styles.empty}>
              No variables configured. Add one or import from a file.
            </div>
          )}
          {!disabled && (
            <Button size="sm" variant="secondary" onClick={addRow}>
              <Plus size={14} style={{ marginRight: 4 }} />
              Add Variable
            </Button>
          )}
        </div>
      ) : (
        <textarea
          className={styles.textEditor}
          value={displayText}
          onChange={(e) => setTextDraft(e.target.value)}
          onBlur={handleTextBlur}
          disabled={disabled}
          spellCheck={false}
          placeholder={
            view === 'yaml'
              ? 'spring:\n  datasource:\n    url: jdbc:...'
              : view === 'properties'
                ? 'server.port=8080\nspring.datasource.url=jdbc:...'
                : 'SERVER_PORT=8080\nSPRING_DATASOURCE_URL=jdbc:...'
          }
        />
      )}
    </div>
  );
}
