import { MessageCircleIcon, XIcon, Maximize2Icon, Minimize2Icon, Trash2Icon } from "lucide-react";
import { useState, useRef, useCallback, useEffect } from "react";
import { cn } from "@/lib/utils";
import ChatbotPanel, { type ChatbotPanelHandle } from "./ChatbotPanel";

type Position = {
  x: number;
  y: number;
};

const STORAGE_KEY = "chatbot_widget_position";
// Increase threshold để tránh kéo nhầm khi chỉ muốn click
const DRAG_THRESHOLD = 10; // pixels - minimum movement to consider as drag

const getInitialPosition = (): Position => {
  if (typeof window === "undefined") return { x: 0, y: 0 };
  try {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved) {
      const parsed = JSON.parse(saved);
      // Validate position is within viewport
      const maxX = window.innerWidth - 60;
      const maxY = window.innerHeight - 60;
      return {
        x: Math.min(Math.max(0, parsed.x), maxX),
        y: Math.min(Math.max(0, parsed.y), maxY),
      };
    }
  } catch {
    // Ignore parse errors
  }
  // Default: bottom-right corner
  return {
    x: window.innerWidth - 76,
    y: window.innerHeight - 76,
  };
};

const ChatbotWidget = ({ className }: { className?: string }) => {
  const [isOpen, setIsOpen] = useState(false);
  const [isExpanded, setIsExpanded] = useState(false); // Phóng to
  const [position, setPosition] = useState<Position>(getInitialPosition);
  const [isDragging, setIsDragging] = useState(false);
  const hasDraggedRef = useRef(false);
  const dragRef = useRef<{ startX: number; startY: number; startPosX: number; startPosY: number } | null>(null);
  const animationFrameRef = useRef<number | null>(null);
  const chatbotPanelRef = useRef<ChatbotPanelHandle>(null);

  // Save position to localStorage when it changes
  useEffect(() => {
    if (!isDragging) {
      try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(position));
      } catch {
        // Ignore storage errors
      }
    }
  }, [position, isDragging]);

  // Handle window resize to keep button in viewport
  useEffect(() => {
    const handleResize = () => {
      setPosition((prev) => ({
        x: Math.min(prev.x, window.innerWidth - 60),
        y: Math.min(prev.y, window.innerHeight - 60),
      }));
    };
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  const handleMouseDown = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    hasDraggedRef.current = false;
    dragRef.current = {
      startX: e.clientX,
      startY: e.clientY,
      startPosX: position.x,
      startPosY: position.y,
    };
    setIsDragging(true);
  }, [position]);

  const handleMouseMove = useCallback((e: MouseEvent) => {
    if (!dragRef.current) return;

    const { startX, startY, startPosX, startPosY } = dragRef.current;
    const deltaX = e.clientX - startX;
    const deltaY = e.clientY - startY;

    if (Math.abs(deltaX) > DRAG_THRESHOLD || Math.abs(deltaY) > DRAG_THRESHOLD) {
      hasDraggedRef.current = true;
    }

    if (!hasDraggedRef.current) return;

    // Dùng requestAnimationFrame để kéo mượt hơn, tránh setState liên tục theo từng mousemove
    if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current);
    }
    animationFrameRef.current = requestAnimationFrame(() => {
      const newX = startPosX + deltaX;
      const newY = startPosY + deltaY;

      const maxX = window.innerWidth - 60;
      const maxY = window.innerHeight - 60;

      setPosition({
        x: Math.min(Math.max(0, newX), maxX),
        y: Math.min(Math.max(0, newY), maxY),
      });
    });
  }, []);

  const handleMouseUp = useCallback(() => {
    setIsDragging(false);
    dragRef.current = null;
  }, []);

  // Toggle via onClick — only if user didn't drag
  const handleClick = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
    if (!hasDraggedRef.current) {
      setIsOpen((prev) => !prev);
    }
  }, []);

  useEffect(() => {
    if (isDragging) {
      window.addEventListener("mousemove", handleMouseMove);
      window.addEventListener("mouseup", handleMouseUp);
      return () => {
        window.removeEventListener("mousemove", handleMouseMove);
        window.removeEventListener("mouseup", handleMouseUp);
      };
    }
  }, [isDragging, handleMouseMove, handleMouseUp]);

  // Touch support
  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    const touch = e.touches[0];
    hasDraggedRef.current = false;
    dragRef.current = {
      startX: touch.clientX,
      startY: touch.clientY,
      startPosX: position.x,
      startPosY: position.y,
    };
    setIsDragging(true);
  }, [position]);

  const handleTouchMove = useCallback((e: TouchEvent) => {
    if (!dragRef.current) return;

    const touch = e.touches[0];
    const { startX, startY, startPosX, startPosY } = dragRef.current;
    const deltaX = touch.clientX - startX;
    const deltaY = touch.clientY - startY;

    if (Math.abs(deltaX) > DRAG_THRESHOLD || Math.abs(deltaY) > DRAG_THRESHOLD) {
      hasDraggedRef.current = true;
    }

    if (!hasDraggedRef.current) return;

    if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current);
    }
    animationFrameRef.current = requestAnimationFrame(() => {
      const newX = startPosX + deltaX;
      const newY = startPosY + deltaY;

      const maxX = window.innerWidth - 60;
      const maxY = window.innerHeight - 60;

      setPosition({
        x: Math.min(Math.max(0, newX), maxX),
        y: Math.min(Math.max(0, newY), maxY),
      });
    });
  }, []);

  const handleTouchEnd = useCallback(() => {
    if (!hasDraggedRef.current) {
      setIsOpen((prev) => !prev);
    }
    setIsDragging(false);
    dragRef.current = null;
    if (animationFrameRef.current) {
      cancelAnimationFrame(animationFrameRef.current);
      animationFrameRef.current = null;
    }
  }, []);

  useEffect(() => {
    if (isDragging) {
      window.addEventListener("touchmove", handleTouchMove, { passive: true });
      window.addEventListener("touchend", handleTouchEnd);
      return () => {
        window.removeEventListener("touchmove", handleTouchMove);
        window.removeEventListener("touchend", handleTouchEnd);
      };
    }
  }, [isDragging, handleTouchMove, handleTouchEnd]);

  // Calculate panel position and size
  const getPanelStyle = (): React.CSSProperties => {
    // Kích thước panel dựa vào trạng thái expand
    const buttonSize = 56;
    // Normal: 400x520, Expanded: 600x800 (To và dài hơn)
    const panelWidth = isExpanded
      ? Math.min(600, window.innerWidth - 32)
      : Math.min(400, window.innerWidth - 32);
    const panelHeight = isExpanded
      ? Math.min(800, window.innerHeight - 80)
      : Math.min(520, window.innerHeight - 100);
    const gap = 16;

    const spaceOnRight = window.innerWidth - position.x - buttonSize;
    const spaceOnLeft = position.x;
    const spaceAbove = position.y;
    const spaceBelow = window.innerHeight - position.y - buttonSize;

    let left: number;
    let top: number;

    // Horizontal positioning
    if (spaceOnRight >= panelWidth + gap) {
      left = position.x + buttonSize + gap;
    } else if (spaceOnLeft >= panelWidth + gap) {
      left = position.x - panelWidth - gap;
    } else {
      left = Math.max(16, Math.min(position.x - panelWidth / 2 + buttonSize / 2, window.innerWidth - panelWidth - 16));
    }

    // Vertical positioning
    if (spaceBelow >= panelHeight + gap || spaceBelow > spaceAbove) {
      top = Math.min(position.y, window.innerHeight - panelHeight - 16);
    } else {
      top = Math.max(16, position.y + buttonSize - panelHeight);
    }

    return {
      position: "fixed",
      left: `${left}px`,
      top: `${top}px`,
      width: `${panelWidth}px`,
      height: `${panelHeight}px`,
      zIndex: 50,
      transition: "all 0.2s ease-in-out", // Smooth transition khi expand/collapse
    };
  };

  const handleClose = () => {
    setIsOpen(false);
    setIsExpanded(false);
  };

  return (
    <>
      {/* Chat Panel */}
      {isOpen && (
        <div
          style={getPanelStyle()}
          className={cn(
            "rounded-2xl shadow-2xl border border-border bg-background overflow-hidden",
            isExpanded && "rounded-xl",
            className
          )}
        >
          {/* Custom Header với nút Expand */}
          <div className="flex items-center justify-between gap-2 border-b border-border p-3 bg-muted/30">
            <div className="flex items-center gap-2">
              <span className="inline-flex size-2 rounded-full bg-emerald-500" />
              <div>
                <p className="text-sm font-semibold leading-none">CuCu Assistant</p>
                <p className="text-xs text-muted-foreground">Notes chat</p>
              </div>
            </div>
            <div className="flex items-center gap-1">
              {/* Nút Clear Messages */}
              <button
                type="button"
                className="rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
                onClick={() => chatbotPanelRef.current?.clearMessages()}
                aria-label="Clear messages"
                title="Xóa lịch sử chat"
              >
                <Trash2Icon className="size-4" />
              </button>
              {/* Nút Expand/Collapse */}
              <button
                type="button"
                className="rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                onClick={() => setIsExpanded((prev) => !prev)}
                aria-label={isExpanded ? "Collapse chat" : "Expand chat"}
                title={isExpanded ? "Thu nhỏ" : "Phóng to"}
              >
                {isExpanded ? (
                  <Minimize2Icon className="size-4" />
                ) : (
                  <Maximize2Icon className="size-4" />
                )}
              </button>
              {/* Nút Close */}
              <button
                type="button"
                className="rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                onClick={handleClose}
                aria-label="Close chat"
                title="Đóng"
              >
                <XIcon className="size-4" />
              </button>
            </div>
          </div>

          {/* Chat Content - không có header riêng nữa */}
          <div className="h-[calc(100%-52px)]">
            <ChatbotPanel ref={chatbotPanelRef} variant="widget" className="border-0 rounded-none" hideHeader />
          </div>
        </div>
      )}

      {/* Draggable Toggle Button */}
      <div
        style={{
          position: "fixed",
          left: `${position.x}px`,
          top: `${position.y}px`,
          zIndex: 52,
          touchAction: "none",
        }}
        className={cn(
          "size-14 rounded-full shadow-lg flex items-center justify-center cursor-pointer select-none transition-transform transition-shadow duration-150",
          isDragging && hasDraggedRef.current ? "cursor-grabbing shadow-xl" : "hover:shadow-xl hover:scale-105",
          isOpen
            ? "bg-destructive text-destructive-foreground"
            : "bg-primary text-primary-foreground",
        )}
        onMouseDown={handleMouseDown}
        onClick={handleClick}
        onTouchStart={handleTouchStart}
        role="button"
        tabIndex={0}
        aria-label={isOpen ? "Close chat" : "Open chat"}
      >
        {isOpen ? (
          <XIcon className="size-6" />
        ) : (
          <MessageCircleIcon className="size-6" />
        )}

        {/* Pulse animation when closed */}
        {!isOpen && !isDragging && (
          <span className="absolute inset-0 animate-ping rounded-full bg-primary opacity-20 pointer-events-none" />
        )}
      </div>
    </>
  );
};

export default ChatbotWidget;
