// video-preview-element-transform.js
import { useCallback, useState } from 'react';
import { calculateSnapAndGuides, usesCenterPositioning } from './video-preview-utils';

export const useElementTransform = (timelineElements, dimensions, onElementUpdate, elementRefs) => {
    // Guide lines state
    const [guideLines, setGuideLines] = useState({
        vertical: null,
        horizontal: null,
        showVertical: false,
        showHorizontal: false,
    });

    // Handle drag events with snapping
    const handleDragMove = useCallback(
        (elementId, e) => {
            const node = e.target;
            const element = timelineElements.find((el) => el.id === elementId);
            if (!element) return;

            // Use fixedWidth if available, otherwise use scaled width
            const width = element.fixedWidth || node.width() * node.scaleX();
            const height = node.height() * node.scaleY();

            let positionX = node.x();
            let positionY = node.y();

            // For center-positioned elements, convert to top-left for consistent snapping
            if (usesCenterPositioning(element.type)) {
                positionX = node.x() - width / 2;
                positionY = node.y() - height / 2;
            }

            const snapResult = calculateSnapAndGuides(elementId, positionX, positionY, width, height, timelineElements, dimensions);

            // Update guide lines
            setGuideLines(snapResult.guideLines);

            // Update state during drag
            if (onElementUpdate) {
                onElementUpdate(elementId, {
                    x: snapResult.x,
                    y: snapResult.y,
                });
            }
        },
        [onElementUpdate, dimensions, timelineElements],
    );

    // Create drag bound function for real-time snapping
    const createDragBoundFunc = useCallback(
        (elementId) => {
            return (pos) => {
                const element = timelineElements.find((el) => el.id === elementId);
                if (!element) return pos;

                const node = elementRefs.current[elementId];
                if (!node) return pos;

                // Use fixedWidth if available, otherwise use scaled width
                const width = element.fixedWidth || node.width() * node.scaleX();
                const height = node.height() * node.scaleY();

                let inputX = pos.x;
                let inputY = pos.y;

                // Convert center position to top-left for snapping calculations if needed
                if (usesCenterPositioning(element.type)) {
                    inputX = pos.x - width / 2;
                    inputY = pos.y - height / 2;
                }

                const snapResult = calculateSnapAndGuides(elementId, inputX, inputY, width, height, timelineElements, dimensions);

                // Convert back to the appropriate coordinate system
                if (usesCenterPositioning(element.type)) {
                    return {
                        x: snapResult.x + width / 2,
                        y: snapResult.y + height / 2,
                    };
                } else {
                    return {
                        x: snapResult.x,
                        y: snapResult.y,
                    };
                }
            };
        },
        [timelineElements, dimensions, elementRefs],
    );

    const handleDragEnd = useCallback(
        (elementId, e) => {
            const node = e.target;
            const element = timelineElements.find((el) => el.id === elementId);
            if (!element) return;

            // Clear guide lines when drag ends
            setGuideLines({
                vertical: null,
                horizontal: null,
                showVertical: false,
                showHorizontal: false,
            });

            // Final position update
            const width = element.fixedWidth || node.width() * node.scaleX();
            const height = node.height() * node.scaleY();

            let finalX = node.x();
            let finalY = node.y();

            // Convert center position to top-left for consistent storage
            if (usesCenterPositioning(element.type)) {
                finalX = node.x() - width / 2;
                finalY = node.y() - height / 2;
            }

            if (onElementUpdate) {
                onElementUpdate(elementId, {
                    x: finalX,
                    y: finalY,
                });
            }
        },
        [onElementUpdate, timelineElements],
    );

    // Handle transform events - TRANSFORMER IS SOURCE OF TRUTH
    const handleTransform = useCallback(
        (elementId) => {
            const node = elementRefs.current[elementId];
            const element = timelineElements.find((el) => el.id === elementId);
            if (!node || !onElementUpdate || !element) return;

            // Get rotation - Konva handles snapping automatically with rotationSnaps
            const rotation = node.rotation();

            // Get the scale values from Konva
            const scaleX = node.scaleX();
            const scaleY = node.scaleY();

            let newWidth, newHeight;
            let updates = { rotation };

            if (element.type === 'text') {
                // For text: Convert scale to actual fontSize and reset scale to 1
                const avgScale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
                const newFontSize = Math.round(element.fontSize * avgScale);

                // Clamp font size to reasonable limits
                const clampedFontSize = Math.max(8, Math.min(120, newFontSize));

                updates.fontSize = clampedFontSize;

                // Reset scale to 1 since we've applied it to fontSize
                node.scaleX(1);
                node.scaleY(1);

                // Use fixedWidth if available, otherwise use natural width
                newWidth = element.fixedWidth || node.width();
                newHeight = node.height();
            } else {
                // For images/videos, maintain aspect ratio by using the larger scale
                const scale = Math.max(Math.abs(scaleX), Math.abs(scaleY));
                newWidth = node.width() * scale;
                newHeight = node.height() * scale;

                // Reset scale to 1 and update dimensions to maintain aspect ratio
                node.scaleX(1);
                node.scaleY(1);
                node.width(newWidth);
                node.height(newHeight);

                // Update offset for center rotation
                node.offsetX(newWidth / 2);
                node.offsetY(newHeight / 2);

                updates.width = newWidth;
                updates.height = newHeight;
            }

            // Calculate position for snapping
            let currentX = node.x();
            let currentY = node.y();

            // Convert center position to top-left for snapping if needed
            if (usesCenterPositioning(element.type)) {
                currentX = node.x() - newWidth / 2;
                currentY = node.y() - newHeight / 2;
            }

            // Check for position snapping during transform (but be less aggressive during rotation)
            const isRotating = Math.abs(rotation % 90) > 5; // Not close to perpendicular
            if (!isRotating) {
                const snapResult = calculateSnapAndGuides(elementId, currentX, currentY, newWidth, newHeight, timelineElements, dimensions);

                if (Math.abs(snapResult.x - currentX) > 5 || Math.abs(snapResult.y - currentY) > 5) {
                    if (usesCenterPositioning(element.type)) {
                        // Convert back to center position
                        const newCenterX = snapResult.x + newWidth / 2;
                        const newCenterY = snapResult.y + newHeight / 2;
                        node.x(newCenterX);
                        node.y(newCenterY);
                    } else {
                        // Apply directly for text
                        node.x(snapResult.x);
                        node.y(snapResult.y);
                    }
                    setGuideLines(snapResult.guideLines);
                    currentX = snapResult.x;
                    currentY = snapResult.y;
                }
            } else {
                // Clear guide lines during rotation
                setGuideLines({
                    vertical: null,
                    horizontal: null,
                    showVertical: false,
                    showHorizontal: false,
                });
            }

            // Add position to updates (always store as top-left coordinates)
            updates.x = currentX;
            updates.y = currentY;

            // Update state with all calculated values
            onElementUpdate(elementId, updates);
        },
        [onElementUpdate, dimensions, timelineElements, elementRefs],
    );

    // Clear guide lines helper
    const clearGuideLines = useCallback(() => {
        setGuideLines({
            vertical: null,
            horizontal: null,
            showVertical: false,
            showHorizontal: false,
        });
    }, []);

    return {
        guideLines,
        setGuideLines,
        handleDragMove,
        handleDragEnd,
        createDragBoundFunc,
        handleTransform,
        clearGuideLines,
    };
};
