import { useState, useEffect } from 'react';
import { X, Settings as SettingsIcon, ChevronRight } from 'lucide-react';
import { Core } from '@esengine/ecs-framework';
import { SettingsService } from '../services/SettingsService';
import { SettingsRegistry, SettingCategory, SettingDescriptor, ProjectService, PluginManager, IPluginManager } from '@esengine/editor-core';
import { PluginListSetting } from './PluginListSetting';
import '../styles/SettingsWindow.css';

interface SettingsWindowProps {
  onClose: () => void;
  settingsRegistry: SettingsRegistry;
  initialCategoryId?: string;
}

export function SettingsWindow({ onClose, settingsRegistry, initialCategoryId }: SettingsWindowProps) {
    const [categories, setCategories] = useState<SettingCategory[]>([]);
    const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(initialCategoryId || null);
    const [values, setValues] = useState<Map<string, any>>(new Map());
    const [errors, setErrors] = useState<Map<string, string>>(new Map());

    useEffect(() => {
        const allCategories = settingsRegistry.getAllCategories();
        setCategories(allCategories);

        if (allCategories.length > 0 && !selectedCategoryId) {
            // 如果有 initialCategoryId，尝试使用它
            if (initialCategoryId && allCategories.some(c => c.id === initialCategoryId)) {
                setSelectedCategoryId(initialCategoryId);
            } else {
                const firstCategory = allCategories[0];
                if (firstCategory) {
                    setSelectedCategoryId(firstCategory.id);
                }
            }
        }

        const settings = SettingsService.getInstance();
        const projectService = Core.services.tryResolve<ProjectService>(ProjectService);
        const allSettings = settingsRegistry.getAllSettings();
        const initialValues = new Map<string, any>();

        for (const [key, descriptor] of allSettings.entries()) {
            // Project-scoped settings are loaded from ProjectService
            if (key.startsWith('project.') && projectService) {
                if (key === 'project.uiDesignResolution.width') {
                    const resolution = projectService.getUIDesignResolution();
                    initialValues.set(key, resolution.width);
                } else if (key === 'project.uiDesignResolution.height') {
                    const resolution = projectService.getUIDesignResolution();
                    initialValues.set(key, resolution.height);
                } else if (key === 'project.uiDesignResolution.preset') {
                    const resolution = projectService.getUIDesignResolution();
                    initialValues.set(key, `${resolution.width}x${resolution.height}`);
                } else {
                    // For other project settings, use default
                    initialValues.set(key, descriptor.defaultValue);
                }
            } else {
                const value = settings.get(key, descriptor.defaultValue);
                initialValues.set(key, value);
            }
        }

        setValues(initialValues);
    }, [settingsRegistry, selectedCategoryId]);

    const handleValueChange = (key: string, value: any, descriptor: SettingDescriptor) => {
        const newValues = new Map(values);
        newValues.set(key, value);
        setValues(newValues);

        const newErrors = new Map(errors);
        if (!settingsRegistry.validateSetting(descriptor, value)) {
            newErrors.set(key, descriptor.validator?.errorMessage || 'Invalid value');
        } else {
            newErrors.delete(key);
        }
        setErrors(newErrors);
    };

    const handleSave = async () => {
        if (errors.size > 0) {
            return;
        }

        const settings = SettingsService.getInstance();
        const projectService = Core.services.tryResolve<ProjectService>(ProjectService);
        const changedSettings: Record<string, any> = {};

        // Track UI resolution changes for batch saving
        let uiResolutionChanged = false;
        let newWidth = 1920;
        let newHeight = 1080;

        for (const [key, value] of values.entries()) {
            // Project-scoped settings are saved to ProjectService
            if (key.startsWith('project.') && projectService) {
                if (key === 'project.uiDesignResolution.width') {
                    newWidth = value;
                    uiResolutionChanged = true;
                } else if (key === 'project.uiDesignResolution.height') {
                    newHeight = value;
                    uiResolutionChanged = true;
                } else if (key === 'project.uiDesignResolution.preset') {
                    // Preset changes width and height together
                    const [w, h] = value.split('x').map(Number);
                    if (w && h) {
                        newWidth = w;
                        newHeight = h;
                        uiResolutionChanged = true;
                    }
                }
                changedSettings[key] = value;
            } else {
                settings.set(key, value);
                changedSettings[key] = value;
            }
        }

        // Save UI resolution if changed
        if (uiResolutionChanged && projectService) {
            await projectService.setUIDesignResolution({ width: newWidth, height: newHeight });
        }

        window.dispatchEvent(new CustomEvent('settings:changed', {
            detail: changedSettings
        }));

        onClose();
    };

    const handleCancel = () => {
        onClose();
    };

    const renderSettingInput = (setting: SettingDescriptor) => {
        const value = values.get(setting.key) ?? setting.defaultValue;
        const error = errors.get(setting.key);

        switch (setting.type) {
            case 'boolean':
                return (
                    <div className="settings-field">
                        <label className="settings-label settings-label-checkbox">
                            <input
                                type="checkbox"
                                className="settings-checkbox"
                                checked={value}
                                onChange={(e) => handleValueChange(setting.key, e.target.checked, setting)}
                            />
                            <span>{setting.label}</span>
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'number':
                return (
                    <div className="settings-field">
                        <label className="settings-label">
                            {setting.label}
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        <input
                            type="number"
                            className={`settings-input ${error ? 'settings-input-error' : ''}`}
                            value={value}
                            onChange={(e) => handleValueChange(setting.key, parseInt(e.target.value) || 0, setting)}
                            placeholder={setting.placeholder}
                            min={setting.min}
                            max={setting.max}
                            step={setting.step}
                        />
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'string':
                return (
                    <div className="settings-field">
                        <label className="settings-label">
                            {setting.label}
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        <input
                            type="text"
                            className={`settings-input ${error ? 'settings-input-error' : ''}`}
                            value={value}
                            onChange={(e) => handleValueChange(setting.key, e.target.value, setting)}
                            placeholder={setting.placeholder}
                        />
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'select':
                return (
                    <div className="settings-field">
                        <label className="settings-label">
                            {setting.label}
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        <select
                            className={`settings-select ${error ? 'settings-input-error' : ''}`}
                            value={value}
                            onChange={(e) => {
                                const option = setting.options?.find((opt) => String(opt.value) === e.target.value);
                                if (option) {
                                    handleValueChange(setting.key, option.value, setting);
                                }
                            }}
                        >
                            {setting.options?.map((option) => (
                                <option key={String(option.value)} value={String(option.value)}>
                                    {option.label}
                                </option>
                            ))}
                        </select>
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'range':
                return (
                    <div className="settings-field">
                        <label className="settings-label">
                            {setting.label}
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        <div className="settings-range-wrapper">
                            <input
                                type="range"
                                className="settings-range"
                                value={value}
                                onChange={(e) => handleValueChange(setting.key, parseFloat(e.target.value), setting)}
                                min={setting.min}
                                max={setting.max}
                                step={setting.step}
                            />
                            <span className="settings-range-value">{value}</span>
                        </div>
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'color':
                return (
                    <div className="settings-field">
                        <label className="settings-label">
                            {setting.label}
                            {setting.description && (
                                <span className="settings-hint">{setting.description}</span>
                            )}
                        </label>
                        <input
                            type="color"
                            className="settings-color-input"
                            value={value}
                            onChange={(e) => handleValueChange(setting.key, e.target.value, setting)}
                        />
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );

            case 'pluginList': {
                const pluginManager = Core.services.tryResolve<PluginManager>(IPluginManager);
                if (!pluginManager) {
                    return (
                        <div className="settings-field settings-field-full">
                            <p className="settings-error">PluginManager 不可用</p>
                        </div>
                    );
                }
                return (
                    <div className="settings-field settings-field-full">
                        <PluginListSetting pluginManager={pluginManager} />
                        {error && <span className="settings-error">{error}</span>}
                    </div>
                );
            }

            default:
                return null;
        }
    };

    const selectedCategory = categories.find((c) => c.id === selectedCategoryId);

    return (
        <div className="settings-overlay">
            <div className="settings-window">
                <div className="settings-header">
                    <div className="settings-title">
                        <SettingsIcon size={18} />
                        <h2>设置</h2>
                    </div>
                    <button className="settings-close-btn" onClick={handleCancel}>
                        <X size={18} />
                    </button>
                </div>

                <div className="settings-body">
                    <div className="settings-sidebar">
                        {categories.map((category) => (
                            <button
                                key={category.id}
                                className={`settings-category-btn ${selectedCategoryId === category.id ? 'active' : ''}`}
                                onClick={() => setSelectedCategoryId(category.id)}
                            >
                                <span className="settings-category-title">{category.title}</span>
                                {category.description && (
                                    <span className="settings-category-desc">{category.description}</span>
                                )}
                                <ChevronRight size={14} className="settings-category-arrow" />
                            </button>
                        ))}
                    </div>

                    <div className="settings-content">
                        {selectedCategory && selectedCategory.sections.map((section) => (
                            <div key={section.id} className="settings-section">
                                <h3 className="settings-section-title">{section.title}</h3>
                                {section.description && (
                                    <p className="settings-section-description">{section.description}</p>
                                )}
                                {section.settings.map((setting) => (
                                    <div key={setting.key}>
                                        {renderSettingInput(setting)}
                                    </div>
                                ))}
                            </div>
                        ))}

                        {!selectedCategory && (
                            <div className="settings-empty">
                                <SettingsIcon size={48} />
                                <p>请选择一个设置分类</p>
                            </div>
                        )}
                    </div>
                </div>

                <div className="settings-footer">
                    <button className="settings-btn settings-btn-cancel" onClick={handleCancel}>
            取消
                    </button>
                    <button
                        className="settings-btn settings-btn-save"
                        onClick={handleSave}
                        disabled={errors.size > 0}
                    >
            保存
                    </button>
                </div>
            </div>
        </div>
    );
}
