import {
    Calendar,
    CheckSquare,
    ChevronDown,
    Edit,
    Eye,
    EyeOff,
    FileText,
    Hash,
    Move,
    Trash2,
    Type
} from 'lucide-react';
import React, { useCallback, useMemo, useState } from 'react';
import { Rnd } from 'react-rnd';
import { ElementLayout, ElementType, FormLayoutSettings, TemplateElement } from '../../types/template';
import { Button } from '../ui/button';
import { Input } from '../ui/input';
import { Textarea } from '../ui/textarea';

interface VisualLayoutEditorProps {
    elements: TemplateElement[];
    layoutSettings: FormLayoutSettings;
    onElementUpdate: (elementId: string, updates: Partial<TemplateElement>) => void;
    onElementDelete: (elementId: string) => void;
    onLayoutSettingsChange: (settings: FormLayoutSettings) => void;
    onElementEdit?: (element: TemplateElement) => void;
}

interface DraggableElementProps {
    element: TemplateElement;
    isSelected: boolean;
    onSelect: () => void;
    onUpdate: (layout: ElementLayout) => void;
    onDelete: () => void;
    onEdit?: () => void;
    gridSize: number;
}

const ELEMENT_ICONS: Record<ElementType, React.ReactNode> = {
    text: <Type className="h-4 w-4" />,
    textarea: <FileText className="h-4 w-4" />,
    number: <Hash className="h-4 w-4" />,
    date: <Calendar className="h-4 w-4" />,
    select: <ChevronDown className="h-4 w-4" />,
    radio: <CheckSquare className="h-4 w-4" />,
    checkbox: <CheckSquare className="h-4 w-4" />,
};

const ELEMENT_COLORS: Record<ElementType, string> = {
    text: 'bg-blue-100 border-blue-300 text-blue-800',
    textarea: 'bg-green-100 border-green-300 text-green-800',
    number: 'bg-purple-100 border-purple-300 text-purple-800',
    date: 'bg-orange-100 border-orange-300 text-orange-800',
    select: 'bg-indigo-100 border-indigo-300 text-indigo-800',
    radio: 'bg-pink-100 border-pink-300 text-pink-800',
    checkbox: 'bg-teal-100 border-teal-300 text-teal-800',
};

const DraggableElement: React.FC<DraggableElementProps> = React.memo(({
    element,
    isSelected,
    onSelect,
    onUpdate,
    onDelete,
    onEdit,
    gridSize,
}) => {
    const layout = element.layout || { x: 50, y: 50, width: 300, height: 80, zIndex: 1 };

    const handleDragStop = useCallback((_e: any, d: { x: number; y: number }) => {
        // Вызываем onUpdate только если позиция действительно изменилась,
        // чтобы избежать ложных срабатываний при клике.
        if (d.x !== layout.x || d.y !== layout.y) {
            onUpdate({ ...layout, x: d.x, y: d.y });
        }
    }, [layout, onUpdate]);

    const handleResizeStop = useCallback((_e: any, _dir: any, ref: HTMLElement, _delta: any, pos: { x: number; y: number }) => {
        onUpdate({
            ...layout,
            width: parseInt(ref.style.width, 10),
            height: parseInt(ref.style.height, 10),
            x: pos.x,
            y: pos.y,
        });
    }, [layout, onUpdate]);

    const handleDeleteClick = useCallback((e: React.MouseEvent) => {
        e.stopPropagation();
        onDelete();
    }, [onDelete]);

    const handleEditClick = useCallback((e: React.MouseEvent) => {
        e.stopPropagation();
        onEdit?.();
    }, [onEdit]);

    /*
     * Render a lightweight, disabled preview of the element so that the user can
     * see how the real control looks directly on the canvas instead of a plain
     * colored square. Keeping the elements disabled and wrapped with
     * `pointer-events-none` guarantees that they do not interfere with the drag
     * behaviour of Rnd and keeps rendering costs minimal.
     */
    const previewControl = useMemo(() => {
        switch (element.type) {
            case 'text':
                return <Input readOnly placeholder={element.placeholder || 'Введите текст'} className="pointer-events-none w-full bg-white" />;
            case 'textarea':
                return <Textarea readOnly rows={3} placeholder={element.placeholder || 'Введите текст'} className="pointer-events-none w-full resize-none bg-white" />;
            case 'number':
                return <Input type="number" readOnly placeholder={element.placeholder || '0'} className="pointer-events-none w-full bg-white" />;
            case 'date':
                return <Input type="date" readOnly className="pointer-events-none w-full bg-white" />;
            case 'select':
                return (
                    <div className="pointer-events-none w-full">
                        <div className="flex h-10 w-full items-center justify-between rounded-md border border-input bg-white px-3 py-2 text-sm">
                            <span className="text-gray-500">
                                {element.placeholder || 'Выберите значение'}
                            </span>
                            <ChevronDown className="h-4 w-4 opacity-50" />
                        </div>
                    </div>
                );
            case 'radio':
                return (
                    <div className="space-y-2 pointer-events-none">
                        {(element.options?.length ? element.options : [{ label: 'Вариант 1' }]).map((opt, idx) => (
                            <div key={idx} className="flex items-center gap-2">
                                <div className="w-4 h-4 border-2 border-gray-300 rounded-full bg-white" />
                                <span className="text-sm text-gray-900">{opt.label || opt.value || `Вариант ${idx + 1}`}</span>
                            </div>
                        ))}
                    </div>
                );
            case 'checkbox':
                return (
                    <div className="flex items-center gap-2 pointer-events-none">
                        <div className="w-4 h-4 border-2 border-gray-300 rounded bg-white" />
                        <span className="text-sm text-gray-900">{element.placeholder || element.label || 'Отметить'}</span>
                    </div>
                );
            default:
                return null;
        }
    }, [element]);

    return (
        <Rnd
            dragGrid={[gridSize, gridSize]}
            resizeGrid={[gridSize, gridSize]}
            default={{
                x: layout.x,
                y: layout.y,
                width: layout.width,
                height: layout.height,
            }}
            onDragStop={handleDragStop}
            onResizeStop={handleResizeStop}
            minWidth={120}
            minHeight={32}
            bounds="parent"
            className={`group ${isSelected ? 'ring-2 ring-blue-500 ring-offset-2 z-20' : 'z-10'}`}
            onClick={onSelect}
        >
            <div className={`h-full cursor-move ${
                isSelected 
                    ? 'bg-blue-50/20 border border-blue-200/50 rounded-md p-2' 
                    : 'bg-transparent border border-transparent rounded-md hover:bg-gray-50/10 p-1'
            }`}>
                {/* Label and controls (only visible when selected or hovered) */}
                <div className={`flex items-center justify-between mb-1 ${
                    isSelected ? 'opacity-100' : 'opacity-0 group-hover:opacity-60'
                }`}>
                    <div className="flex items-center gap-2">
                        <span className="font-medium text-xs text-gray-600 truncate">
                            {element.label || element.name || `${element.type} элемент`}
                        </span>
                    </div>
                    <div className="flex items-center gap-1">
                        {onEdit && (
                            <Button
                                variant="ghost"
                                size="icon"
                                className="h-4 w-4 cursor-pointer hover:bg-blue-100"
                                onClick={handleEditClick}
                            >
                                <Edit className="h-2.5 w-2.5 text-blue-600" />
                            </Button>
                        )}
                        <Button
                            variant="ghost"
                            size="icon"
                            className="h-4 w-4 cursor-pointer hover:bg-red-100"
                            onClick={handleDeleteClick}
                        >
                            <Trash2 className="h-2.5 w-2.5 text-red-600" />
                        </Button>
                    </div>
                </div>

                {/* Real element preview */}
                {previewControl && (
                    <div className="space-y-1 flex-1">
                        {element.label && (
                            <label className="block text-sm font-medium text-gray-900 pointer-events-none">
                                {element.label}
                                {element.required && <span className="text-red-500 ml-1">*</span>}
                            </label>
                        )}
                        {previewControl}
                    </div>
                )}

                {/* Additional info (only visible on selection to preserve visual clarity & perf) */}
                {isSelected && (
                    <div className="text-xs opacity-75 space-y-1 mt-1">
                        {element.targetCells && element.targetCells.length > 0 && (
                            <div className="font-mono truncate">
                                {element.targetCells.map((cell, i) => (
                                    <span key={i} className="mr-1 px-1 py-0.5 bg-black/5 rounded text-xs">{cell.sheet}!{cell.cell}</span>
                                ))}
                            </div>
                        )}
                    </div>
                )}
            </div>
        </Rnd>
    );
});

export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
    elements,
    layoutSettings,
    onElementUpdate,
    onElementDelete,
    onLayoutSettingsChange,
    onElementEdit,
}) => {
    const [selectedElementId, setSelectedElementId] = useState<string | null>(null);

    const canvasSize = useMemo(() => {
        const PADDING_Y = 200;

        const baseWidth = 1200;
        const baseHeight = 800;

        if (elements.length === 0) {
            return { width: baseWidth, height: baseHeight };
        }

        const contentHeight = Math.max(
            0,
            ...elements.map((el) => (el.layout?.y || 0) + (el.layout?.height || 0)),
        );

        return {
            width: baseWidth,
            height: Math.max(baseHeight, contentHeight + PADDING_Y),
        };
    }, [elements]);

    const GridPattern = useMemo(() => {
        if (!layoutSettings.showGrid) return null;
        const gridSize = layoutSettings.gridSize;
        return (
            <div
                className="absolute inset-0 pointer-events-none"
                style={{
                    backgroundImage: `linear-gradient(to right, #e5e7eb 1px, transparent 1px), linear-gradient(to bottom, #e5e7eb 1px, transparent 1px)`,
                    backgroundSize: `${gridSize}px ${gridSize}px`,
                }}
            />
        );
    }, [layoutSettings.showGrid, layoutSettings.gridSize]);

    const handleElementUpdateCallback = useCallback((elementId: string, layout: ElementLayout) => {
        onElementUpdate(elementId, { layout });
    }, [onElementUpdate]);
    
    const handleCanvasClick = useCallback((e: React.MouseEvent) => {
        if (e.target === e.currentTarget) {
            setSelectedElementId(null);
        }
    }, []);

    const toggleGrid = useCallback(() => {
        onLayoutSettingsChange({ ...layoutSettings, showGrid: !layoutSettings.showGrid });
    }, [layoutSettings, onLayoutSettingsChange]);
    
    return (
        <div className="flex flex-col h-full bg-gray-50">
            <div className="flex items-center justify-between p-2 bg-white border-b shrink-0">
                <span className="text-sm text-gray-600 px-2">{elements.length} элементов на холсте</span>
                <Button variant="outline" size="sm" onClick={toggleGrid}>
                    {layoutSettings.showGrid ? <EyeOff className="h-4 w-4 mr-2" /> : <Eye className="h-4 w-4 mr-2" />}
                    {layoutSettings.showGrid ? 'Скрыть сетку' : 'Показать сетку'}
                </Button>
            </div>

            <div className="flex-1 relative overflow-auto" onClick={handleCanvasClick}>
                <div
                    className="relative bg-white shadow-lg mx-auto my-8"
                    style={{ width: canvasSize.width, height: canvasSize.height }}
                >
                    {GridPattern}
                    {elements.map((element) => (
                        <DraggableElement
                            key={element.id}
                            element={element}
                            isSelected={selectedElementId === element.id}
                            onSelect={() => setSelectedElementId(element.id)}
                            onUpdate={(layout) => handleElementUpdateCallback(element.id, layout)}
                            onDelete={() => onElementDelete(element.id)}
                            onEdit={onElementEdit ? () => onElementEdit(element) : undefined}
                            gridSize={layoutSettings.gridSize}
                        />
                    ))}
                    {elements.length === 0 && (
                        <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
                            <div className="text-center text-gray-400">
                                <Move className="h-16 w-16 mx-auto mb-4" />
                                <p className="text-xl font-medium mb-2">Холст пуст</p>
                                <p className="text-sm">Добавьте свой первый элемент</p>
                            </div>
                        </div>
                    )}
                </div>
            </div>
        </div>
    );
}; 