<script setup>
import { ref, computed, nextTick, watch } from "vue";
import GoogleIcon from "@Shared/GoogleIcon.vue";
import SimpleTable from "./TableEditor.vue";

/** Propiedades */
const props = defineProps({
  element: {
    type: Object,
    required: true,
  },
  isSelected: {
    type: Boolean,
    default: false,
  },
});

/** Eventos */
const emit = defineEmits(["select", "delete", "update", "move"]);

/** Referencias */
const isEditing = ref(false);
const editValue = ref("");
const editInput = ref(null);
const editTextarea = ref(null);
const elementRef = ref(null);
const isDragging = ref(false);
const isResizing = ref(false);
const resizeDirection = ref(null); // 'corner', 'right', 'bottom'
const dragStart = ref({ x: 0, y: 0 });
const resizeStart = ref({ x: 0, y: 0, width: 0, height: 0 });
const fileInput = ref(null);

/** Referencias adicionales para auto-posicionamiento */
const controlsRef = ref(null);

/** Propiedades computadas */
const elementStyles = computed(() => {
  const baseStyles = {
    left: `${props.element.x}px`,
    top: `${props.element.y}px`,
    width: `${props.element.width || 200}px`,
    height: `${props.element.height || 40}px`,
    // Asegurar que la fuente se renderice con la misma métrica que el PDF
    fontFamily: "Helvetica, Arial, sans-serif",
    lineHeight: "1.2",
    letterSpacing: "normal",
  };

  // Aplicar estilos de formato para elementos de texto
  if (props.element.type === "text" && props.element.formatting) {
    const formatting = props.element.formatting;

    // Aplicar tamaño de fuente con factor de corrección
    if (formatting.fontSize) {
      baseStyles.fontSize = `${formatting.fontSize}px`;
    }

    if (formatting.color) {
      baseStyles.color = formatting.color;
    }

    // Alineación del contenedor en la página
    if (formatting.containerAlign) {
      const pageWidth = 794; // A4 width por defecto
      const elementWidth = props.element.width || 200;

      switch (formatting.containerAlign) {
        case "center":
          baseStyles.left = `${(pageWidth - elementWidth) / 2}px`;
          break;
        case "right":
          baseStyles.left = `${pageWidth - elementWidth - 50}px`; // 50px margen
          break;
        case "left":
        default:
          baseStyles.left = `${props.element.x}px`;
      }
    }
  }

  return baseStyles;
});

// Propiedades computadas para clases CSS dinámicas
const textContainerClasses = computed(() => {
  if (props.element.type !== "text") return {};

  const formatting = props.element.formatting || {};

  return {
    "font-bold": formatting.bold,
    italic: formatting.italic,
    underline: formatting.underline,
    "text-left": !formatting.textAlign || formatting.textAlign === "left",
    "text-center": formatting.textAlign === "center",
    "text-right": formatting.textAlign === "right",
    "justify-start": !formatting.textAlign || formatting.textAlign === "left",
    "justify-center": formatting.textAlign === "center",
    "justify-end": formatting.textAlign === "right",
  };
});

const inputClasses = computed(() => {
  if (props.element.type !== "text") return {};

  const formatting = props.element.formatting || {};

  return {
    "font-bold": formatting.bold,
    italic: formatting.italic,
    underline: formatting.underline,
    "text-left": !formatting.textAlign || formatting.textAlign === "left",
    "text-center": formatting.textAlign === "center",
    "text-right": formatting.textAlign === "right",
  };
});

const inputStyles = computed(() => {
  if (props.element.type !== "text") return {};

  const formatting = props.element.formatting || {};
  const styles = {};

  if (formatting.fontSize) {
    styles.fontSize = `${formatting.fontSize}px`;
  }

  if (formatting.color) {
    styles.color = formatting.color;
  }

  return styles;
});

/** Propiedades computadas para posicionamiento dinámico */
const controlsPosition = computed(() => {
  if (!props.isSelected || isEditing.value) return {};

  // Si el elemento está muy cerca del borde superior
  const isNearTop = props.element.y < 50;

  return {
    styles: isNearTop
      ? {
          top: "100%",
          marginTop: "8px",
        }
      : {
          bottom: "100%",
          marginBottom: "8px",
        },
  };
});

const tooltipPosition = computed(() => {
  if (!props.isSelected || isEditing.value) return {};

  const isNearTop = props.element.y < 50;
  const hasControlButtons = props.element.type === "image";

  const rightOffset = hasControlButtons ? "60px" : "0px";

  return {
    position: isNearTop ? "bottom" : "top",
    styles: isNearTop
      ? {
          top: "100%",
          marginTop: "8px",
          right: rightOffset,
        }
      : {
          bottom: "100%",
          marginBottom: "8px",
          right: rightOffset,
        },
  };
});

const handleImageDoubleClick = (event) => {
  event.stopPropagation();
  if (props.element.type === "image") {
    fileInput.value?.click();
  }
};


/** Métodos */
const handleSelect = (event) => {
  event.stopPropagation();
  emit("select", props.element.id);
};

const handleDelete = () => {
  emit("delete", props.element.id);
};

const startEditing = () => {
  if (props.element.type === "table" && props.element.content) {
    // Deep copy para evitar mutaciones directas
    editValue.value = JSON.parse(JSON.stringify(props.element.content));
  } else if (props.element.type === "code") {
    editValue.value = props.element.content || 'console.log("Hola mundo");';
  } else {
    editValue.value = props.element.content || getDefaultEditValue();
  }
  isEditing.value = true;

  nextTick(() => {
    if (editTextarea.value) editTextarea.value.focus();
    if (editInput.value) editInput.value.focus();
  });
};

const finishEditing = () => {
  if (isEditing.value) {
    isEditing.value = false;

    // Para tablas, los datos ya se actualizaron en tiempo real
    // Solo necesitamos confirmar que se guardaron
    if (props.element.type === "table" && editValue.value) {
      emit("update", {
        id: props.element.id,
        content: editValue.value,
      });
    } else if (props.element.type !== "table") {
      emit("update", {
        id: props.element.id,
        content: editValue.value,
      });
    }
  }
};

const handleKeydown = (event) => {
  if (props.element.type === "text") {
    // Permitir Enter para salto de línea
    if (event.key === "Enter") {
      if (event.shiftKey || event.ctrlKey) {
        event.preventDefault();
        finishEditing();
      }
      // Si es solo Enter, permitir el salto de línea normal
    } else if (event.key === "Escape") {
      isEditing.value = false;
      editValue.value = props.element.content || "Nuevo texto";
    } else if (event.key === "Tab") {
      event.preventDefault();
      const start = editTextarea.value.selectionStart;
      const end = editTextarea.value.selectionEnd;
      const spaces = "    ";
      editValue.value =
        editValue.value.substring(0, start) +
        spaces +
        editValue.value.substring(end);

      // Restaurar posición del cursor
      nextTick(() => {
        editTextarea.value.selectionStart = editTextarea.value.selectionEnd =
          start + spaces.length;
      });
    }
  } else if (props.element.type === "code") {
    if (event.key === "Escape") {
      isEditing.value = false;
      editValue.value = props.element.content || 'console.log("Hola mundo");';
    }
    // Para código, permitimos Enter normal y usamos Ctrl+Enter para terminar
    if (event.key === "Enter" && event.ctrlKey) {
      event.preventDefault();
      finishEditing();
    }
  } else if (props.element.type === "table") {
    if (event.key === "Escape") {
      isEditing.value = false;
      // Restaurar el contenido original de la tabla
      editValue.value = props.element.content
        ? JSON.parse(JSON.stringify(props.element.content))
        : getDefaultEditValue();
    }
  }
};

// Función para ajustar altura automáticamente del textarea
const adjustTextareaHeight = () => {
  if (editTextarea.value) {
    editTextarea.value.style.height = "auto";
    editTextarea.value.style.height = editTextarea.value.scrollHeight + "px";

    // Actualizar altura del elemento si es necesario
    const newHeight = Math.max(40, editTextarea.value.scrollHeight + 20);
    if (newHeight !== props.element.height) {
      emit("update", {
        id: props.element.id,
        height: newHeight,
      });
    }
  }
};

// Función para contar líneas y ajustar altura
const updateTextHeight = () => {
  if (props.element.type === "text" && editValue.value) {
    const lines = editValue.value.split("\n");
    const fontSize = props.element.formatting?.fontSize || 14;
    const lineHeight = fontSize * 1.4; // Factor de altura de línea
    const padding = 20; // Padding vertical
    const newHeight = Math.max(40, lines.length * lineHeight + padding);

    if (newHeight !== props.element.height) {
      emit("update", {
        id: props.element.id,
        height: newHeight,
      });
    }
  }
};

// Manejo de archivo de imagen
const handleFileSelect = (event) => {
  const file = event.target.files[0];
  if (file && file.type.startsWith("image/")) {
    const reader = new FileReader();
    reader.onload = (e) => {
      emit("update", {
        id: props.element.id,
        content: e.target.result,
        fileName: file.name,
      });
    };
    reader.readAsDataURL(file);
  }
  // Limpiar el input
  event.target.value = "";
};

// Funcionalidad de arrastre
const handleMouseDown = (event) => {
  if (isEditing.value || isResizing.value) return;

  isDragging.value = true;
  dragStart.value = {
    x: event.clientX - props.element.x,
    y: event.clientY - props.element.y,
  };

  document.addEventListener("mousemove", handleMouseMove);
  document.addEventListener("mouseup", handleMouseUp);

  event.preventDefault();
};

const handleMouseMove = (event) => {
  if (isDragging.value && !isResizing.value) {
    const newX = event.clientX - dragStart.value.x;
    const newY = event.clientY - dragStart.value.y;

    emit("move", {
      id: props.element.id,
      x: Math.max(0, newX),
      y: Math.max(0, newY),
    });
  } else if (isResizing.value && !isDragging.value) {
    handleResizeMove(event);
  }
};

const handleMouseUp = () => {
  isDragging.value = false;
  isResizing.value = false;
  resizeDirection.value = null;
  document.removeEventListener("mousemove", handleMouseMove);
  document.removeEventListener("mouseup", handleMouseUp);
};

// Funcionalidad de redimensionamiento por esquina
const startResize = (event) => {
  event.stopPropagation();
  event.preventDefault();

  isResizing.value = true;
  resizeDirection.value = "corner";
  resizeStart.value = {
    x: event.clientX,
    y: event.clientY,
    width: props.element.width || 200,
    height: props.element.height || 40,
  };

  document.addEventListener("mousemove", handleMouseMove);
  document.addEventListener("mouseup", handleMouseUp);
};

// Funcionalidad de redimensionamiento por bordes
const startResizeEdge = (event, direction) => {
  event.stopPropagation();
  event.preventDefault();

  isResizing.value = true;
  resizeDirection.value = direction;
  resizeStart.value = {
    x: event.clientX,
    y: event.clientY,
    width: props.element.width || 200,
    height: props.element.height || 40,
  };

  document.addEventListener("mousemove", handleMouseMove);
  document.addEventListener("mouseup", handleMouseUp);
};

const handleResizeMove = (event) => {
  if (!isResizing.value) return;

  const deltaX = event.clientX - resizeStart.value.x;
  const deltaY = event.clientY - resizeStart.value.y;

  let newWidth = resizeStart.value.width;
  let newHeight = resizeStart.value.height;

  // Calcular nuevas dimensiones según la dirección
  if (resizeDirection.value === "corner") {
    newWidth = Math.max(
      getMinWidth(),
      Math.min(getMaxWidth(), resizeStart.value.width + deltaX)
    );
    newHeight = Math.max(
      getMinHeight(),
      Math.min(getMaxHeight(), resizeStart.value.height + deltaY)
    );
  } else if (resizeDirection.value === "right") {
    newWidth = Math.max(
      getMinWidth(),
      Math.min(getMaxWidth(), resizeStart.value.width + deltaX)
    );
  } else if (resizeDirection.value === "bottom") {
    newHeight = Math.max(
      getMinHeight(),
      Math.min(getMaxHeight(), resizeStart.value.height + deltaY)
    );
  }

  emit("update", {
    id: props.element.id,
    width: newWidth,
    height: newHeight,
  });
};

// Obtener tamaños mínimos según el tipo de elemento
const getMinWidth = () => {
  switch (props.element.type) {
    case "text":
      return 100;
    case "image":
      return 100;
    case "table":
      return 200;
    default:
      return 100;
  }
};

const getMinHeight = () => {
  switch (props.element.type) {
    case "text":
      return 30;
    case "image":
      return 80;
    case "table":
      return 80;
    default:
      return 30;
  }
};

// Obtener tamaños máximos según el tipo de elemento
const getMaxWidth = () => {
  return 800; // Máximo general
};

const getMaxHeight = () => {
  return 600; // Máximo general
};

/** Watchers */
watch(
  () => props.isSelected,
  (selected) => {
    if (selected && isEditing.value) {
      nextTick(() => {
        if (props.element.type === "text" && editInput.value) {
          editInput.value.focus();
          editInput.value.select();
        } else if (props.element.type === "code" && editTextarea.value) {
          editTextarea.value.focus();
          editTextarea.value.select();
        }
      });
    }
  }
);

// Watch para ajustar altura cuando cambie el texto
watch(editValue, () => {
  if (isEditing.value && props.element.type === "text") {
    nextTick(() => {
      adjustTextareaHeight();
      updateTextHeight();
    });
  }
});

const getDefaultEditValue = () => {
  switch (props.element.type) {
    case "text":
      return "Nuevo texto";
    case "table":
      return {
        data: [
          ["Columna 1", "Columna 2", "Columna 3"],
          ["Fila 1", "Fila 1", "Fila 1"],
          ["Fila 2", "Fila 2", "Fila 2"],
        ],
        rows: 3,
        cols: 3,
      };
    default:
      return "";
  }
};

// Nuevas variables reactivas para selección de texto
const selectedTextRange = ref(null);
const isSelectingText = ref(false);

// Método para capturar selección de texto
const handleTextSelection = () => {
    if (props.element.type === 'text' && !isEditing.value) {
        const selection = window.getSelection();
        if (selection.rangeCount > 0 && selection.toString().length > 0) {
            const range = selection.getRangeAt(0);
            selectedTextRange.value = {
                start: range.startOffset,
                end: range.endOffset,
                text: selection.toString()
            };
            isSelectingText.value = true;
            
            // Emitir evento para activar TextFormatter
            emit('text-selected', {
                id: props.element.id,
                selection: selectedTextRange.value,
                element: props.element
            });
        } else {
            selectedTextRange.value = null;
            isSelectingText.value = false;
        }
    }
};

// Aplicar formato solo a texto seleccionado
const applyFormatToSelection = (formatting) => {
    if (selectedTextRange.value && props.element.type === 'text') {
        // Crear un nuevo contenido con formato aplicado solo a la selección
        const content = props.element.content || '';
        const beforeSelection = content.substring(0, selectedTextRange.value.start);
        const selectedText = content.substring(selectedTextRange.value.start, selectedTextRange.value.end);
        const afterSelection = content.substring(selectedTextRange.value.end);
        
        // Aquí podrías implementar markdown o HTML para mantener formato
        // Por ahora aplicamos formato a todo el elemento como antes
        emit('update', {
            id: props.element.id,
            formatting: formatting
        });
    }
};
</script>

<template>
  <div
    ref="elementRef"
    :style="elementStyles"
    @click="handleSelect"
    @dblclick="startEditing"
    @mousedown="handleMouseDown"
    class="absolute group select-none"
    :class="{
      'ring-2 ring-blue-500 ring-opacity-50': isSelected,
      'cursor-move': !isEditing && !isResizing,
      'cursor-text': isEditing && element.type === 'text',
      'cursor-se-resize': isResizing && resizeDirection === 'corner',
      'cursor-e-resize': isResizing && resizeDirection === 'right',
      'cursor-s-resize': isResizing && resizeDirection === 'bottom',
      'z-50': isSelected,
      'z-10': !isSelected,
    }"
  >
    <!-- Input oculto para selección de archivos -->
    <input
      ref="fileInput"
      type="file"
      accept="image/*"
      @change="handleFileSelect"
      class="hidden"
    />

    <!-- Elemento de Texto MEJORADO -->
    <div
      v-if="element.type === 'text'"
      class="w-full h-full flex items-start px-3 py-2 bg-white rounded border border-gray-300 shadow-sm"
      :class="textContainerClasses"
      :style="{
        fontSize: element.formatting?.fontSize ? `${element.formatting.fontSize}px` : '14px',
        color: element.formatting?.color || '#374151',
        fontFamily: 'Helvetica, Arial, sans-serif',
        lineHeight: '1.4',
        letterSpacing: 'normal',
        textRendering: 'geometricPrecision',
        fontSmooth: 'always',
        WebkitFontSmoothing: 'antialiased',
      }"
    >
      <!-- Textarea para edición -->
      <textarea
        v-if="isEditing"
        ref="editTextarea"
        v-model="editValue"
        @blur="finishEditing"
        @keydown="handleKeydown"
        @input="adjustTextareaHeight"
        class="w-full bg-transparent outline-none resize-none cursor-text"
        :class="inputClasses"
        :style="{
          ...inputStyles,
          fontFamily: 'Helvetica, Arial, sans-serif',
          lineHeight: '1.4',
          letterSpacing: 'normal',
          minHeight: '20px',
          height: 'auto',
        }"
        @mousedown.stop
        placeholder="Escribe tu texto aquí... (Shift+Enter o Ctrl+Enter para terminar)"
      ></textarea>

      <!-- Vista de solo lectura con selección de texto -->
      <div
        v-else
        class="w-full h-full overflow-hidden cursor-text"
        :class="textContainerClasses"
        :style="{
          fontSize: element.formatting?.fontSize ? `${element.formatting.fontSize}px` : '14px',
          color: element.formatting?.color || '#374151',
          fontFamily: 'Helvetica, Arial, sans-serif',
          lineHeight: '1.4',
          letterSpacing: 'normal',
          whiteSpace: 'pre-wrap',
          wordWrap: 'break-word',
        }"
        @mouseup="handleTextSelection"
        @selectstart="() => isSelectingText = true"
      >
        {{ element.content || "Nuevo texto" }}
      </div>
    </div>

    <!-- Elemento de Imagen -->
    <div
      v-else-if="element.type === 'image'"
      class="w-full h-full flex items-center justify-center bg-gray-100 rounded border border-gray-300 dark:bg-primary/10 dark:border-primary/20 overflow-hidden"
      @dblclick.stop="handleImageDoubleClick"
    >
      <!-- Si hay imagen cargada -->
      <img
        v-if="element.content && element.content.startsWith('data:image')"
        :src="element.content"
        :alt="element.fileName || 'Imagen'"
        class="w-full h-full object-cover pointer-events-none"
      />
      <!-- Placeholder para imagen -->
      <div
        v-else
        class="flex flex-col items-center justify-center text-gray-400 dark:text-primary-dt/50 p-4"
      >
        <GoogleIcon name="image" class="text-2xl mb-1" />
        <span class="text-xs text-center"
          >Haz doble clic para cargar imagen</span
        >
      </div>
    </div>

    <!-- Elemento de Tabla SIMPLE -->
    <SimpleTable
      v-if="element.type === 'table'"
      :element="element"
      :is-editing="isEditing"
      @update="(data) => emit('update', data)"
      @finish-editing="() => { isEditing = false; }"
    />

    <!-- Controles del elemento -->
    <div
      v-if="isSelected && !isEditing"
      ref="controlsRef"
      class="absolute right-0 flex gap-1 opacity-100 transition-opacity z-[60]"
      :style="controlsPosition.styles"
    >
      <!-- Flecha indicadora cuando está abajo -->
      <div
        v-if="controlsPosition.position === 'bottom'"
        class="absolute -top-2 right-2 w-0 h-0 border-l-4 border-r-4 border-b-4 border-l-transparent border-r-transparent border-b-gray-800"
      ></div>

      <!-- Botón para cargar imagen -->
      <button
        v-if="element.type === 'image'"
        @click.stop="() => fileInput.click()"
        class="w-7 h-7 bg-blue-500 hover:bg-blue-600 text-white rounded-md text-xs flex items-center justify-center transition-colors shadow-md"
        title="Cargar imagen"
      >
        <GoogleIcon name="upload" class="text-sm" />
      </button>

      <!-- Botón eliminar -->
      <button
        @click.stop="handleDelete"
        class="w-7 h-7 bg-red-500 hover:bg-red-600 text-white rounded-md text-xs flex items-center justify-center transition-colors shadow-md"
        title="Eliminar elemento"
      >
        <GoogleIcon name="close" class="text-sm" />
      </button>

      <!-- Flecha indicadora cuando está arriba -->
      <div
        v-if="controlsPosition.position === 'top'"
        class="absolute -bottom-2 right-2 w-0 h-0 border-l-4 border-r-4 border-t-4 border-l-transparent border-r-transparent border-t-gray-800"
      ></div>
    </div>

    <!-- Controles de redimensionamiento  -->
    <div
      v-if="isSelected && !isEditing"
      class="absolute inset-0 pointer-events-none z-[55]"
    >
      <!-- Esquina inferior derecha -->
      <div
        @mousedown.stop="startResize"
        class="absolute -bottom-2 -right-2 w-5 h-5 bg-blue-500 border-2 border-white cursor-se-resize pointer-events-auto rounded-md shadow-lg hover:bg-blue-600 hover:scale-110 transition-all"
        title="Redimensionar"
      >
        <div class="absolute inset-1 border border-white/40 rounded-sm"></div>
      </div>

      <!-- Lado derecho -->
      <div
        @mousedown.stop="(event) => startResizeEdge(event, 'right')"
        class="absolute top-3 bottom-3 -right-1 w-2 bg-blue-500/80 cursor-e-resize pointer-events-auto rounded-full shadow-sm hover:bg-blue-600 hover:w-3 transition-all"
        title="Redimensionar ancho"
      >
        <div
          class="absolute top-1/2 left-1/2 w-0.5 h-6 bg-white/60 -translate-x-1/2 -translate-y-1/2 rounded-full"
        ></div>
      </div>

      <!-- Lado inferior -->
      <div
        @mousedown.stop="(event) => startResizeEdge(event, 'bottom')"
        class="absolute -bottom-1 left-3 right-3 h-2 bg-blue-500/80 cursor-s-resize pointer-events-auto rounded-full shadow-sm hover:bg-blue-600 hover:h-3 transition-all"
        title="Redimensionar alto"
      >
        <div
          class="absolute top-1/2 left-1/2 w-6 h-0.5 bg-white/60 -translate-x-1/2 -translate-y-1/2 rounded-full"
        ></div>
      </div>
    </div>

    <!-- Tooltips adaptativos -->
    <div
      v-if="
        isSelected && !element.content && element.type === 'text' && !isResizing
      "
      class="absolute right-0 bg-gray-900 text-white text-xs px-2 py-1 rounded whitespace-nowrap z-[60]"
      :style="{
        ...tooltipPosition.styles,
        [tooltipPosition.position === 'top' ? 'bottom' : 'top']: '100%',
        [tooltipPosition.position === 'top' ? 'marginBottom' : 'marginTop']:
          '8px',
      }"
    >
      Doble clic para escribir párrafos
    </div>

    <!-- Indicador de arrastre -->
    <div
      v-if="isDragging"
      class="absolute inset-0 bg-blue-500 opacity-20 rounded pointer-events-none"
    ></div>

    <!-- Indicador de redimensionamiento -->
    <div
      v-if="isResizing"
      class="absolute inset-0 bg-green-500 opacity-20 rounded pointer-events-none"
    ></div>
  </div>
</template>

<style scoped>
.select-none {
    user-select: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
}

/* Estilos para textarea */
textarea {
    overflow: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

textarea::-webkit-scrollbar {
    display: none;
}
</style>