import { useRef, useState } from 'react';
import '../../styles/UploadTab.css';
import { loadImageDimensions } from '../../utils/imageLoading';
import { MIN_ELEMENT_SIZE } from '../../constants/elements';

/**
 * Upload Photo tab.
 *
 * Layout:
 *   [drop zone]               — Click to upload or drop a file
 *   [Recent Uploads]          — quick re-add of previously-used pet photos
 */
export function UploadTab({ onAddImage, recentUploads = [], onRemoveUpload }) {
  const fileInputRef = useRef(null);
  const [isDragging, setIsDragging] = useState(false);
  const [isUploading, setIsUploading] = useState(false);

  const placeImage = async (previewUrl, originalUrl) => {
    const { width: naturalW, height: naturalH } = await loadImageDimensions(previewUrl);
    const maxSide = 150;
    const scale = Math.min(maxSide / naturalW, maxSide / naturalH, 1);
    const width = Math.max(MIN_ELEMENT_SIZE, Math.round(naturalW * scale));
    const height = Math.max(MIN_ELEMENT_SIZE, Math.round(naturalH * scale));
    const x = Math.round((300 - width) / 2);
    const y = Math.round((300 - height) / 2);

    onAddImage({
      type: 'image',
      x, y, width, height,
      rotation: 0,
      src: previewUrl,
      originalUrl,
    });
  };

  const handleFiles = async (files) => {
    const file = files[0];
    if (!file) return;
    const validTypes = ['image/jpeg', 'image/png', 'image/webp'];
    if (!validTypes.includes(file.type)) { alert('Please upload a JPEG, PNG, or WebP image'); return; }
    if (file.size > 20 * 1024 * 1024) { alert('File size must be under 20MB'); return; }

    setIsUploading(true);
    try {
      const formData = new FormData();
      formData.append('image', file);
      const response = await fetch('/api/upload', { method: 'POST', body: formData });
      if (!response.ok) throw new Error('Upload failed');
      const data = await response.json();
      await placeImage(data.preview.url, data.original.url);
    } catch (error) {
      console.error('Upload error:', error);
      alert('Failed to upload image. Please try again.');
    } finally {
      setIsUploading(false);
      // Reset the file input value so picking the same file twice in a row still fires
      // the change event. Without this, click-to-pick → delete → click-to-pick the same
      // file silently does nothing.
      if (fileInputRef.current) fileInputRef.current.value = '';
    }
  };

  return (
    <div className="ut">
      <div
        onClick={() => fileInputRef.current?.click()}
        onDragOver={(e) => { e.preventDefault(); setIsDragging(true); }}
        onDragLeave={(e) => { e.preventDefault(); setIsDragging(false); }}
        onDrop={(e) => { e.preventDefault(); setIsDragging(false); handleFiles(e.dataTransfer.files); }}
        className={`ut__dropzone${isDragging ? ' is-dragging' : ''}`}
        role="button"
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); fileInputRef.current?.click(); }
        }}
      >
        <div className="ut__dropzone-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" width="34" height="34" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 15a4 4 0 0 1 .9-7.9 5.5 5.5 0 0 1 10.6-1.5A4.5 4.5 0 0 1 22 9.5" />
            <path d="M12 12v9" />
            <path d="M8 16l4-4 4 4" />
          </svg>
        </div>
        <div className="ut__dropzone-text">Drop your pet photo here</div>
        <div className="ut__dropzone-hint">
          or <span className="ut__browse">click to browse</span>
        </div>
      </div>
      <input
        ref={fileInputRef}
        type="file"
        accept="image/jpeg,image/png,image/webp"
        onChange={(e) => handleFiles(e.target.files)}
        className="ut__hidden-input"
      />

      {isUploading && <div className="ut__status">Uploading…</div>}

      {recentUploads.length > 0 && (
        <div className="ut__recent">
          <div className="ut__recent-header">
            <span className="ut__recent-title">Recent Uploads</span>
            <button type="button" className="ut__see-all" onClick={(e) => e.preventDefault()}>See all</button>
          </div>
          <div className="ut__recent-grid">
            {recentUploads.slice(0, 5).map((u) => (
              <div key={u.id} className="ut__recent-item">
                <button
                  type="button"
                  className="ut__recent-thumb"
                  onClick={() => placeImage(u.previewUrl, u.originalUrl)}
                  aria-label="Add this photo to canvas"
                >
                  {/* onError prunes entries whose underlying file is
                   * no longer on the server. The `recentUploads` list
                   * is persisted to localStorage, but the files behind
                   * those URLs can vanish between sessions — server
                   * restart wiping /uploads, manual cleanup, a TTL on
                   * the preview dir, etc. When that happens the
                   * thumbnail GET returns 404 and the browser renders
                   * a broken-image icon.
                   *
                   * Calling `onRemoveUpload(u.id)` on error lets the
                   * parent (App) drop the entry from `recentUploads`,
                   * which removes the row on the next render and
                   * triggers a persistence save that cleans the entry
                   * out of localStorage too. No retry / debouncing
                   * because the cost of mis-pruning a transient
                   * network failure is low (user can re-upload from
                   * the dropzone), while the cost of NOT pruning a
                   * permanently-dead URL is a persistent broken
                   * thumbnail across every future session.
                   *
                   * Guarded on `onRemoveUpload` being supplied so the
                   * component still works in callers that don't wire
                   * the prune callback through (the broken thumb just
                   * stays, same as the previous behaviour). */}
                  <img
                    src={u.previewUrl}
                    alt=""
                    onError={() => onRemoveUpload?.(u.id)}
                  />
                </button>
                {onRemoveUpload && (
                  <button
                    type="button"
                    className="ut__recent-delete"
                    onClick={() => onRemoveUpload(u.id)}
                    aria-label="Remove this photo from recent uploads"
                  >
                    <svg viewBox="0 0 24 24" width="12" height="12" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <path d="M3 6h18" />
                      <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
                      <path d="M6 6l1 14a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-14" />
                      <path d="M10 11v6" />
                      <path d="M14 11v6" />
                    </svg>
                    <span>Delete</span>
                  </button>
                )}
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
