import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Plus, Trash2, Code } from 'lucide-react';
import Tooltip from '../Tooltip/Tooltip';
import { Info } from 'lucide-react';

interface KeyValuePair {
  id: string;
  key: string;
  value: string;
  type: 'string' | 'number' | 'boolean';
}

interface KeyValueEditorProps {
  label: string;
  tooltip?: string;
  value?: Record<string, any> | string; // Can accept JSON object or JSON string
  onChange?: (value: Record<string, any>) => void;
  placeholder?: string;
  suggestions?: Array<{ key: string; value: string; type?: 'string' | 'number' | 'boolean' }>;
  className?: string;
}

export const KeyValueEditor: React.FC<KeyValueEditorProps> = ({
  label,
  tooltip,
  value,
  onChange,
  placeholder,
  suggestions = [],
  className = ''
}) => {
  const { t } = useTranslation('wizards');
  const [pairs, setPairs] = useState<KeyValuePair[]>([]);
  const [showRawJson, setShowRawJson] = useState(false);
  const [rawJson, setRawJson] = useState('');
  const [jsonError, setJsonError] = useState<string | null>(null);
  const [isInitialized, setIsInitialized] = useState(false);

  // Initialize pairs from value only on first mount or when value changes from external source
  useEffect(() => {
    // Skip if already initialized with internal changes
    if (isInitialized && pairs.length > 0) {
      return;
    }

    if (!value) {
      setPairs([]);
      setRawJson('{}');
      setIsInitialized(true);
      return;
    }

    try {
      let jsonObj: Record<string, any>;

      if (typeof value === 'string') {
        if (value.trim() === '') {
          setPairs([]);
          setRawJson('{}');
          setIsInitialized(true);
          return;
        }
        jsonObj = JSON.parse(value);
      } else {
        jsonObj = value;
      }

      // Only update if there's actual data
      if (Object.keys(jsonObj).length > 0) {
        const newPairs: KeyValuePair[] = Object.entries(jsonObj).map(([key, val], index) => ({
          id: `pair-${Date.now()}-${index}`,
          key,
          value: String(val),
          type: detectType(val)
        }));

        setPairs(newPairs);
        setRawJson(JSON.stringify(jsonObj, null, 2));
        setJsonError(null);
      }
      setIsInitialized(true);
    } catch (error) {
      // If parsing fails, treat as empty
      setPairs([]);
      setRawJson(typeof value === 'string' ? value : '{}');
      setJsonError('Invalid JSON');
      setIsInitialized(true);
    }
  }, [value, isInitialized, pairs.length]);

  const detectType = (value: any): 'string' | 'number' | 'boolean' => {
    if (typeof value === 'boolean') return 'boolean';
    if (typeof value === 'number') return 'number';
    return 'string';
  };

  const convertValue = (value: string, type: 'string' | 'number' | 'boolean'): any => {
    if (type === 'boolean') {
      return value === 'true' || value === '1';
    }
    if (type === 'number') {
      const num = parseFloat(value);
      return isNaN(num) ? 0 : num;
    }
    return value;
  };

  const pairsToJson = (pairs: KeyValuePair[]): Record<string, any> => {
    const obj: Record<string, any> = {};
    pairs.forEach(pair => {
      if (pair.key.trim()) {
        obj[pair.key.trim()] = convertValue(pair.value, pair.type);
      }
    });
    return obj;
  };

  const handleAddPair = () => {
    const newPair: KeyValuePair = {
      id: `pair-${Date.now()}`,
      key: '',
      value: '',
      type: 'string'
    };
    const newPairs = [...pairs, newPair];
    setPairs(newPairs);
    // Don't call onChange yet - wait for user to fill in the key
    // onChange will be called when they type in the key/value
  };

  const handleRemovePair = (id: string) => {
    const newPairs = pairs.filter(p => p.id !== id);
    setPairs(newPairs);
    onChange?.(pairsToJson(newPairs));
  };

  const handlePairChange = (id: string, field: 'key' | 'value' | 'type', newValue: string) => {
    const newPairs = pairs.map(pair => {
      if (pair.id === id) {
        return { ...pair, [field]: newValue };
      }
      return pair;
    });
    setPairs(newPairs);
    onChange?.(pairsToJson(newPairs));
  };

  const handleApplySuggestion = (suggestion: { key: string; value: string; type?: 'string' | 'number' | 'boolean' }) => {
    // Check if key already exists
    const existingPair = pairs.find(p => p.key === suggestion.key);
    if (existingPair) {
      // Update existing
      handlePairChange(existingPair.id, 'value', suggestion.value);
      if (suggestion.type) {
        handlePairChange(existingPair.id, 'type', suggestion.type);
      }
    } else {
      // Add new
      const newPair: KeyValuePair = {
        id: `pair-${Date.now()}`,
        key: suggestion.key,
        value: suggestion.value,
        type: suggestion.type || 'string'
      };
      const newPairs = [...pairs, newPair];
      setPairs(newPairs);
      onChange?.(pairsToJson(newPairs));
    }
  };

  const handleRawJsonChange = (jsonString: string) => {
    setRawJson(jsonString);

    try {
      const parsed = JSON.parse(jsonString);
      setJsonError(null);

      const newPairs: KeyValuePair[] = Object.entries(parsed).map(([key, val], index) => ({
        id: `pair-${Date.now()}-${index}`,
        key,
        value: String(val),
        type: detectType(val)
      }));

      setPairs(newPairs);
      onChange?.(parsed);
    } catch (error) {
      setJsonError('Invalid JSON format');
    }
  };

  return (
    <div className={`space-y-3 ${className}`}>
      {/* Header */}
      <div className="flex items-center justify-between">
        <label className="block text-sm font-medium text-[var(--text-secondary)]">
          {label}
          {tooltip && (
            <Tooltip content={tooltip}>
              <Info className="inline w-4 h-4 ml-1 text-[var(--text-tertiary)]" />
            </Tooltip>
          )}
        </label>

        <button
          type="button"
          onClick={() => setShowRawJson(!showRawJson)}
          className="text-xs text-[var(--text-tertiary)] hover:text-[var(--text-primary)] flex items-center gap-1 transition-colors"
        >
          <Code className="w-3 h-3" />
          {showRawJson ? t('keyValueEditor.showBuilder') : t('keyValueEditor.showJson')}
        </button>
      </div>

      {showRawJson ? (
        /* Raw JSON Editor */
        <div className="space-y-2">
          <textarea
            value={rawJson}
            onChange={(e) => handleRawJsonChange(e.target.value)}
            placeholder={placeholder || '{}'}
            rows={6}
            className={`w-full px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)] font-mono text-xs ${
              jsonError ? 'border-red-500' : 'border-[var(--border-secondary)]'
            }`}
          />
          {jsonError && (
            <p className="text-xs text-red-500">{jsonError}</p>
          )}
        </div>
      ) : (
        /* Key-Value Builder */
        <div className="space-y-2">
          {/* Suggestions */}
          {suggestions.length > 0 && pairs.length === 0 && (
            <div className="bg-[var(--bg-secondary)] border border-[var(--border-secondary)] rounded-lg p-3">
              <p className="text-xs text-[var(--text-tertiary)] mb-2">
                {t('keyValueEditor.suggestions')}:
              </p>
              <div className="flex flex-wrap gap-2">
                {suggestions.map((suggestion, index) => (
                  <button
                    key={index}
                    type="button"
                    onClick={() => handleApplySuggestion(suggestion)}
                    className="text-xs px-2 py-1 bg-[var(--bg-primary)] border border-[var(--border-secondary)] rounded hover:border-[var(--color-primary)] transition-colors"
                  >
                    {suggestion.key}: {suggestion.value}
                  </button>
                ))}
              </div>
            </div>
          )}

          {/* Key-Value Pairs */}
          {pairs.length > 0 && (
            <div className="space-y-2 max-h-64 overflow-y-auto">
              {pairs.map((pair) => (
                <div key={pair.id} className="flex items-center gap-2">
                  {/* Key Input */}
                  <input
                    type="text"
                    value={pair.key}
                    onChange={(e) => handlePairChange(pair.id, 'key', e.target.value)}
                    placeholder={t('keyValueEditor.keyPlaceholder')}
                    className="flex-1 px-2 py-1.5 text-sm border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]"
                  />

                  {/* Value Input */}
                  {pair.type === 'boolean' ? (
                    <select
                      value={pair.value}
                      onChange={(e) => handlePairChange(pair.id, 'value', e.target.value)}
                      className="flex-1 px-2 py-1.5 text-sm border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]"
                    >
                      <option value="true">true</option>
                      <option value="false">false</option>
                    </select>
                  ) : (
                    <input
                      type={pair.type === 'number' ? 'number' : 'text'}
                      value={pair.value}
                      onChange={(e) => handlePairChange(pair.id, 'value', e.target.value)}
                      placeholder={t('keyValueEditor.valuePlaceholder')}
                      step={pair.type === 'number' ? '0.01' : undefined}
                      className="flex-1 px-2 py-1.5 text-sm border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-primary)]"
                    />
                  )}

                  {/* Type Selector */}
                  <select
                    value={pair.type}
                    onChange={(e) => handlePairChange(pair.id, 'type', e.target.value)}
                    className="w-24 px-2 py-1.5 text-xs border border-[var(--border-secondary)] rounded focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] bg-[var(--bg-primary)] text-[var(--text-secondary)]"
                  >
                    <option value="string">Text</option>
                    <option value="number">Number</option>
                    <option value="boolean">Bool</option>
                  </select>

                  {/* Delete Button */}
                  <button
                    type="button"
                    onClick={() => handleRemovePair(pair.id)}
                    className="p-1.5 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors"
                    title={t('keyValueEditor.remove')}
                  >
                    <Trash2 className="w-4 h-4" />
                  </button>
                </div>
              ))}
            </div>
          )}

          {/* Add Button */}
          <button
            type="button"
            onClick={handleAddPair}
            className="w-full py-2 border-2 border-dashed border-[var(--border-secondary)] text-[var(--text-secondary)] rounded-lg hover:border-[var(--color-primary)] hover:text-[var(--color-primary)] transition-colors font-medium text-sm inline-flex items-center justify-center gap-2"
          >
            <Plus className="w-4 h-4" />
            {t('keyValueEditor.addPair')}
          </button>

          {/* Empty State */}
          {pairs.length === 0 && suggestions.length === 0 && (
            <p className="text-xs text-center text-[var(--text-tertiary)] py-4">
              {t('keyValueEditor.emptyState')}
            </p>
          )}
        </div>
      )}
    </div>
  );
};

export default KeyValueEditor;
