'use client';
import { useState, useEffect, useRef, useCallback } from 'react';
import {
  DndContext,
  useDraggable,
  useDroppable,
  DragOverlay,
  type DragEndEvent,
} from '@dnd-kit/core';
import { CSS } from '@dnd-kit/utilities';
import type { SignatureFieldData } from '@/lib/db/schema';

interface PageInfo {
  originalWidth: number;
  originalHeight: number;
  width: number;
  height: number;
  scale: number;
}

// Screen (DOM) → PDF user space. Y-axis flip required.
// DOM: Y=0 at top, increases downward
// PDF: Y=0 at bottom, increases upward
function screenToPdfCoords(
  screenX: number,
  screenY: number,
  containerRect: DOMRect,
  pageInfo: PageInfo,
) {
  // Use containerRect dimensions (current rendered size) not stale pageInfo
  const renderedW = containerRect.width;
  const renderedH = containerRect.height;
  const pdfX = (screenX / renderedW) * pageInfo.originalWidth;
  const pdfY = ((renderedH - screenY) / renderedH) * pageInfo.originalHeight;
  return { x: pdfX, y: pdfY };
}

// PDF user space → screen (for rendering stored fields)
function pdfToScreenCoords(
  pdfX: number,
  pdfY: number,
  containerRect: DOMRect,
  pageInfo: PageInfo,
) {
  const renderedW = containerRect.width;
  const renderedH = containerRect.height;
  const left = (pdfX / pageInfo.originalWidth) * renderedW;
  // top is measured from DOM top; pdfY is from PDF bottom — reverse flip
  const top = renderedH - (pdfY / pageInfo.originalHeight) * renderedH;
  return { left, top };
}

async function persistFields(docId: string, fields: SignatureFieldData[]) {
  try {
    await fetch(`/api/documents/${docId}/fields`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(fields),
    });
  } catch (e) {
    console.error('Failed to persist fields:', e);
  }
}

// Draggable token in the palette
function DraggableToken({ id }: { id: string }) {
  const { attributes, listeners, setNodeRef, transform, isDragging } = useDraggable({ id });
  const style: React.CSSProperties = {
    transform: CSS.Translate.toString(transform),
    opacity: isDragging ? 0.4 : 1,
    cursor: 'grab',
    padding: '6px 12px',
    border: '2px dashed #2563eb',
    borderRadius: '4px',
    background: 'rgba(37,99,235,0.08)',
    color: '#2563eb',
    fontSize: '13px',
    fontWeight: 600,
    userSelect: 'none',
    touchAction: 'none',
  };

  return (
    <div ref={setNodeRef} style={style} {...listeners} {...attributes}>
      + Signature Field
    </div>
  );
}

// Droppable zone wrapper for the PDF canvas
function DroppableZone({
  id,
  containerRef,
  children,
}: {
  id: string;
  containerRef: React.RefObject<HTMLDivElement | null>;
  children: React.ReactNode;
}) {
  const { setNodeRef } = useDroppable({ id });

  return (
    <div
      ref={(node) => {
        setNodeRef(node);
        if (containerRef && 'current' in containerRef) {
          (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node;
        }
      }}
      style={{ position: 'relative' }}
    >
      {children}
    </div>
  );
}

interface FieldPlacerProps {
  docId: string;
  pageInfo: PageInfo | null;
  currentPage: number;
  children: React.ReactNode;
}

export function FieldPlacer({ docId, pageInfo, currentPage, children }: FieldPlacerProps) {
  const [fields, setFields] = useState<SignatureFieldData[]>([]);
  const [isDraggingToken, setIsDraggingToken] = useState(false);
  const containerRef = useRef<HTMLDivElement | null>(null);

  // Load existing fields from server on mount
  useEffect(() => {
    async function loadFields() {
      try {
        const res = await fetch(`/api/documents/${docId}/fields`);
        if (res.ok) {
          const data = await res.json();
          setFields(data);
        }
      } catch (e) {
        console.error('Failed to load fields:', e);
      }
    }
    loadFields();
  }, [docId]);

  const handleDragEnd = useCallback(
    (event: DragEndEvent) => {
      setIsDraggingToken(false);

      const { active, over, activatorEvent, delta } = event;

      // Only process if dropped onto the PDF zone
      if (!over || over.id !== 'pdf-drop-zone') return;
      if (!pageInfo) return;

      const containerRect = containerRef.current?.getBoundingClientRect();
      if (!containerRect) return;

      // Compute the final screen position relative to the container
      // activatorEvent is the initial MouseEvent/TouchEvent at drag start
      // delta is the displacement from drag start to drop
      let clientX: number;
      let clientY: number;

      if (activatorEvent instanceof MouseEvent) {
        clientX = activatorEvent.clientX;
        clientY = activatorEvent.clientY;
      } else if (activatorEvent instanceof TouchEvent && activatorEvent.touches.length > 0) {
        clientX = activatorEvent.touches[0].clientX;
        clientY = activatorEvent.touches[0].clientY;
      } else {
        // Fallback: use center of container
        clientX = containerRect.left + containerRect.width / 2;
        clientY = containerRect.top + containerRect.height / 2;
      }

      // finalClient = activatorClient + delta (displacement during drag)
      const finalClientX = clientX + delta.x;
      const finalClientY = clientY + delta.y;

      // Convert to coordinates relative to the container
      const screenX = finalClientX - containerRect.left;
      const screenY = finalClientY - containerRect.top;

      // Clamp to container bounds
      const clampedX = Math.max(0, Math.min(screenX, containerRect.width));
      const clampedY = Math.max(0, Math.min(screenY, containerRect.height));

      // Convert screen coords to PDF user-space (Y-flip applied)
      const { x: pdfX, y: pdfY } = screenToPdfCoords(clampedX, clampedY, containerRect, pageInfo);

      const newField: SignatureFieldData = {
        id: crypto.randomUUID(),
        page: currentPage,
        x: pdfX,
        y: pdfY,
        width: 144, // 2 inches at 72 DPI
        height: 36, // 0.5 inches at 72 DPI
      };

      const next = [...fields, newField];
      setFields(next);
      persistFields(docId, next);
    },
    [fields, pageInfo, currentPage, docId],
  );

  // Render placed fields for the current page
  const renderFields = () => {
    if (!pageInfo) return null;
    const containerRect = containerRef.current?.getBoundingClientRect();
    if (!containerRect) return null;

    return fields
      .filter((f) => f.page === currentPage)
      .map((field) => {
        const { left, top } = pdfToScreenCoords(field.x, field.y, containerRect, pageInfo);
        const widthPx = (field.width / pageInfo.originalWidth) * containerRect.width;
        const heightPx = (field.height / pageInfo.originalHeight) * containerRect.height;

        return (
          <div
            key={field.id}
            style={{
              position: 'absolute',
              left,
              top: top - heightPx, // top is y of bottom-left corner; shift up by height
              width: widthPx,
              height: heightPx,
              border: '2px solid #2563eb',
              background: 'rgba(37,99,235,0.1)',
              borderRadius: '2px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              padding: '0 4px',
              fontSize: '10px',
              color: '#2563eb',
              pointerEvents: 'all',
              boxSizing: 'border-box',
            }}
          >
            <span>Signature</span>
            <button
              onClick={() => {
                const next = fields.filter((f) => f.id !== field.id);
                setFields(next);
                persistFields(docId, next);
              }}
              style={{
                cursor: 'pointer',
                background: 'none',
                border: 'none',
                color: '#ef4444',
                fontWeight: 'bold',
                padding: '0 2px',
                fontSize: '12px',
                lineHeight: 1,
              }}
              aria-label="Remove field"
            >
              ×
            </button>
          </div>
        );
      });
  };

  return (
    <DndContext
      onDragStart={() => setIsDraggingToken(true)}
      onDragEnd={handleDragEnd}
    >
      {/* Palette */}
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: '8px',
          marginBottom: '8px',
          padding: '8px 12px',
          background: '#f8fafc',
          border: '1px solid #e2e8f0',
          borderRadius: '6px',
        }}
      >
        <span style={{ fontSize: '12px', color: '#64748b', fontWeight: 500 }}>Field Palette:</span>
        <DraggableToken id="signature-token" />
      </div>

      {/* Droppable PDF zone with field overlays */}
      <DroppableZone id="pdf-drop-zone" containerRef={containerRef}>
        {children}
        {renderFields()}
      </DroppableZone>

      {/* Ghost overlay during drag */}
      <DragOverlay>
        {isDraggingToken ? (
          <div
            style={{
              width: 144,
              height: 36,
              border: '2px solid #2563eb',
              background: 'rgba(37,99,235,0.15)',
              borderRadius: '2px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              fontSize: '11px',
              color: '#2563eb',
              fontWeight: 600,
              pointerEvents: 'none',
            }}
          >
            Signature
          </div>
        ) : null}
      </DragOverlay>
    </DndContext>
  );
}
