'use client'
import React, {ChangeEvent, useCallback, useContext, useEffect, useMemo} from 'react';
import {Baseline, CaseSensitive, Eye, Indent, Palette, Type} from 'lucide-react';
import {useTranslations} from '@/lib/i18n';
import SelectBox from "@/components/form/SelectBox";
import Button from "@/components/ui/Button";
import {AlertContext, AlertContextProps} from "@/context/AlertContext";

interface UserEditorSettingsProps {
    settings: EditorDisplaySettings;
    onSettingsChange: (settings: EditorDisplaySettings) => void;
}

export interface EditorDisplaySettings {
    zoomLevel: number;
    indent: number;
    lineHeight: number;
    theme: 'clair' | 'sombre' | 'sépia';
    fontFamily: 'lora' | 'serif' | 'sans-serif' | 'monospace';
    maxWidth: number;
    focusMode: boolean;
}

const zoomLabels = ['Très petit', 'Petit', 'Normal', 'Grand', 'Très grand'] as const;
const fontSizes = [14, 16, 18, 20, 22] as const;
const themes = ['clair', 'sombre', 'sépia'] as const;

function isValidFontFamily(value: string): value is EditorDisplaySettings['fontFamily'] {
    return value === 'lora' || value === 'serif' || value === 'sans-serif' || value === 'monospace';
}

const defaultSettings: EditorDisplaySettings = {
    zoomLevel: 3,
    indent: 30,
    lineHeight: 1.5,
    theme: 'sombre',
    fontFamily: 'lora',
    maxWidth: 768,
    focusMode: false
};

export default function UserEditorSettings({settings, onSettingsChange}: UserEditorSettingsProps): React.JSX.Element {
    const t = useTranslations();
    const {errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);

    const handleSettingChange = useCallback(<K extends keyof EditorDisplaySettings>(
        key: K,
        value: EditorDisplaySettings[K]
    ): void => {
        onSettingsChange({...settings, [key]: value});
    }, [settings, onSettingsChange]);
    
    const resetToDefaults = useCallback((): void => {
        onSettingsChange(defaultSettings);
    }, [onSettingsChange]);
    
    const zoomOptions = useMemo((): { value: string; label: string }[] =>
            zoomLabels.map((label: typeof zoomLabels[number], index: number): { value: string; label: string } => ({
                value: (index + 1).toString(),
                label: `${t(`userEditorSettings.zoom.${label}`)} (${fontSizes[index]}px)`
            }))
        , [t]);
    
    const themeButtons = useMemo((): { key: typeof themes[number]; isActive: boolean; className: string }[] =>
            themes.map((theme: typeof themes[number]): {
                key: typeof themes[number];
                isActive: boolean;
                className: string
            } => ({
                key: theme,
                isActive: settings.theme === theme,
                className: `p-2.5 rounded-xl border capitalize transition-colors duration-150 font-medium ${
                    settings.theme === theme
                        ? 'bg-secondary text-primary border-primary'
                        : 'bg-secondary border-secondary text-muted hover:text-text-primary'
                }`
            }))
        , [settings.theme]);

    useEffect((): void => {
        try {
            const savedSettings: string | null = localStorage.getItem('userEditorSettings');
            if (savedSettings) {
                const parsed: Partial<EditorDisplaySettings> = JSON.parse(savedSettings);
                if (parsed && typeof parsed === 'object') {
                    onSettingsChange({...defaultSettings, ...parsed});
                }
            }
        } catch (e: unknown) {
            onSettingsChange(defaultSettings);
        }
    }, [onSettingsChange]);

    useEffect((): () => void => {
        const timeoutId: ReturnType<typeof setTimeout> = setTimeout((): void => {
            try {
                localStorage.setItem('userEditorSettings', JSON.stringify(settings));
            } catch (e: unknown) {
                if (e instanceof Error) {
                    errorMessage(t('userEditorSettings.saveError'));
                } else {
                    errorMessage(t('userEditorSettings.unknownError'));
                }
            }
        }, 100);

        return (): void => clearTimeout(timeoutId);
    }, [settings]);
    
    return (
        <div
            className="p-5 h-full overflow-y-auto">
            <div className="flex items-center gap-3 mb-8 pb-4 border-b border-secondary">
                <Eye className="text-primary w-6 h-6" strokeWidth={1.75}/>
                <h3 className="text-xl font-['ADLaM_Display'] text-text-primary">{t("userEditorSettings.displayPreferences")}</h3>
            </div>
            
            <div className="space-y-6">
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <CaseSensitive className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.textSize")}
                    </label>
                    <SelectBox
                        defaultValue={settings.zoomLevel.toString()}
                        onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => {
                            handleSettingChange('zoomLevel', Number(e.target.value))
                        }}
                        data={zoomOptions}
                    />
                </div>
                
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <Indent className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.indent")}
                    </label>
                    <div className="space-y-2">
                        <input
                            type="range"
                            min={0}
                            max={50}
                            step={5}
                            value={settings.indent}
                            onChange={(e: ChangeEvent<HTMLInputElement>): void => handleSettingChange('indent', Number(e.target.value))}
                            className="w-full accent-primary"
                        />
                        <div className="flex justify-between text-sm text-muted">
                            <span>{t("userEditorSettings.indentNone")}</span>
                            <span className="text-text-primary font-medium">{settings.indent}px</span>
                            <span>{t("userEditorSettings.indentMax")}</span>
                        </div>
                    </div>
                </div>
                
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <Baseline className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.lineHeight")}
                    </label>
                    <SelectBox
                        defaultValue={settings.lineHeight.toString()}
                        onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => handleSettingChange('lineHeight', Number(e.target.value))}
                        data={[
                            {value: "1.2", label: t("userEditorSettings.lineHeightCompact")},
                            {value: "1.5", label: t("userEditorSettings.lineHeightNormal")},
                            {value: "1.75", label: t("userEditorSettings.lineHeightSpaced")},
                            {value: "2", label: t("userEditorSettings.lineHeightDouble")}
                        ]}
                    />
                </div>
                
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <Type className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.fontFamily")}
                    </label>
                    <SelectBox
                        defaultValue={settings.fontFamily}
                        onChangeCallBack={(e: ChangeEvent<HTMLSelectElement>): void => {
                            const fontValue: string = e.target.value;
                            if (isValidFontFamily(fontValue)) {
                                handleSettingChange('fontFamily', fontValue);
                            }
                        }}
                        data={[
                            {value: "lora", label: t("userEditorSettings.fontLora")},
                            {value: "serif", label: t("userEditorSettings.fontSerif")},
                            {value: "sans-serif", label: t("userEditorSettings.fontSansSerif")},
                            {value: "monospace", label: t("userEditorSettings.fontMonospace")}
                        ]}
                    />
                </div>
                
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <Baseline className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.maxWidth")}
                    </label>
                    <div className="space-y-2">
                        <input
                            type="range"
                            min={600}
                            max={1200}
                            step={50}
                            value={settings.maxWidth}
                            onChange={(e: ChangeEvent<HTMLInputElement>): void => handleSettingChange('maxWidth', Number(e.target.value))}
                            className="w-full accent-primary"
                        />
                        <div className="flex justify-between text-sm text-muted">
                            <span>{t("userEditorSettings.maxWidthNarrow")}</span>
                            <span className="text-text-primary font-medium">{settings.maxWidth}px</span>
                            <span>{t("userEditorSettings.maxWidthWide")}</span>
                        </div>
                    </div>
                </div>
                
                <div>
                    <label className="flex items-center gap-2 mb-2 text-text-primary">
                        <Palette className="text-muted w-5 h-5" strokeWidth={1.75}/>
                        {t("userEditorSettings.theme")}
                    </label>
                    <div className="grid grid-cols-3 gap-2">
                        {themeButtons.map((themeBtn: {
                            key: typeof themes[number];
                            isActive: boolean;
                            className: string
                        }) => (
                            <button
                                key={themeBtn.key}
                                onClick={(): void => handleSettingChange('theme', themeBtn.key)}
                                className={themeBtn.className}
                            >
                                {t(`userEditorSettings.themeOption.${themeBtn.key}`)}
                            </button>
                        ))}
                    </div>
                </div>
                
                <div>
                    <label className="flex items-center gap-2 cursor-pointer">
                        <input
                            type="checkbox"
                            checked={settings.focusMode}
                            onChange={(e: ChangeEvent<HTMLInputElement>): void => handleSettingChange('focusMode', e.target.checked)}
                            className="w-4 h-4 accent-primary"
                        />
                        <span className="text-text-primary">{t("userEditorSettings.focusMode")}</span>
                    </label>
                </div>
                
                <div className="pt-6 border-t border-secondary">
                    <Button variant="secondary" onClick={resetToDefaults} fullWidth>
                        {t("userEditorSettings.reset")}
                    </Button>
                </div>
            </div>
        </div>
    );
}