import { useState, useEffect, useCallback } from 'react';
import { Settings, Save, X, AlertTriangle, Check, RotateCcw } from 'lucide-react';
import { Card } from './common/Card';

interface DesignVariable {
  name: string;
  min: number;
  max: number;
  type?: string;
  description?: string;
}

interface Objective {
  name: string;
  direction: 'minimize' | 'maximize';
  description?: string;
  unit?: string;
}

interface OptimizationConfig {
  study_name?: string;
  description?: string;
  design_variables?: DesignVariable[];
  objectives?: Objective[];
  constraints?: any[];
  optimization_settings?: {
    n_trials?: number;
    sampler?: string;
    [key: string]: any;
  };
  [key: string]: any;
}

interface ConfigEditorProps {
  studyId: string;
  onClose: () => void;
  onSaved?: () => void;
}

export function ConfigEditor({ studyId, onClose, onSaved }: ConfigEditorProps) {
  const [config, setConfig] = useState<OptimizationConfig | null>(null);
  const [originalConfig, setOriginalConfig] = useState<OptimizationConfig | null>(null);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<string | null>(null);
  const [isRunning, setIsRunning] = useState(false);
  const [activeTab, setActiveTab] = useState<'general' | 'variables' | 'objectives' | 'settings' | 'json'>('general');
  const [jsonText, setJsonText] = useState('');
  const [jsonError, setJsonError] = useState<string | null>(null);

  // Load config
  useEffect(() => {
    const loadConfig = async () => {
      try {
        setLoading(true);
        setError(null);

        // Check if optimization is running
        const processRes = await fetch(`/api/optimization/studies/${studyId}/process`);
        const processData = await processRes.json();
        setIsRunning(processData.is_running);

        // Load config
        const configRes = await fetch(`/api/optimization/studies/${studyId}/config`);
        if (!configRes.ok) {
          throw new Error('Failed to load config');
        }
        const configData = await configRes.json();
        setConfig(configData.config);
        setOriginalConfig(JSON.parse(JSON.stringify(configData.config)));
        setJsonText(JSON.stringify(configData.config, null, 2));
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load config');
      } finally {
        setLoading(false);
      }
    };

    loadConfig();
  }, [studyId]);

  // Handle JSON text changes
  const handleJsonChange = useCallback((text: string) => {
    setJsonText(text);
    setJsonError(null);
    try {
      const parsed = JSON.parse(text);
      setConfig(parsed);
    } catch (err) {
      setJsonError('Invalid JSON');
    }
  }, []);

  // Save config
  const handleSave = async () => {
    if (!config || isRunning) return;

    try {
      setSaving(true);
      setError(null);
      setSuccess(null);

      const res = await fetch(`/api/optimization/studies/${studyId}/config`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ config })
      });

      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.detail || 'Failed to save config');
      }

      setSuccess('Configuration saved successfully');
      setOriginalConfig(JSON.parse(JSON.stringify(config)));
      onSaved?.();

      // Clear success after 3 seconds
      setTimeout(() => setSuccess(null), 3000);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save config');
    } finally {
      setSaving(false);
    }
  };

  // Reset to original
  const handleReset = () => {
    if (originalConfig) {
      setConfig(JSON.parse(JSON.stringify(originalConfig)));
      setJsonText(JSON.stringify(originalConfig, null, 2));
      setJsonError(null);
    }
  };

  // Check if there are unsaved changes
  const hasChanges = config && originalConfig
    ? JSON.stringify(config) !== JSON.stringify(originalConfig)
    : false;

  // Update a design variable
  const updateDesignVariable = (index: number, field: keyof DesignVariable, value: any) => {
    if (!config?.design_variables) return;

    const newVars = [...config.design_variables];
    newVars[index] = { ...newVars[index], [field]: value };
    setConfig({ ...config, design_variables: newVars });
    setJsonText(JSON.stringify({ ...config, design_variables: newVars }, null, 2));
  };

  // Update an objective
  const updateObjective = (index: number, field: keyof Objective, value: any) => {
    if (!config?.objectives) return;

    const newObjs = [...config.objectives];
    newObjs[index] = { ...newObjs[index], [field]: value };
    setConfig({ ...config, objectives: newObjs });
    setJsonText(JSON.stringify({ ...config, objectives: newObjs }, null, 2));
  };

  // Update optimization settings
  const updateSettings = (field: string, value: any) => {
    if (!config) return;

    const newSettings = { ...config.optimization_settings, [field]: value };
    setConfig({ ...config, optimization_settings: newSettings });
    setJsonText(JSON.stringify({ ...config, optimization_settings: newSettings }, null, 2));
  };

  if (loading) {
    return (
      <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50">
        <Card className="w-full max-w-4xl max-h-[90vh] p-6">
          <div className="flex items-center justify-center py-12">
            <div className="animate-spin w-8 h-8 border-2 border-primary-500 border-t-transparent rounded-full"></div>
          </div>
        </Card>
      </div>
    );
  }

  return (
    <div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
      <Card className="w-full max-w-4xl max-h-[90vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-dark-600">
          <div className="flex items-center gap-3">
            <Settings className="w-5 h-5 text-primary-400" />
            <h2 className="text-lg font-semibold text-white">Edit Configuration</h2>
            {hasChanges && (
              <span className="px-2 py-0.5 bg-yellow-500/20 text-yellow-400 text-xs rounded">
                Unsaved changes
              </span>
            )}
          </div>
          <button
            onClick={onClose}
            className="p-2 text-dark-400 hover:text-white transition-colors"
          >
            <X className="w-5 h-5" />
          </button>
        </div>

        {/* Warning if running */}
        {isRunning && (
          <div className="m-4 p-3 bg-red-500/10 border border-red-500/30 rounded-lg flex items-center gap-3">
            <AlertTriangle className="w-5 h-5 text-red-400" />
            <span className="text-red-400 text-sm">
              Optimization is running. Stop it before editing configuration.
            </span>
          </div>
        )}

        {/* Tabs */}
        <div className="flex border-b border-dark-600 px-4">
          {(['general', 'variables', 'objectives', 'settings', 'json'] as const).map(tab => (
            <button
              key={tab}
              onClick={() => setActiveTab(tab)}
              className={`px-4 py-2 text-sm font-medium transition-colors ${
                activeTab === tab
                  ? 'text-primary-400 border-b-2 border-primary-400 -mb-[2px]'
                  : 'text-dark-400 hover:text-white'
              }`}
            >
              {tab.charAt(0).toUpperCase() + tab.slice(1)}
            </button>
          ))}
        </div>

        {/* Content */}
        <div className="flex-1 overflow-y-auto p-4">
          {error && (
            <div className="mb-4 p-3 bg-red-500/10 border border-red-500/30 rounded-lg text-red-400 text-sm">
              {error}
            </div>
          )}

          {success && (
            <div className="mb-4 p-3 bg-green-500/10 border border-green-500/30 rounded-lg text-green-400 text-sm flex items-center gap-2">
              <Check className="w-4 h-4" />
              {success}
            </div>
          )}

          {config && (
            <>
              {/* General Tab */}
              {activeTab === 'general' && (
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium text-dark-300 mb-1">
                      Study Name
                    </label>
                    <input
                      type="text"
                      value={config.study_name || ''}
                      onChange={(e) => {
                        setConfig({ ...config, study_name: e.target.value });
                        setJsonText(JSON.stringify({ ...config, study_name: e.target.value }, null, 2));
                      }}
                      disabled={isRunning}
                      className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-dark-300 mb-1">
                      Description
                    </label>
                    <textarea
                      value={config.description || ''}
                      onChange={(e) => {
                        setConfig({ ...config, description: e.target.value });
                        setJsonText(JSON.stringify({ ...config, description: e.target.value }, null, 2));
                      }}
                      disabled={isRunning}
                      rows={3}
                      className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                    />
                  </div>
                </div>
              )}

              {/* Design Variables Tab */}
              {activeTab === 'variables' && (
                <div className="space-y-4">
                  <p className="text-dark-400 text-sm mb-4">
                    Edit design variable bounds. These control the parameter search space.
                  </p>
                  {config.design_variables?.map((dv, index) => (
                    <div key={dv.name} className="p-4 bg-dark-750 rounded-lg">
                      <div className="font-medium text-white mb-3">{dv.name}</div>
                      <div className="grid grid-cols-2 gap-4">
                        <div>
                          <label className="block text-xs text-dark-400 mb-1">Min</label>
                          <input
                            type="number"
                            value={dv.min}
                            onChange={(e) => updateDesignVariable(index, 'min', parseFloat(e.target.value))}
                            disabled={isRunning}
                            step="any"
                            className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                          />
                        </div>
                        <div>
                          <label className="block text-xs text-dark-400 mb-1">Max</label>
                          <input
                            type="number"
                            value={dv.max}
                            onChange={(e) => updateDesignVariable(index, 'max', parseFloat(e.target.value))}
                            disabled={isRunning}
                            step="any"
                            className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                          />
                        </div>
                      </div>
                    </div>
                  ))}
                </div>
              )}

              {/* Objectives Tab */}
              {activeTab === 'objectives' && (
                <div className="space-y-4">
                  <p className="text-dark-400 text-sm mb-4">
                    Configure optimization objectives and their directions.
                  </p>
                  {config.objectives?.map((obj, index) => (
                    <div key={obj.name} className="p-4 bg-dark-750 rounded-lg">
                      <div className="font-medium text-white mb-3">{obj.name}</div>
                      <div className="grid grid-cols-2 gap-4">
                        <div>
                          <label className="block text-xs text-dark-400 mb-1">Direction</label>
                          <select
                            value={obj.direction}
                            onChange={(e) => updateObjective(index, 'direction', e.target.value)}
                            disabled={isRunning}
                            className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                          >
                            <option value="minimize">Minimize</option>
                            <option value="maximize">Maximize</option>
                          </select>
                        </div>
                        <div>
                          <label className="block text-xs text-dark-400 mb-1">Unit</label>
                          <input
                            type="text"
                            value={obj.unit || ''}
                            onChange={(e) => updateObjective(index, 'unit', e.target.value)}
                            disabled={isRunning}
                            className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                          />
                        </div>
                      </div>
                    </div>
                  ))}
                </div>
              )}

              {/* Settings Tab */}
              {activeTab === 'settings' && (
                <div className="space-y-4">
                  <p className="text-dark-400 text-sm mb-4">
                    Optimization algorithm settings.
                  </p>
                  <div className="grid grid-cols-2 gap-4">
                    <div>
                      <label className="block text-sm font-medium text-dark-300 mb-1">
                        Number of Trials
                      </label>
                      <input
                        type="number"
                        value={config.optimization_settings?.n_trials || 100}
                        onChange={(e) => updateSettings('n_trials', parseInt(e.target.value))}
                        disabled={isRunning}
                        min={1}
                        className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                      />
                    </div>
                    <div>
                      <label className="block text-sm font-medium text-dark-300 mb-1">
                        Sampler
                      </label>
                      <select
                        value={config.optimization_settings?.sampler || 'TPE'}
                        onChange={(e) => updateSettings('sampler', e.target.value)}
                        disabled={isRunning}
                        className="w-full px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white disabled:opacity-50"
                      >
                        <option value="TPE">TPE (Tree-structured Parzen Estimator)</option>
                        <option value="CMA-ES">CMA-ES (Evolution Strategy)</option>
                        <option value="NSGA-II">NSGA-II (Multi-objective)</option>
                        <option value="Random">Random</option>
                        <option value="QMC">QMC (Quasi-Monte Carlo)</option>
                      </select>
                    </div>
                  </div>
                </div>
              )}

              {/* JSON Tab */}
              {activeTab === 'json' && (
                <div className="space-y-2">
                  <p className="text-dark-400 text-sm">
                    Edit the raw JSON configuration. Be careful with syntax.
                  </p>
                  {jsonError && (
                    <div className="p-2 bg-red-500/10 border border-red-500/30 rounded text-red-400 text-xs">
                      {jsonError}
                    </div>
                  )}
                  <textarea
                    value={jsonText}
                    onChange={(e) => handleJsonChange(e.target.value)}
                    disabled={isRunning}
                    spellCheck={false}
                    className="w-full h-96 px-3 py-2 bg-dark-700 border border-dark-600 rounded-lg text-white font-mono text-sm disabled:opacity-50"
                  />
                </div>
              )}
            </>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-between p-4 border-t border-dark-600">
          <button
            onClick={handleReset}
            disabled={!hasChanges || isRunning}
            className="flex items-center gap-2 px-4 py-2 text-dark-400 hover:text-white disabled:opacity-50 transition-colors"
          >
            <RotateCcw className="w-4 h-4" />
            Reset
          </button>
          <div className="flex gap-2">
            <button
              onClick={onClose}
              className="px-4 py-2 bg-dark-700 text-white rounded-lg hover:bg-dark-600 transition-colors"
            >
              Cancel
            </button>
            <button
              onClick={handleSave}
              disabled={saving || !hasChanges || isRunning || !!jsonError}
              className="flex items-center gap-2 px-4 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 disabled:opacity-50 transition-colors"
            >
              <Save className="w-4 h-4" />
              {saving ? 'Saving...' : 'Save Changes'}
            </button>
          </div>
        </div>
      </Card>
    </div>
  );
}

export default ConfigEditor;
