import type { useComponentData } from "../../hooks/useComponent";
import { useDragComponent } from "../../hooks/useDragComponent";
import { ComponentType } from "../../types/component";
import type { ButtonGeneralData, Component, TableGeneralData, TextFieldGeneralData, TextGeneralData, UIData } from "../../types/component";
import { useEffect, useRef, useState } from "react";


interface CanvasComponentProps {
    component: Component,
    width: number,
    height: number
}

function CanvasComponent({ component, width, height }: CanvasComponentProps) {

    const baseStyle = {
        width: width,
        height: height
    }

    switch (component.type) {
        case ComponentType.Button:
            return (
                <button
                    style={baseStyle}
                    className="bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg transition-colors border border-blue-600 shadow-sm"
                >
                    {(component.generalData as ButtonGeneralData).text}
                </button>
            )
        case ComponentType.Text:
            return (
                <div
                    key={component.id}
                    style={baseStyle}
                    className="text-gray-900 flex items-center overflow-hidden"
                >
                    {(component.generalData as TextGeneralData).text}
                </div>
            )
        case ComponentType.TextField:
            return (
                <input
                    key={component.id}
                    type={(component.generalData as TextFieldGeneralData).text}
                    placeholder={'テキストを入力'}
                    style={baseStyle}
                    readOnly
                    className="border border-gray-500 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none"
                />
            )
        case ComponentType.Table:
            return (
                <div className="flex-col w-full overflow-hidden border" style={baseStyle}>
                    <div className="flex w-full">
                        {(component.generalData as TableGeneralData).columns.map((col, idx) =>
                            <div key={`tableCol${idx}`} className={`flex h-8 text-sm flex-1 justify-center item-center border ${idx !== 0 && "border-l-0"} overflow-hidden py-1 px-2`}>
                                {col}
                            </div>
                        )}
                    </div>
                    <div className="flex w-full">
                        {(component.generalData as TableGeneralData).columns.map((_, idx) =>
                            <div key={`tableCol${idx}`} className={`flex flex-1 h-8 justify-center item-center border border-t-0 ${idx !== 0 && "border-l-0"}`}>
                            </div>
                        )}
                    </div>
                    <div className="flex w-full">
                        {(component.generalData as TableGeneralData).columns.map((_, idx) =>
                            <div key={`tableCol${idx}`} className={`flex flex-1 h-8 justify-center item-center border border-t-0 ${idx !== 0 && "border-l-0"}`}>
                            </div>
                        )}
                    </div>
                    <div className="flex w-full">
                        {(component.generalData as TableGeneralData).columns.map((_, idx) =>
                            <div key={`tableCol${idx}`} className={`flex flex-1 h-8 justify-center item-center border border-t-0 ${idx !== 0 && "border-l-0"}`}>
                            </div>
                        )}
                    </div>
                </div>
            )
    }

}

interface CanvasProps {
    componentData: useComponentData
    canvasWidth: number
    moveComponent: (index: number, uiData: UIData) => void
    selectComponent: (index: number) => void
    resetSelectingComponent: () => void
}

export default function Canvas({
    componentData,
    canvasWidth,
    moveComponent,
    selectComponent: selectComponentGrobal,
    resetSelectingComponent
}: CanvasProps) {

    const outRef = useRef<HTMLDivElement>(null);
    const canvasRef = useRef<HTMLDivElement>(null);
    const [widgetScale] = useState(0.4);
    const [scale, setScale] = useState(1);
    const {
        componentX,
        componentY,
        componentW,
        componentH,
        onDragStart,
        draggingComponent,
        draggingSquare,
        onDragEnd
    } = useDragComponent(
        componentData.selectingComponent,
        componentData.selectingComponentIndex,
        moveComponent,
        scale,
        widgetScale
    );

    const borderWidth = 1;
    const padding = 4;

    useEffect(() => {
        if (!outRef.current) return;

        const observer = new ResizeObserver((entries) => {
            const width = entries[0].contentRect.width;
            const newScale = width / canvasWidth;
            setScale(newScale);
        })

        observer.observe(outRef.current);
        return () => observer.disconnect();
    }, [canvasWidth]);

    const componentStyle = (isSelecting: boolean, component: Component) => {
        if (isSelecting) return {
            position: "absolute" as const,
            left: `${componentX - padding * 2 - borderWidth}px`,
            top: `${componentY - padding * 2 - borderWidth}px`,
            width: `${componentW + padding * 4 + borderWidth * 2}px`,
            height: `${componentH + padding * 4 + borderWidth * 2}px`,
        }

        return {
            position: "absolute" as const,
            left: `${component.uiData.posX}px`,
            top: `${component.uiData.posY}px`,
            width: `${component.uiData.width}px`,
            height: `${component.uiData.height}px`,
        }
    }

    const squareStyle = (index: number) => {
        const squareWidth = padding * 2 + borderWidth;
        if (index == 0) {
            return {
                position: "absolute" as const,
                left: "0px",
                top: "0px",
                width: `${squareWidth}px`,
                height: `${squareWidth}px`,

            }
        } else if (index == 1) {
            return {
                position: "absolute" as const,
                left: `${squareWidth + componentW}px`,
                top: "0px",
                width: `${squareWidth}px`,
                height: `${squareWidth}px`,
            }
        } else if (index == 2) {
            return {
                position: "absolute" as const,
                left: `${squareWidth + componentW}px`,
                top: `${squareWidth + componentH}px`,
                width: `${squareWidth}px`,
                height: `${squareWidth}px`,
            }
        } else {
            return {
                position: "absolute" as const,
                left: "0px",
                top: `${squareWidth + componentH}px`,
                width: `${squareWidth}px`,
                height: `${squareWidth}px`,
            }
        }
    }

    const borderStyle = (index: number) => {
        const squareWidth = padding * 2 + borderWidth;
        if (index == 0) {
            return {
                position: "absolute" as const,
                left: `${squareWidth}px`,
                top: `${padding}px`,
                width: `${componentW}px`,
                height: `${borderWidth}px`,
            }
        } else if (index == 1) {
            return {
                position: "absolute" as const,
                left: `${squareWidth + componentW + padding}px`,
                top: `${squareWidth}px`,
                width: `${borderWidth}px`,
                height: `${componentH}px`,
            }
        } else if (index == 2) {
            return {
                position: "absolute" as const,
                left: `${squareWidth}px`,
                top: `${squareWidth + componentH + padding}px`,
                width: `${componentW}px`,
                height: `${borderWidth}px`,
            }
        } else {
            return {
                position: "absolute" as const,
                left: `${padding}px`,
                top: `${squareWidth}px`,
                width: `${borderWidth}px`,
                height: `${componentH}px`,
            }
        }
    }

    const selectComopnent = (e: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
        e.stopPropagation();
        selectComponentGrobal(index);
    }

    const resetSelectComponent = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
        e.stopPropagation();
        resetSelectingComponent();
    }

    return (
        <div className="flex items-center justify-center h-full bg-gray-50"
            ref={outRef}
        >
            <div
                className="bg-white border border-gray-200 shadow-lg rounded-lg relative overflow-hidden"
                ref={canvasRef}
                onClick={resetSelectComponent}
                style={{
                    aspectRatio: '16/9',
                    width: `${canvasWidth}px`,
                    transform: `scale(${scale})`
                }}
            >
                {/* Canvas Content */}
                <div className="w-full h-full relative" style={{ transform: `scale(${widgetScale})`, transformOrigin: "top left" }}>
                    {componentData.curScreenComponents.map((component, index) =>
                        <div
                            key={index}
                            style={componentStyle(componentData.selectingComponentIndex === index, component)}
                            onClick={(e) => { selectComopnent(e, index) }}
                            draggable
                            onDragStart={(e) => { if (componentData.selectingComponentIndex === index) onDragStart(e) }}
                            onDrag={(e) => { if (componentData.selectingComponentIndex === index) draggingComponent(e) }}
                            onDragEnd={(e) => { if (componentData.selectingComponentIndex === index) onDragEnd(e) }}
                        >
                            {componentData.selectingComponentIndex === index ?
                                <div>
                                    <div
                                        style={{
                                            position: "absolute",
                                            left: `${padding * 2 + borderWidth}px`,
                                            top: `${padding * 2 + borderWidth}px`
                                        }}
                                    >
                                        <CanvasComponent component={component} width={componentW} height={componentH} />
                                    </div>
                                    {[0, 1, 2, 3].map((num) => (
                                        <div
                                            key={`square${num}`}
                                            style={squareStyle(num)}
                                            draggable
                                            onDragStart={onDragStart}
                                            onDrag={(e) => { draggingSquare(e, num) }}
                                            onDragEnd={onDragEnd}
                                            className="bg-black"
                                        />
                                    ))}
                                    {[0, 1, 2, 3].map((num) => (
                                        <div
                                            key={`border${num}`}
                                            style={borderStyle(num)}
                                            className="bg-black"
                                        />
                                    ))}
                                </div> :
                                <div>
                                    <CanvasComponent component={component} width={component.uiData.width} height={component.uiData.height} />
                                </div>
                            }
                        </div>
                    )}
                </div>

                {/* Grid overlay (optional, for development) */}
                <div
                    className="absolute inset-0 pointer-events-none opacity-5"
                    style={{
                        backgroundImage: `
                            linear-gradient(to right, #000 1px, transparent 1px),
                            linear-gradient(to bottom, #000 1px, transparent 1px)
                        `,
                        backgroundSize: '20px 20px'
                    }}
                />
            </div>
        </div>
    );
}