// @design-system: primitives/ImageUploadField/CropModal

'use client';

import { useState, useRef, useCallback } from 'react';
import ReactCrop, { type Crop, type PixelCrop, centerCrop, makeAspectCrop } from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
import { Dialog, DialogContent, DialogHeader, DialogFooter } from '@/components/ui/overlays/Dialog';
import * as RadixDialog from '@radix-ui/react-dialog';
import { useT } from '@/lib/i18n/react';
import type { DimensionConstraint } from '@/server/storage/imageDimensions';

export interface CropModalProps {
  /** Data URL of the image to crop. */
  imageSrc: string;
  /** Original file name (used when creating the output Blob). */
  fileName: string;
  /** Dimension constraint for this upload purpose. */
  constraint: DimensionConstraint;
  /** Called with the cropped Blob when the user confirms. */
  onCrop: (blob: Blob) => void;
  /** Called when the user cancels without cropping. */
  onCancel: () => void;
}

function aspectRatioNumber(aspectRatio: '1:1' | '16:9' | null): number | undefined {
  if (aspectRatio === '1:1') return 1;
  if (aspectRatio === '16:9') return 16 / 9;
  return undefined;
}

function centerInitialCrop(
  mediaWidth: number,
  mediaHeight: number,
  aspect: number | undefined,
): Crop {
  if (aspect) {
    return centerCrop(
      makeAspectCrop({ unit: '%', width: 90 }, aspect, mediaWidth, mediaHeight),
      mediaWidth,
      mediaHeight,
    );
  }
  return { unit: '%', x: 5, y: 5, width: 90, height: 90 };
}

/**
 * Modal that lets a vendor crop an uploaded image to the required aspect ratio.
 * Uses react-image-crop. The resulting Blob is handed back via onCrop.
 */
export function CropModal({ imageSrc, fileName, constraint, onCrop, onCancel }: CropModalProps) {
  const t = useT('image_upload');
  const imgRef = useRef<HTMLImageElement>(null);
  const aspect = aspectRatioNumber(constraint.aspectRatio);

  const [crop, setCrop] = useState<Crop>();
  const [completedCrop, setCompletedCrop] = useState<PixelCrop>();
  const [scale, setScale] = useState<number>(1); // displayed px / natural px

  const onImageLoad = useCallback(
    (e: React.SyntheticEvent<HTMLImageElement>) => {
      const img = e.currentTarget;
      const { naturalWidth, naturalHeight, width } = img;
      const s = width && naturalWidth ? width / naturalWidth : 1;
      setScale(s);
      // Initial crop set to the largest centered region that satisfies
      // the minimum natural-pixel constraint when possible.
      const initial = centerInitialCrop(naturalWidth, naturalHeight, aspect);
      setCrop(initial);
    },
    [aspect],
  );

  // Minimum crop size in displayed (CSS) pixels — react-image-crop expects display px.
  const minDisplayWidth = constraint.minWidth * scale;
  const minDisplayHeight = constraint.minHeight * scale;

  // Natural-pixel size of current completed crop (for confirm-button gating).
  const naturalCropW = completedCrop ? completedCrop.width / scale : 0;
  const naturalCropH = completedCrop ? completedCrop.height / scale : 0;
  const tooSmall =
    !!completedCrop && (naturalCropW < constraint.minWidth || naturalCropH < constraint.minHeight);

  const handleKeep = useCallback(async () => {
    const img = imgRef.current;
    if (!img || !completedCrop || completedCrop.width === 0 || completedCrop.height === 0) return;

    // Draw the cropped region on an off-screen canvas
    const scaleX = img.naturalWidth / img.width;
    const scaleY = img.naturalHeight / img.height;

    const canvas = document.createElement('canvas');
    canvas.width = completedCrop.width * scaleX;
    canvas.height = completedCrop.height * scaleY;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    ctx.drawImage(
      img,
      completedCrop.x * scaleX,
      completedCrop.y * scaleY,
      completedCrop.width * scaleX,
      completedCrop.height * scaleY,
      0,
      0,
      canvas.width,
      canvas.height,
    );

    canvas.toBlob(
      (blob) => {
        if (blob) onCrop(blob);
      },
      'image/jpeg',
      0.92,
    );
  }, [completedCrop, onCrop]);

  const subtitle = t('crop_subtitle')
    .replace('{minW}', String(constraint.minWidth))
    .replace('{minH}', String(constraint.minHeight));

  return (
    <Dialog
      open
      onOpenChange={(open) => {
        if (!open) onCancel();
      }}
    >
      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <RadixDialog.Title className="text-text-primary text-lg font-semibold">
            {t('crop_title')}
          </RadixDialog.Title>
          <RadixDialog.Description className="text-text-muted text-sm">
            {subtitle}
          </RadixDialog.Description>
        </DialogHeader>

        <div className="overflow-auto rounded-md">
          <ReactCrop
            crop={crop}
            onChange={(c) => setCrop(c)}
            onComplete={(c) => setCompletedCrop(c)}
            aspect={aspect}
            minWidth={minDisplayWidth}
            minHeight={minDisplayHeight}
            keepSelection
            className="max-h-[60vh] w-full"
          >
            {}
            <img
              ref={imgRef}
              src={imageSrc}
              alt={fileName}
              onLoad={onImageLoad}
              className="max-w-full"
            />
          </ReactCrop>
        </div>

        {tooSmall && (
          <p role="alert" className="text-danger-600 text-xs">
            {t('error_too_small')
              .replace('{minW}', String(constraint.minWidth))
              .replace('{minH}', String(constraint.minHeight))}
          </p>
        )}

        <DialogFooter>
          <button
            type="button"
            onClick={() => void handleKeep()}
            disabled={!completedCrop || completedCrop.width === 0 || tooSmall}
            className="focus-visible:ring-brand-primary-500 bg-brand-primary-600 text-brand-on-primary hover:bg-brand-primary-700 inline-flex h-10 items-center justify-center rounded-md px-4 text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50"
          >
            {t('crop_keep')}
          </button>
          <button
            type="button"
            onClick={onCancel}
            className="focus-visible:ring-brand-primary-500 bg-neutral-0 text-text-primary inline-flex h-10 items-center justify-center rounded-md border border-neutral-300 px-4 text-sm font-medium transition-colors hover:bg-neutral-50 focus-visible:outline-none focus-visible:ring-2"
          >
            {t('crop_cancel')}
          </button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
