/**
 * Annotation Viewer - Display-only viewer for image annotations
 *
 * Alpine.js component for viewing measurement markers on technical drawings.
 * Supports point markers and rectangle markers with highlighting.
 *
 * Annotation JSON Format:
 * {
 *   "markers": [
 *     {
 *       "id": 1,
 *       "marker_number": 1,
 *       "subtask_id": 42,
 *       "x": 150,
 *       "y": 200,
 *       "type": "point",
 *       "label": "D1"
 *     },
 *     {
 *       "id": 2,
 *       "marker_number": 2,
 *       "subtask_id": 43,
 *       "x": 300,
 *       "y": 150,
 *       "width": 100,
 *       "height": 50,
 *       "type": "rectangle",
 *       "label": "L1"
 *     }
 *   ],
 *   "imageWidth": 800,
 *   "imageHeight": 600
 * }
 *
 * Usage:
 * <div x-data="annotationViewer()"
 *      x-init="imageUrl = '/path/to/image.jpg'; annotations = {...}; init()">
 *   <canvas x-ref="annotationCanvas" @click="handleClick($event)"></canvas>
 * </div>
 */

function annotationViewer() {
  return {
    // Canvas elements
    canvas: null,
    ctx: null,

    // Data
    annotations: null,      // { markers: [...], imageWidth, imageHeight }
    imageUrl: null,         // URL dell'immagine da visualizzare
    activeMarker: null,     // marker_number del marker correntemente selezionato

    // State
    imageLoaded: false,
    scale: 1,               // scala di ridimensionamento immagine

    /**
     * Inizializzazione component
     */
    init() {
      this.canvas = this.$refs.annotationCanvas;
      if (!this.canvas) {
        console.error('AnnotationViewer: canvas ref not found');
        return;
      }

      this.ctx = this.canvas.getContext('2d');

      // Load image if URL is provided
      if (this.imageUrl) {
        this.loadImage();
      }

      // Responsive resize
      window.addEventListener('resize', () => {
        if (this.imageLoaded) {
          this.loadImage();
        }
      });
    },

    /**
     * Carica e renderizza l'immagine (o la prima pagina PDF) con scaling
     */
    loadImage() {
      var isPdf = this.imageUrl.toLowerCase().replace(/\?.*$/, '').endsWith('.pdf');

      if (isPdf && typeof pdfjsLib !== 'undefined') {
        this._loadPdf();
      } else {
        this._loadRasterImage();
      }
    },

    /**
     * Render first page of a PDF via PDF.js
     */
    _loadPdf() {
      const self = this;
      pdfjsLib.getDocument(this.imageUrl).promise.then(function (pdf) {
        return pdf.getPage(1);
      }).then(function (page) {
        const pdfScale = 2; // render at 2x for clarity
        const viewport = page.getViewport({ scale: pdfScale });

        const offCanvas = document.createElement('canvas');
        offCanvas.width = viewport.width;
        offCanvas.height = viewport.height;
        const offCtx = offCanvas.getContext('2d');

        page.render({ canvasContext: offCtx, viewport: viewport }).promise.then(function () {
          // Use rendered PDF page as if it were an image
          self._drawImageOnCanvas(offCanvas, viewport.width, viewport.height);
        });
      }).catch(function (err) {
        console.error('AnnotationViewer: failed to load PDF:', err);
      });
    },

    /**
     * Load a raster image (PNG, JPG, etc.)
     */
    _loadRasterImage() {
      const self = this;
      const img = new Image();

      img.onload = function () {
        self._drawImageOnCanvas(img, img.width, img.height);
      };

      img.onerror = function () {
        console.error('AnnotationViewer: failed to load image:', self.imageUrl);
      };

      img.src = this.imageUrl;
    },

    /**
     * Draw an image source (Image or Canvas) scaled to fit the container
     */
    _drawImageOnCanvas(source, srcWidth, srcHeight) {
      const container = this.canvas.parentElement;
      if (!container) {
        console.error('AnnotationViewer: parent container not found');
        return;
      }

      const containerWidth = container.clientWidth;
      const containerHeight = container.clientHeight || 500;

      this.scale = Math.min(
        containerWidth / srcWidth,
        containerHeight / srcHeight,
        1
      );

      this.canvas.width = srcWidth * this.scale;
      this.canvas.height = srcHeight * this.scale;

      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.drawImage(source, 0, 0, this.canvas.width, this.canvas.height);
      this.imageLoaded = true;

      this.drawAnnotations();
    },

    /**
     * Disegna tutti i markers sulle annotazioni
     */
    drawAnnotations() {
      if (!this.annotations) return;

      // Editor format (objects array from annotation-editor.js)
      if (this.annotations.objects) {
        var previewScale = this.scale;
        var imgScale = this.annotations.imageScale;
        // v2+: use imageScale for correct canvas→image→preview mapping
        // v1 fallback: annoScale = previewWidth / editorWidth
        var annoScale = imgScale
          ? (previewScale / imgScale)
          : (this.canvas.width / (this.annotations.width || this.canvas.width));
        _drawEditorAnnotations(this.ctx, this.annotations, annoScale);
        return;
      }

      // Legacy format (markers array)
      if (!this.annotations.markers) return;
      for (const marker of this.annotations.markers) {
        const isActive = this.activeMarker === marker.marker_number;
        this.drawMarker(marker, isActive);
      }
    },

    /**
     * Disegna un singolo marker
     * @param {Object} marker - marker data
     * @param {boolean} isActive - se il marker è attualmente selezionato
     */
    drawMarker(marker, isActive) {
      const x = marker.x * this.scale;
      const y = marker.y * this.scale;
      const color = isActive ? '#2563EB' : '#64748B'; // primary : steel
      const radius = isActive ? 16 : 12;

      if (marker.type === 'point') {
        // Cerchio numerato
        this.ctx.beginPath();
        this.ctx.arc(x, y, radius, 0, Math.PI * 2);
        this.ctx.fillStyle = color;
        this.ctx.globalAlpha = isActive ? 0.9 : 0.7;
        this.ctx.fill();
        this.ctx.globalAlpha = 1;

        // Bordo bianco
        this.ctx.strokeStyle = '#FFFFFF';
        this.ctx.lineWidth = 2;
        this.ctx.stroke();

        // Numero
        this.ctx.fillStyle = '#FFFFFF';
        this.ctx.font = `bold ${isActive ? 14 : 11}px Inter, sans-serif`;
        this.ctx.textAlign = 'center';
        this.ctx.textBaseline = 'middle';
        this.ctx.fillText(marker.marker_number.toString(), x, y);

      } else if (marker.type === 'rectangle') {
        const w = (marker.width || 50) * this.scale;
        const h = (marker.height || 30) * this.scale;

        // Rettangolo
        this.ctx.strokeStyle = color;
        this.ctx.lineWidth = isActive ? 3 : 2;
        this.ctx.setLineDash(isActive ? [] : [5, 3]);
        this.ctx.strokeRect(x, y, w, h);
        this.ctx.setLineDash([]);

        // Label badge
        const badgeWidth = 30;
        const badgeHeight = 18;
        this.ctx.fillStyle = color;
        this.ctx.globalAlpha = 0.8;
        this.ctx.fillRect(x, y - 20, badgeWidth, badgeHeight);
        this.ctx.globalAlpha = 1;

        // Numero nella badge
        this.ctx.fillStyle = '#FFFFFF';
        this.ctx.font = 'bold 11px Inter, sans-serif';
        this.ctx.textAlign = 'center';
        this.ctx.textBaseline = 'middle';
        this.ctx.fillText(marker.marker_number.toString(), x + badgeWidth / 2, y - 11);
      }
    },

    /**
     * Evidenzia un marker specifico
     * @param {number} markerNumber - numero del marker da evidenziare
     */
    setActiveMarker(markerNumber) {
      this.activeMarker = markerNumber;
      if (this.imageLoaded) {
        // Ridisegna tutto
        this.loadImage();
      }
    },

    /**
     * Gestisce click sul canvas per selezionare markers
     * @param {MouseEvent} e - evento click
     */
    handleClick(e) {
      if (!this.annotations || !this.annotations.markers) return;

      const rect = this.canvas.getBoundingClientRect();
      const clickX = e.clientX - rect.left;
      const clickY = e.clientY - rect.top;

      // Check click su ogni marker (reverse order per priorità visuale)
      for (let i = this.annotations.markers.length - 1; i >= 0; i--) {
        const marker = this.annotations.markers[i];
        const mx = marker.x * this.scale;
        const my = marker.y * this.scale;

        let hit = false;

        if (marker.type === 'point') {
          const dist = Math.sqrt((clickX - mx) ** 2 + (clickY - my) ** 2);
          hit = dist < 20;
        } else if (marker.type === 'rectangle') {
          const w = (marker.width || 50) * this.scale;
          const h = (marker.height || 30) * this.scale;
          hit = clickX >= mx && clickX <= mx + w &&
                clickY >= my && clickY <= my + h;
        }

        if (hit) {
          // Dispatch event per parent component
          this.$dispatch('marker-click', {
            marker_number: marker.marker_number,
            subtask_id: marker.subtask_id,
            marker: marker
          });

          // Auto-evidenzia
          this.setActiveMarker(marker.marker_number);
          return;
        }
      }
    },

    /**
     * Pulisce il canvas
     */
    clear() {
      if (this.ctx && this.canvas) {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        this.imageLoaded = false;
      }
    },

    /**
     * Aggiorna le annotazioni e ridisegna
     * @param {Object} newAnnotations - nuovo oggetto annotations
     */
    updateAnnotations(newAnnotations) {
      this.annotations = newAnnotations;
      if (this.imageLoaded) {
        this.loadImage();
      }
    }
  };
}

/**
 * Standalone function to render an image with annotations overlay.
 * For use in read-only previews (e.g. task cards) without Alpine.js.
 *
 * @param {HTMLCanvasElement} canvas - the canvas element to draw on
 * @param {string} imageUrl - URL of the image to load
 * @param {Object|string|null} annotationsJson - annotations data from the editor
 * @param {Object} [options] - optional settings
 * @param {number} [options.maxHeight=192] - max canvas height in pixels
 */
function renderAnnotationPreview(canvas, imageUrl, annotationsJson, options) {
  if (!canvas || !imageUrl) return;

  var opts = options || {};
  var maxHeight = opts.maxHeight || 192;
  var ctx = canvas.getContext('2d');

  var annotations = null;
  if (annotationsJson) {
    try {
      annotations = (typeof annotationsJson === 'string')
        ? JSON.parse(annotationsJson)
        : annotationsJson;
    } catch (e) {
      console.error('renderAnnotationPreview: invalid annotations JSON');
    }
  }

  var isPdf = imageUrl.toLowerCase().replace(/\?.*$/, '').endsWith('.pdf');

  if (isPdf && typeof pdfjsLib !== 'undefined') {
    pdfjsLib.getDocument(imageUrl).promise.then(function (pdf) {
      return pdf.getPage(1);
    }).then(function (page) {
      var viewport = page.getViewport({ scale: 2 });
      var offCanvas = document.createElement('canvas');
      offCanvas.width = viewport.width;
      offCanvas.height = viewport.height;
      var offCtx = offCanvas.getContext('2d');
      page.render({ canvasContext: offCtx, viewport: viewport }).promise.then(function () {
        _drawPreview(canvas, ctx, offCanvas, viewport.width, viewport.height, annotations, maxHeight);
      });
    }).catch(function (err) {
      console.error('renderAnnotationPreview: PDF load failed:', err);
    });
  } else {
    var img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = function () {
      _drawPreview(canvas, ctx, img, img.width, img.height, annotations, maxHeight);
    };
    img.onerror = function () {
      console.error('renderAnnotationPreview: image load failed:', imageUrl);
    };
    img.src = imageUrl;
  }
}

/**
 * Internal: draw image + annotations on canvas, scaled to fit.
 */
function _drawPreview(canvas, ctx, source, srcW, srcH, annotations, maxHeight) {
  var container = canvas.parentElement;
  var containerWidth = container ? container.clientWidth : 400;
  var scale = Math.min(containerWidth / srcW, maxHeight / srcH, 1);

  canvas.width = Math.round(srcW * scale);
  canvas.height = Math.round(srcH * scale);

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(source, 0, 0, canvas.width, canvas.height);

  if (annotations && annotations.objects) {
    var imgScale = annotations.imageScale;
    // v2+: use imageScale for correct canvas→image→preview mapping
    // v1 fallback: annoScale = previewWidth / editorWidth
    var annoScale = imgScale
      ? (scale / imgScale)
      : (canvas.width / (annotations.width || srcW));
    _drawEditorAnnotations(ctx, annotations, annoScale);
  } else if (annotations && annotations.markers) {
    _drawLegacyAnnotations(ctx, annotations, scale);
  }
}

/**
 * Draw annotations in the editor format (objects: marker/arrow/area).
 */
function _drawEditorAnnotations(ctx, data, scale) {
  var objects = data.objects || [];

  // Calculate annotation scale: annotations were placed on a canvas of
  // data.width x data.height, but we're drawing on a scaled canvas.
  // The image was scaled to fit data.width x data.height in the editor,
  // and now we scale again for preview. Use overall scale factor.
  var annoScale = scale;

  for (var i = 0; i < objects.length; i++) {
    var obj = objects[i];

    if (obj.type === 'marker') {
      _drawPreviewMarker(ctx, obj, annoScale);
    } else if (obj.type === 'arrow') {
      _drawPreviewArrow(ctx, obj, annoScale);
    } else if (obj.type === 'area') {
      _drawPreviewArea(ctx, obj, annoScale);
    } else if (obj.type === 'text') {
      _drawPreviewText(ctx, obj, annoScale);
    }
  }
}

function _drawPreviewMarker(ctx, obj, scale) {
  var x = obj.left * scale;
  var y = obj.top * scale;
  var color = obj.fill || '#2563EB';
  var radius = 14 * Math.min(scale, 1);

  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2);
  ctx.fillStyle = color;
  ctx.globalAlpha = 0.85;
  ctx.fill();
  ctx.globalAlpha = 1;

  ctx.strokeStyle = '#ffffff';
  ctx.lineWidth = 2;
  ctx.stroke();

  if (obj.markerNumber) {
    ctx.fillStyle = '#ffffff';
    ctx.font = 'bold ' + Math.max(10, Math.round(12 * Math.min(scale, 1))) + 'px Inter, sans-serif';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillText(obj.markerNumber.toString(), x, y);
  }
}

function _drawPreviewArrow(ctx, obj, scale) {
  var x1 = (obj.x1 != null ? obj.x1 : obj.left) * scale;
  var y1 = (obj.y1 != null ? obj.y1 : obj.top) * scale;
  var x2 = (obj.x2 != null ? obj.x2 : (obj.left + (obj.width || 100))) * scale;
  var y2 = (obj.y2 != null ? obj.y2 : (obj.top + (obj.height || 50))) * scale;
  var color = obj.stroke || '#DC2626';
  var lineWidth = obj.strokeWidth || 2;

  var lineDash = obj.lineDash || [];
  ctx.setLineDash(lineDash);

  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.strokeStyle = color;
  ctx.lineWidth = lineWidth;
  ctx.stroke();

  ctx.setLineDash([]);

  // Arrowhead
  var angle = Math.atan2(y2 - y1, x2 - x1);
  var headLen = 8 + lineWidth * 2;
  ctx.beginPath();
  ctx.moveTo(x2, y2);
  ctx.lineTo(x2 - headLen * Math.cos(angle - Math.PI / 6), y2 - headLen * Math.sin(angle - Math.PI / 6));
  ctx.lineTo(x2 - headLen * Math.cos(angle + Math.PI / 6), y2 - headLen * Math.sin(angle + Math.PI / 6));
  ctx.closePath();
  ctx.fillStyle = color;
  ctx.fill();
}

function _drawPreviewArea(ctx, obj, scale) {
  var x = obj.left * scale;
  var y = obj.top * scale;
  var w = (obj.width || 150) * (obj.scaleX || 1) * scale;
  var h = (obj.height || 100) * (obj.scaleY || 1) * scale;
  var color = obj.stroke || '#2563EB';
  var lineWidth = obj.strokeWidth || 2;

  var lineDash = obj.lineDash || [5, 3];
  ctx.strokeStyle = color;
  ctx.lineWidth = lineWidth;
  ctx.setLineDash(lineDash);
  ctx.strokeRect(x, y, w, h);
  ctx.setLineDash([]);
}

function _drawPreviewText(ctx, obj, scale) {
  var x = obj.left * scale;
  var y = obj.top * scale;
  var color = obj.textColor || '#000000';
  var fontSize = Math.max(10, Math.round((obj.fontSize || 18) * scale));

  ctx.fillStyle = color;
  ctx.font = 'bold ' + fontSize + 'px Inter, sans-serif';
  ctx.textAlign = 'left';
  ctx.textBaseline = 'top';

  var lines = (obj.textContent || '').split('\n');
  var lineHeight = fontSize * 1.2;
  for (var j = 0; j < lines.length; j++) {
    ctx.fillText(lines[j], x, y + j * lineHeight);
  }
}

/**
 * Draw annotations in the legacy format (markers: point/rectangle).
 */
function _drawLegacyAnnotations(ctx, data, scale) {
  var markers = data.markers || [];
  for (var i = 0; i < markers.length; i++) {
    var m = markers[i];
    if (m.type === 'point') {
      _drawPreviewMarker(ctx, { left: m.x, top: m.y, markerNumber: m.marker_number, fill: '#64748B' }, scale);
    } else if (m.type === 'rectangle') {
      _drawPreviewArea(ctx, { left: m.x, top: m.y, width: m.width, height: m.height, stroke: '#64748B' }, scale);
    }
  }
}
