(() => {
  'use strict';

  const root = document.querySelector('[data-doctor-photo-crop]');
  if (!root) return;

  const input = root.querySelector('[data-photo-file]');
  const dialog = document.getElementById('doctor-photo-crop-dialog');
  const canvas = dialog?.querySelector('[data-photo-editor-canvas]');
  const context = canvas?.getContext('2d');
  const zoom = dialog?.querySelector('[data-photo-zoom]');
  const horizontal = dialog?.querySelector('[data-photo-horizontal]');
  const vertical = dialog?.querySelector('[data-photo-vertical]');
  const status = dialog?.querySelector('[data-photo-status]');
  const frame = dialog?.querySelector('[data-photo-editor-frame]');
  const apply = dialog?.querySelector('[data-photo-apply]');
  const cancelButtons = Array.from(dialog?.querySelectorAll('[data-photo-cancel]') || []);
  const presetButtons = Array.from(dialog?.querySelectorAll('[data-photo-preset]') || []);
  const hiddenSquare = root.querySelector('input[name="photo_square_data"]');
  const hiddenPortrait = root.querySelector('input[name="photo_portrait_data"]');
  const hiddenThumbnail = root.querySelector('input[name="photo_thumbnail_data"]');
  const squarePreview = root.querySelector('[data-photo-preview="square"]');
  const portraitPreview = root.querySelector('[data-photo-preview="portrait"]');
  const cropState = root.querySelector('[data-photo-crop-state]');

  if (!input || !dialog || !canvas || !context || !zoom || !horizontal || !vertical || !apply) return;

  const presets = {
    square: { width: 600, height: 600, label: '2×2 photo', zoom: 1, x: 0, y: -8 },
    portrait: { width: 800, height: 1000, label: 'half-body portrait', zoom: 1, x: 0, y: -4 },
  };

  let image = null;
  let activePreset = 'square';
  let objectUrl = '';

  const setStatus = (message, kind = '') => {
    if (!status) return;
    status.textContent = message;
    status.dataset.kind = kind;
  };

  const state = () => presets[activePreset];

  const syncControls = () => {
    const current = state();
    zoom.value = String(current.zoom);
    horizontal.value = String(current.x);
    vertical.value = String(current.y);
    presetButtons.forEach((button) => {
      const selected = button.dataset.photoPreset === activePreset;
      button.classList.toggle('active', selected);
      button.setAttribute('aria-pressed', selected ? 'true' : 'false');
    });
    frame?.classList.toggle('is-square', activePreset === 'square');
    frame?.classList.toggle('is-portrait', activePreset === 'portrait');
  };

  const drawCrop = (targetCanvas, presetName, output = false) => {
    if (!image) return;
    const preset = presets[presetName];
    targetCanvas.width = preset.width;
    targetCanvas.height = preset.height;
    const targetContext = targetCanvas.getContext('2d');
    if (!targetContext) return;

    targetContext.clearRect(0, 0, preset.width, preset.height);
    targetContext.fillStyle = '#ffffff';
    targetContext.fillRect(0, 0, preset.width, preset.height);

    const baseScale = Math.max(preset.width / image.naturalWidth, preset.height / image.naturalHeight);
    const scale = baseScale * Number(preset.zoom || 1);
    const drawWidth = image.naturalWidth * scale;
    const drawHeight = image.naturalHeight * scale;
    const overflowX = Math.max(0, (drawWidth - preset.width) / 2);
    const overflowY = Math.max(0, (drawHeight - preset.height) / 2);
    const offsetX = (Number(preset.x || 0) / 100) * overflowX;
    const offsetY = (Number(preset.y || 0) / 100) * overflowY;
    const drawX = (preset.width - drawWidth) / 2 + offsetX;
    const drawY = (preset.height - drawHeight) / 2 + offsetY;

    targetContext.imageSmoothingEnabled = true;
    targetContext.imageSmoothingQuality = 'high';
    targetContext.drawImage(image, drawX, drawY, drawWidth, drawHeight);

    if (!output && targetCanvas === canvas) {
      targetContext.save();
      targetContext.strokeStyle = 'rgba(255,255,255,.78)';
      targetContext.lineWidth = Math.max(2, Math.round(preset.width / 280));
      targetContext.setLineDash([12, 10]);
      targetContext.beginPath();
      targetContext.moveTo(preset.width / 3, 0);
      targetContext.lineTo(preset.width / 3, preset.height);
      targetContext.moveTo((preset.width * 2) / 3, 0);
      targetContext.lineTo((preset.width * 2) / 3, preset.height);
      targetContext.moveTo(0, preset.height / 3);
      targetContext.lineTo(preset.width, preset.height / 3);
      targetContext.moveTo(0, (preset.height * 2) / 3);
      targetContext.lineTo(preset.width, (preset.height * 2) / 3);
      targetContext.stroke();
      targetContext.restore();
    }
  };

  const render = () => {
    if (!image) return;
    drawCrop(canvas, activePreset, false);
    setStatus(`Adjusting ${state().label}. Keep the face centered and leave comfortable space above the head.`, 'ready');
  };

  const loadFile = (file) => {
    if (!file) return;
    if (!['image/jpeg', 'image/png', 'image/webp'].includes(file.type)) {
      input.value = '';
      setStatus('Use a JPG, PNG, or WebP photograph.', 'error');
      return;
    }
    if (file.size > 5 * 1024 * 1024) {
      input.value = '';
      setStatus('The selected photograph exceeds 5 MB.', 'error');
      return;
    }
    if (objectUrl) URL.revokeObjectURL(objectUrl);
    objectUrl = URL.createObjectURL(file);
    const nextImage = new Image();
    nextImage.onload = () => {
      if (nextImage.naturalWidth < 800 || nextImage.naturalHeight < 800) {
        input.value = '';
        URL.revokeObjectURL(objectUrl);
        objectUrl = '';
        setStatus('Use a photograph at least 800 × 800 pixels.', 'error');
        return;
      }
      image = nextImage;
      presets.square.zoom = 1;
      presets.square.x = 0;
      presets.square.y = -8;
      presets.portrait.zoom = 1;
      presets.portrait.x = 0;
      presets.portrait.y = -4;
      activePreset = 'square';
      syncControls();
      render();
      if (typeof dialog.showModal === 'function') dialog.showModal();
      else dialog.setAttribute('open', 'open');
    };
    nextImage.onerror = () => {
      input.value = '';
      setStatus('The selected photograph could not be opened.', 'error');
    };
    nextImage.src = objectUrl;
  };

  const cropData = (presetName, width, height, quality = 0.9) => {
    const source = document.createElement('canvas');
    drawCrop(source, presetName, true);
    if (source.width === width && source.height === height) return source.toDataURL('image/jpeg', quality);
    const output = document.createElement('canvas');
    output.width = width;
    output.height = height;
    const outputContext = output.getContext('2d');
    outputContext.imageSmoothingEnabled = true;
    outputContext.imageSmoothingQuality = 'high';
    outputContext.drawImage(source, 0, 0, width, height);
    return output.toDataURL('image/jpeg', quality);
  };

  input.addEventListener('change', () => loadFile(input.files?.[0] || null));

  presetButtons.forEach((button) => {
    button.addEventListener('click', () => {
      const requested = button.dataset.photoPreset;
      if (!presets[requested]) return;
      activePreset = requested;
      syncControls();
      render();
    });
  });

  [zoom, horizontal, vertical].forEach((control) => {
    control.addEventListener('input', () => {
      const current = state();
      current.zoom = Number(zoom.value);
      current.x = Number(horizontal.value);
      current.y = Number(vertical.value);
      render();
    });
  });

  apply.addEventListener('click', () => {
    if (!image) return;
    apply.disabled = true;
    setStatus('Generating the protected professional photo formats…', 'working');
    window.requestAnimationFrame(() => {
      try {
        const square = cropData('square', 600, 600, 0.9);
        const portrait = cropData('portrait', 800, 1000, 0.9);
        const thumbnail = cropData('square', 240, 240, 0.86);
        hiddenSquare.value = square;
        hiddenPortrait.value = portrait;
        hiddenThumbnail.value = thumbnail;
        if (squarePreview) squarePreview.src = square;
        if (portraitPreview) portraitPreview.src = portrait;
        if (cropState) cropState.textContent = 'Professional 2×2 and half-body crops are ready. Save the Doctor Profile to store them.';
        setStatus('Both professional formats are ready.', 'success');
        dialog.close();
      } catch (error) {
        setStatus('The browser could not generate the photo crops. Try a smaller image.', 'error');
      } finally {
        apply.disabled = false;
      }
    });
  });

  const cancelEditor = () => {
    input.value = '';
    hiddenSquare.value = '';
    hiddenPortrait.value = '';
    hiddenThumbnail.value = '';
    dialog.close();
  };
  cancelButtons.forEach((button) => button.addEventListener('click', cancelEditor));

  dialog.addEventListener('cancel', (event) => {
    event.preventDefault();
    cancelEditor();
  });
})();
