"use client";
import { Stage, Layer, Text } from "react-konva";
import { ToolbarMode, Color } from "@/lib/Enums";
import React, { useEffect } from "react";
import type Konva from "konva";
import ImageLayer from "./ImageLayer";
import LineLayer, { LineLayerHandle } from "./LineLayer";
import styles from "@/styles/DrawBoard/Board.module.css";



const Board = React.forwardRef<{ getCanvasImageBase64: () => string, clear: () => void } , { toolbarMode: ToolbarMode, imageUrl: string | null, color: Color }>(
  ({ toolbarMode, imageUrl, color }, ref) => {
    const textRef = React.useRef<Konva.Text>(null);
    const inputRef = React.useRef<HTMLInputElement | null>(null);
    const stageRef = React.useRef<Konva.Stage | null>(null);

    const lineLayerRef = React.useRef<LineLayerHandle | null>(null);

    React.useImperativeHandle(ref, () => ({
      getCanvasImageBase64() {
        try {
          const stage = stageRef.current?.getStage();
          if (!stage) return "";
          // Konva Stage has toDataURL which returns a data URL representing the canvas contents
          return stage.toDataURL();
        } catch (err) {
          console.error("getCanvasImageBase64 failed:", err);
          return "";
        }
      },
      clear() {
        // clear line layer and any written text; other clearing (like uploaded image) handled by parent DrawBoard
        try {
          lineLayerRef.current?.clear();
          setText("");
          if (textRef.current) {
            textRef.current.text("");
          }
        } catch (err) {
          console.error("Board.clear failed:", err);
        }
      }
    }), [stageRef]);

  const [cursor, setCursor] = React.useState<string | null>(null);
  const [text, setText] = React.useState("");
  const scrollPositionRef = React.useRef({ x: 0, y: 0 });
  const containerRef = React.useRef<HTMLDivElement | null>(null);
  const [inputPlacement, setInputPlacement] = React.useState({ top: 0, left: 0 });

  const handleStageMouseDown = React.useCallback(() => {
    lineLayerRef.current?.handleMouseDown();
  }, []);

  const handleStageMouseMove = React.useCallback(() => {
    lineLayerRef.current?.handleMouseMove();
  }, []);

  const handleStageMouseUp = React.useCallback(() => {
    lineLayerRef.current?.handleMouseUp();
  }, []);

  const updateInputPlacement = React.useCallback(() => {
    if (typeof window === "undefined") {
      return;
    }
    const container = containerRef.current;
    if (!container) {
      return;
    }
    const rect = container.getBoundingClientRect();
    const top = Math.min(window.innerHeight - 40, Math.max(0, rect.top + 20));
    const left = Math.min(window.innerWidth - 40, Math.max(0, rect.left + 20));
    setInputPlacement({ top, left });
    const input = inputRef.current;
    if (input) {
      input.style.top = `${top}px`;
      input.style.left = `${left}px`;
    }
  }, []);

  const restoreScrollPosition = React.useCallback(() => {
    if (typeof window === "undefined") {
      return;
    }
    const { x, y } = scrollPositionRef.current;
    window.scrollTo(x, y);
  }, []);

  const focusHiddenInput = React.useCallback(() => {
    if (typeof window !== "undefined") {
      scrollPositionRef.current = { x: window.scrollX, y: window.scrollY };
    }
    updateInputPlacement();
    requestAnimationFrame(() => {
      const input = inputRef.current;
      if (!input) {
        return;
      }
      try {
        input.focus({ preventScroll: true });
      } catch {
        input.focus();
      }
      const len = input.value.length;
      input.setSelectionRange?.(len, len);
      requestAnimationFrame(restoreScrollPosition);
    });
  }, [restoreScrollPosition, updateInputPlacement]);

  useEffect(() => {
    if (toolbarMode !== ToolbarMode.Write) {
      setCursor(null);
      if (inputRef.current) {
        inputRef.current.blur();
      }
      const stage = stageRef.current?.getStage();
      const container = stage?.container();
      if (container) {
        container.tabIndex = 0;
        try {
          container.focus({ preventScroll: true });
        } catch {
          container.focus();
        }
      }
      return;
    }

    const focusTimer = setTimeout(() => {
      focusHiddenInput();
    }, 0);

    const blinkTimer = setInterval(() => {
      setCursor(prev => (prev === null ? "|" : null));
    }, 500);

    return () => {
      clearTimeout(focusTimer);
      clearInterval(blinkTimer);
    };
  }, [focusHiddenInput, toolbarMode]);

  useEffect(() => {
    if (toolbarMode !== ToolbarMode.Write || typeof window === "undefined") {
      return;
    }
    const handleViewportChange = () => {
      updateInputPlacement();
    };
    window.addEventListener("resize", handleViewportChange);
    window.addEventListener("scroll", handleViewportChange, true);
    return () => {
      window.removeEventListener("resize", handleViewportChange);
      window.removeEventListener("scroll", handleViewportChange, true);
    };
  }, [toolbarMode, updateInputPlacement]);

  const handleKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
    if (toolbarMode !== ToolbarMode.Write || !textRef.current) {
      return;
    }

    if (e.key === "Backspace") {
      const updated = textRef.current.text().slice(0, -1);
      textRef.current.text(updated);
      setText(updated);
      restoreScrollPosition();
      return;
    }

    if (e.key && e.key.length === 1) {
      const char = e.shiftKey ? e.key.toUpperCase() : e.key;
      const updated = textRef.current.text() + char;
      textRef.current.text(updated);
      setText(updated);
      restoreScrollPosition();
    }
  };

  return (
    <div
      ref={containerRef}
      className={styles.container}
    >
      <input
        ref={inputRef}
        value={text}
        onChange={(ev: React.ChangeEvent<HTMLInputElement>) => {
          const value = ev.target.value;
          setText(value);
          if (textRef.current) {
            textRef.current.text(value);
          }
        }}
        style={{
          left: inputPlacement.left,
          top: inputPlacement.top,
        }}
        className={styles.hiddenTextInput}
        autoComplete="off"
        autoCapitalize="none"
        autoCorrect="off"
        spellCheck={false}
        aria-hidden="true"
      />
      <Stage
        width={800}
        height={600}
        ref={stageRef}
        tabIndex={0}
        onMouseDown={handleStageMouseDown}
        onMouseMove={handleStageMouseMove}
        onMouseUp={handleStageMouseUp}
        onTouchStart={handleStageMouseDown}
        onTouchMove={handleStageMouseMove}
        onTouchEnd={handleStageMouseUp}
        onKeyDown={handleKeyPress}
      >
        <ImageLayer imageUrl={imageUrl} />
        <LineLayer stageRef={stageRef} ref={lineLayerRef} toolbarMode={toolbarMode} color={color} />
        <Layer>
          <Text
            ref={textRef}
            x={50}
            y={50}
            draggable={toolbarMode === ToolbarMode.Write}
            text={`${text}${toolbarMode === ToolbarMode.Write ? cursor ?? "" : ""}`}
            fontSize={24}
            fill="black"
          />
        </Layer>
      </Stage>
    </div>
  );
  }
);

Board.displayName = "Board";

export default Board;