import { useState } from "react";
import { Link } from "react-router-dom";
import type { Match } from "../types";
import ConfidenceBar from "./ConfidenceBar";

type Photo = { id: number; url: string | null; thumb_url: string | null };

// Top-3 estimated breeds as a comma-joined label (owners don't enter breed — we estimate it).
export function estimatedBreeds(breeds?: string[] | null): string {
  return breeds && breeds.length ? breeds.slice(0, 3).join(", ") : "Breed not estimated";
}

interface Props {
  match: Match;
  onConfirm?: (m: Match) => void;
  onReject?: (m: Match) => void;
  // For the "Not a match" list: move a rejected candidate back to pending for another look.
  onReconsider?: (m: Match) => void;
  // When provided, the photo modal compares these (the case's own dog) side-by-side with the match.
  queryPhotos?: Photo[];
  queryLabel?: string;
  // When set, a confirmed match links here (reunion next-steps page).
  reclaimTo?: string;
}

export default function MatchCard({
  match,
  onConfirm,
  onReject,
  onReconsider,
  queryPhotos,
  queryLabel,
  reclaimTo,
}: Props) {
  const [busy, setBusy] = useState(false);
  const [gallery, setGallery] = useState(false);
  const c = match.candidate;
  const photos = c?.pictures ?? [];
  const compare = (queryPhotos?.length ?? 0) > 0;
  const pct = (Math.round(match.similarity_score * 1000) / 10).toFixed(1); // one decimal
  const primary = photos.find((p) => p.is_primary) ?? photos[0];
  const title = c?.name || c?.description || (c?.type === "known" ? "Lost dog" : "Found dog");
  const zip = c?.current_zip || c?.last_known_zip;

  async function act(fn?: (m: Match) => void) {
    if (!fn) return;
    setBusy(true);
    try {
      await fn(match);
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="card flex gap-4">
      <button
        type="button"
        className="relative h-28 w-28 shrink-0 group"
        onClick={() => photos.length && setGallery(true)}
        title={photos.length ? (compare ? "Compare photos" : "View all photos") : undefined}
        disabled={!photos.length}
      >
        <img
          src={primary?.thumb_url || primary?.url || "/paw-placeholder.svg"}
          alt={title}
          className="h-28 w-28 rounded-md object-contain bg-gray-100 group-hover:ring-2 group-hover:ring-brand-300"
        />
        {photos.length > 1 && (
          <span className="badge absolute bottom-1 right-1 bg-black/60 text-white text-[10px]">
            {photos.length} photos
          </span>
        )}
      </button>
      <div className="flex-1 min-w-0">
        <div className="flex items-center justify-between gap-2">
          <h3 className="font-semibold truncate">
            #{match.rank} · {title}
          </h3>
          {match.status !== "pending" && (
            <span
              className={`badge ${
                match.status === "confirmed" ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600"
              }`}
            >
              {match.status}
            </span>
          )}
        </div>
        <p className="text-xs text-gray-500 mb-2">
          {estimatedBreeds(c?.estimated_breeds)}
          {zip ? ` · near ${zip}` : ""}
        </p>
        {c?.current_location_detail && (
          <p className="text-xs text-brand-700 mb-2">
            Being held at <span className="font-medium">{c.current_location_detail}</span>
          </p>
        )}
        {c?.estimated_breeds && c.estimated_breeds.length > 0 && (
          <div className="flex flex-wrap gap-1 mb-2">
            {c.estimated_breeds.slice(0, 3).map((b) => (
              <span key={b} className="badge bg-brand-50 text-brand-700 capitalize" title="AI breed estimate (top 3)">
                {b}
              </span>
            ))}
          </div>
        )}
        <ConfidenceBar score={match.similarity_score} />
        {photos.length > 0 && (
          <button
            type="button"
            className="btn-secondary mt-3"
            onClick={() => setGallery(true)}
          >
            {compare ? "Examine photos side by side" : "Examine photos"}
          </button>
        )}
        {(onConfirm || onReject) && match.status === "pending" && (
          <div className="flex gap-2 mt-3">
            <button className="btn-primary" disabled={busy} onClick={() => act(onConfirm)}>
              Confirm match
            </button>
            <button className="btn-secondary" disabled={busy} onClick={() => act(onReject)}>
              Not my dog
            </button>
          </div>
        )}
        {onReconsider && match.status === "rejected" && (
          <button className="btn-secondary mt-3" disabled={busy} onClick={() => act(onReconsider)}>
            Reconsider — move back to candidates
          </button>
        )}
        {reclaimTo && match.status === "confirmed" && (
          <Link to={reclaimTo} className="btn-primary inline-block mt-3">
            Reunion next steps →
          </Link>
        )}
      </div>

      {gallery && (
        <div
          className="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-40"
          role="dialog"
          onClick={() => setGallery(false)}
        >
          <div
            className="card max-w-4xl w-full max-h-[88vh] flex flex-col"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="flex items-start justify-between mb-3 shrink-0">
              <div>
                <h3 className="font-bold text-lg">
                  {compare ? `Compare · ${pct}% match` : title}
                </h3>
                <p className="text-xs text-gray-500">
                  {estimatedBreeds(c?.estimated_breeds)}
                  {zip ? ` · near ${zip}` : ""}
                </p>
              </div>
              <button className="btn-secondary" onClick={() => setGallery(false)}>
                Close
              </button>
            </div>

            {compare ? (
              // Each side scrolls on its own so you can line up one photo against the other.
              <div className="grid grid-cols-2 gap-4 flex-1 min-h-0">
                <PhotoColumn label={queryLabel ?? "Case dog"} photos={queryPhotos!} />
                <PhotoColumn label={`${title} (match)`} photos={photos} />
              </div>
            ) : (
              <div className="flex-1 min-h-0 overflow-y-auto">
                <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
                  {photos.map((p) => (
                    <img
                      key={p.id}
                      src={p.url || p.thumb_url || "/paw-placeholder.svg"}
                      alt={title}
                      className="w-full h-48 object-contain rounded-md bg-gray-100"
                    />
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function PhotoColumn({ label, photos }: { label: string; photos: Photo[] }) {
  return (
    <div className="h-full min-h-0 overflow-y-auto pr-1">
      <p className="text-sm font-medium text-gray-700 mb-2 sticky top-0 bg-white py-1 truncate z-10">
        {label} <span className="text-gray-400 font-normal">({photos.length})</span>
      </p>
      <div className="space-y-2">
        {photos.map((p) => (
          <img
            key={p.id}
            src={p.url || p.thumb_url || "/paw-placeholder.svg"}
            alt={label}
            className="w-full h-44 object-contain rounded-md bg-gray-100"
          />
        ))}
        {photos.length === 0 && <p className="text-gray-500 text-sm">No photos.</p>}
      </div>
    </div>
  );
}
