import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import {
  CheckCircle,
  Image as ImageIcon,
  FileText,
  Table,
  CheckSquare,
  Square,
  ArrowRight,
  UploadCloud,
} from "react-feather";

import { postForm, putJson, request } from "../lib/api";
import { getSessionId, setStoredSessionId } from "../lib/session";
import type { Session } from "../types/session";
import { PageFooter } from "../components/PageFooter";
import { PageHeader } from "../components/PageHeader";
import { PageShell } from "../components/PageShell";

export default function ReviewSetupPage() {
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const sessionId = getSessionId(searchParams.toString());

  const photoUploadRef = useRef<HTMLInputElement | null>(null);
  const dataUploadRef = useRef<HTMLInputElement | null>(null);
  const [session, setSession] = useState<Session | null>(null);
  const [selectedPhotoIds, setSelectedPhotoIds] = useState<Set<string>>(
    new Set(),
  );
  const [showAllPhotos, setShowAllPhotos] = useState(false);
  const [statusMessage, setStatusMessage] = useState("");
  const [isUploadingPhotos, setIsUploadingPhotos] = useState(false);
  const [isUploadingData, setIsUploadingData] = useState(false);

  useEffect(() => {
    if (!sessionId) {
      setStatusMessage("No active session found. Return to upload to continue.");
      return;
    }
    setStoredSessionId(sessionId);
    async function loadSession() {
      try {
        const data = await request<Session>(`/sessions/${sessionId}`);
        setSession(data);
        const initial = new Set(data.selected_photo_ids || []);
        const photoIds = (data.uploads?.photos ?? []).map((photo) => photo.id);
        if (photoIds.length > 0 && initial.size < photoIds.length) {
          photoIds.forEach((photoId) => initial.add(photoId));
        }
        setSelectedPhotoIds(initial);
      } catch (err) {
        const message =
          err instanceof Error ? err.message : "Failed to load session.";
        setStatusMessage(message);
      }
    }
    loadSession();
  }, [sessionId]);

  const photos = session?.uploads?.photos ?? [];
  const documents = session?.uploads?.documents ?? [];
  const dataFiles = session?.uploads?.data_files ?? [];

  const canContinue =
    selectedPhotoIds.size > 0 || (session?.uploads?.data_files?.length ?? 0) > 0;
  const previewCount = 9;
  const visiblePhotos = showAllPhotos ? photos : photos.slice(0, previewCount);

  const readyStatus = useMemo(() => {
    if (!sessionId) return "No active session found. Return to upload to continue.";
    if (!canContinue) return "Choose report example images to continue...";
    if (selectedPhotoIds.size === 0 && (session?.uploads?.data_files?.length ?? 0) > 0) {
      return "Data file detected. Continue to build the report.";
    }
    return "Ready. Continue to report viewer.";
  }, [canContinue, selectedPhotoIds.size, session?.uploads?.data_files?.length, sessionId]);

  async function handleUploadPhotos(files: FileList | null) {
    if (!sessionId || !files || files.length === 0) return;
    setIsUploadingPhotos(true);
    setStatusMessage("");
    const priorPhotoIds = new Set(
      (session?.uploads?.photos ?? []).map((photo) => photo.id),
    );
    try {
      let updatedSession: Session | null = session;
      for (const file of Array.from(files)) {
        const formData = new FormData();
        formData.append("file", file);
        updatedSession = await postForm<Session>(
          `/sessions/${sessionId}/uploads`,
          formData,
        );
      }
      if (updatedSession) {
        setSession(updatedSession);
        const next = new Set(selectedPhotoIds);
        for (const photo of updatedSession.uploads?.photos ?? []) {
          if (!priorPhotoIds.has(photo.id)) {
            next.add(photo.id);
          }
        }
        setSelectedPhotoIds(next);
      }
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Failed to upload photos.";
      setStatusMessage(message);
    } finally {
      setIsUploadingPhotos(false);
      if (photoUploadRef.current) photoUploadRef.current.value = "";
    }
  }

  async function handleUploadDataFile(files: FileList | null) {
    if (!sessionId || !files || files.length === 0) return;
    setIsUploadingData(true);
    setStatusMessage("");
    try {
      const file = files[0];
      const formData = new FormData();
      formData.append("file", file);
      const updated = await postForm<Session>(
        `/sessions/${sessionId}/data-files`,
        formData,
      );
      setSession(updated);
      const nextSelected = new Set(updated.selected_photo_ids || []);
      const allPhotoIds = (updated.uploads?.photos ?? []).map((photo) => photo.id);
      if (nextSelected.size < allPhotoIds.length) {
        allPhotoIds.forEach((photoId) => nextSelected.add(photoId));
      }
      setSelectedPhotoIds(nextSelected);
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Failed to upload data file.";
      setStatusMessage(message);
    } finally {
      setIsUploadingData(false);
      if (dataUploadRef.current) dataUploadRef.current.value = "";
    }
  }

  async function handleContinue() {
    if (!sessionId) return;
    if (selectedPhotoIds.size === 0 && dataFiles.length === 0) return;
    try {
      if (selectedPhotoIds.size > 0) {
        await putJson(`/sessions/${sessionId}/selection`, {
          selected_photo_ids: Array.from(selectedPhotoIds),
        });
      }
      navigate(`/report-viewer?session=${encodeURIComponent(sessionId)}`);
    } catch (err) {
      const message =
        err instanceof Error ? err.message : "Failed to save selection.";
      setStatusMessage(message);
    }
  }

  return (
    <PageShell>
      <PageHeader
        title="RepEx - Report Express"
        subtitle="Review uploads -> pick examples -> continue to report viewer"
        right={
          <span className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-xs font-semibold text-gray-700">
            <CheckCircle className="h-4 w-4" />
            Uploads processed
          </span>
        }
      />

      <section className="mb-8" aria-labelledby="what-next">
        <h2
          id="what-next"
          className="text-xl font-semibold text-gray-800 border-b border-gray-200 pb-2 mb-4"
        >
          What happens on this page
        </h2>

        <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <div className="rounded-lg border border-gray-200 bg-gray-50 p-4">
            <div className="inline-flex h-10 w-10 items-center justify-center rounded-full bg-blue-50 border border-blue-100 mb-3">
              <ImageIcon className="h-5 w-5 text-blue-700" />
            </div>
            <h3 className="font-semibold text-gray-900 mb-1">
              Select example photos
            </h3>
            <p className="text-sm text-gray-600">
              Choose which uploaded images should appear as example figures in the report.
            </p>
          </div>

          <div className="rounded-lg border border-gray-200 bg-gray-50 p-4">
            <div className="inline-flex h-10 w-10 items-center justify-center rounded-full bg-emerald-50 border border-emerald-100 mb-3">
              <FileText className="h-5 w-5 text-emerald-700" />
            </div>
            <h3 className="font-semibold text-gray-900 mb-1">Confirm documents</h3>
            <p className="text-sm text-gray-600">
              Ensure supporting PDFs/DOCX are correct (and later attach to export if needed).
            </p>
          </div>

          <div className="rounded-lg border border-gray-200 bg-gray-50 p-4">
            <div className="inline-flex h-10 w-10 items-center justify-center rounded-full bg-amber-50 border border-amber-100 mb-3">
              <Table className="h-5 w-5 text-amber-700" />
            </div>
            <h3 className="font-semibold text-gray-900 mb-1">Use Excel/CSV data</h3>
            <p className="text-sm text-gray-600">
              If Excel/CSV exists, it will populate report data areas automatically in later steps.
            </p>
          </div>
        </div>
      </section>

      <section className="mb-8" aria-labelledby="review-uploads">
        <h2
          id="review-uploads"
          className="text-xl font-semibold text-gray-800 border-b border-gray-200 pb-2 mb-6"
        >
          Review uploaded files
        </h2>

        <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
          <div className="lg:col-span-2">
            <div className="flex flex-wrap items-center justify-between gap-3 mb-3">
              <h3 className="text-lg font-semibold text-gray-900">Photos</h3>
              <div className="flex flex-wrap items-center gap-2">
                <span className="text-sm font-semibold text-gray-600">
                  {photos.length} file{photos.length === 1 ? "" : "s"}
                </span>
                <button
                  type="button"
                  onClick={() => photoUploadRef.current?.click()}
                  disabled={!sessionId || isUploadingPhotos}
                  className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-semibold text-gray-800 hover:bg-gray-50 transition disabled:opacity-50"
                >
                  <UploadCloud className="h-4 w-4" />
                  {isUploadingPhotos ? "Uploading..." : "Add photos"}
                </button>
                <input
                  ref={photoUploadRef}
                  type="file"
                  className="hidden"
                  multiple
                  accept=".jpg,.jpeg,.png,.webp"
                  onChange={(event) => handleUploadPhotos(event.target.files)}
                />
              </div>
            </div>

            <div className="rounded-lg border border-gray-200 bg-white p-4">
              <p className="text-sm text-gray-600 mb-3">
                Select images to use as example figures in the report.{" "}
                <span className="font-semibold text-gray-800">Recommended:</span>{" "}
                2-6 images.
              </p>

              <div className="grid grid-cols-2 md:grid-cols-3 gap-3">
                {photos.length === 0 ? (
                  <div className="col-span-full text-sm text-gray-500">
                    No photos were uploaded.
                  </div>
                ) : (
                  visiblePhotos.map((photo) => {
                    const isChecked = selectedPhotoIds.has(photo.id);
                    return (
                      <label key={photo.id} className="cursor-pointer">
                        <input
                          type="checkbox"
                          className="sr-only"
                          checked={isChecked}
                          onChange={(event) => {
                            const next = new Set(selectedPhotoIds);
                            if (event.target.checked) {
                              next.add(photo.id);
                            } else {
                              next.delete(photo.id);
                            }
                            setSelectedPhotoIds(next);
                          }}
                        />
                        <div
                          className={[
                            "rounded-lg border bg-gray-50 overflow-hidden transition",
                            isChecked
                              ? "ring-2 ring-emerald-200 border-emerald-300"
                              : "border-gray-200",
                          ].join(" ")}
                        >
                          <div className="relative">
                            <img
                              src={photo.url}
                              alt={photo.name}
                              className="h-28 w-full object-cover"
                              loading="eager"
                            />
                            <div
                              className={[
                                "absolute top-2 right-2 inline-flex items-center justify-center rounded-full border p-1.5",
                                isChecked
                                  ? "bg-emerald-50 border-emerald-200 text-emerald-700"
                                  : "bg-white/90 border-gray-200 text-gray-700",
                              ].join(" ")}
                            >
                              <CheckCircle className="h-4 w-4" />
                            </div>
                          </div>
                          <div className="p-2">
                            <div className="text-xs font-semibold text-gray-900 truncate">
                              {photo.name}
                            </div>
                            <div className="text-xs text-gray-500">
                              Click to select for report
                            </div>
                          </div>
                        </div>
                      </label>
                    );
                  })
                )}
              </div>

              {photos.length > previewCount ? (
                <div className="mt-3 flex items-center justify-between gap-3 text-sm text-gray-600">
                  <span>
                    Showing {visiblePhotos.length} of {photos.length} photos
                  </span>
                  <button
                    type="button"
                    onClick={() => setShowAllPhotos((prev) => !prev)}
                    className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
                  >
                    {showAllPhotos ? "Show fewer" : `Show all (${photos.length})`}
                  </button>
                </div>
              ) : null}

              <div className="mt-4 flex flex-wrap items-center justify-between gap-3">
                <div className="text-sm text-gray-600">
                  Selected for report:{" "}
                  <span className="font-semibold text-gray-900">
                    {selectedPhotoIds.size}
                  </span>
                </div>
                <div className="flex gap-2">
                  <button
                    type="button"
                    onClick={() => {
                      setSelectedPhotoIds(new Set(photos.map((p) => p.id)));
                    }}
                    className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
                  >
                    <CheckSquare className="h-4 w-4" />
                    Select all
                  </button>
                  <button
                    type="button"
                    onClick={() => setSelectedPhotoIds(new Set())}
                    className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 transition"
                  >
                    <Square className="h-4 w-4" />
                    Clear
                  </button>
                </div>
              </div>
            </div>
          </div>

          <div className="space-y-6">
            <div>
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-lg font-semibold text-gray-900">Documents</h3>
                <span className="text-sm font-semibold text-gray-600">
                  {documents.length} file{documents.length === 1 ? "" : "s"}
                </span>
              </div>

              <div className="rounded-lg border border-gray-200 bg-white p-4">
                <ul className="space-y-2 text-sm text-gray-700">
                  {documents.length === 0 ? (
                    <li className="text-sm text-gray-500">
                      No supporting documents detected.
                    </li>
                  ) : (
                    documents.map((doc) => (
                      <li
                        key={doc.id}
                        className="flex items-center justify-between gap-3 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2"
                      >
                        <div className="flex items-center gap-2 min-w-0">
                          <FileText className="h-4 w-4 text-gray-600" />
                          <span className="truncate text-gray-800">{doc.name}</span>
                        </div>
                        <span className="text-xs font-semibold text-gray-600">
                          {doc.content_type || "File"}
                        </span>
                      </li>
                    ))
                  )}
                </ul>
                {documents.length === 0 ? (
                  <p className="text-xs text-gray-500 mt-3">
                    PDFs/DOCX appear here after processing.
                  </p>
                ) : null}
              </div>
            </div>

            <div>
              <div className="flex flex-wrap items-center justify-between gap-3 mb-3">
                <h3 className="text-lg font-semibold text-gray-900">Data files</h3>
                <div className="flex flex-wrap items-center gap-2">
                  <span className="text-sm font-semibold text-gray-600">
                    {dataFiles.length} file{dataFiles.length === 1 ? "" : "s"}
                  </span>
                  <button
                    type="button"
                    onClick={() => dataUploadRef.current?.click()}
                    disabled={!sessionId || isUploadingData}
                    className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-semibold text-gray-800 hover:bg-gray-50 transition disabled:opacity-50"
                  >
                    <UploadCloud className="h-4 w-4" />
                    {isUploadingData ? "Uploading..." : "Upload data file"}
                  </button>
                  <input
                    ref={dataUploadRef}
                    type="file"
                    className="hidden"
                    accept=".csv,.xls,.xlsx"
                    onChange={(event) => handleUploadDataFile(event.target.files)}
                  />
                </div>
              </div>

              <div className="rounded-lg border border-gray-200 bg-white p-4">
                {dataFiles.length === 0 ? (
                  <div className="rounded-lg border border-gray-200 bg-gray-50 p-3 text-sm text-gray-600">
                    <div className="font-semibold text-gray-800 mb-1">
                      No Excel/CSV detected
                    </div>
                    If you upload a CSV or Excel file, RepEx can auto-populate report data fields.
                  </div>
                ) : (
                  dataFiles.map((file) => (
                    <div
                      key={file.id}
                      className="rounded-lg border border-gray-200 bg-gray-50 p-3 text-sm text-gray-700 mb-2 last:mb-0"
                    >
                      <div className="flex items-center justify-between gap-3">
                        <div className="flex items-center gap-2 min-w-0">
                          <Table className="h-4 w-4 text-amber-700" />
                          <span className="truncate font-semibold text-gray-900">
                            {file.name}
                          </span>
                        </div>
                        <span className="text-xs font-semibold text-gray-600">
                          {file.content_type || "Data"}
                        </span>
                      </div>
                      <div className="text-xs text-gray-600 mt-1">
                        Will populate report data areas (tables/fields).
                      </div>
                    </div>
                  ))
                )}
                <p className="text-xs text-gray-500 mt-3">
                  If present, these files will populate report tables/fields automatically.
                </p>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section className="mb-4" aria-label="Continue to report viewer">
        <div className="rounded-lg border border-gray-200 bg-gray-50 p-4 flex flex-col sm:flex-row gap-3 sm:items-center sm:justify-between">
          <div
            className={[
              "text-sm",
              canContinue ? "text-emerald-700 font-semibold" : "text-amber-700 font-semibold",
            ].join(" ")}
          >
            {readyStatus}
          </div>

          <button
            type="button"
            onClick={handleContinue}
            disabled={!canContinue}
            className="inline-flex items-center justify-center gap-2 rounded-lg bg-emerald-600 px-5 py-2.5 text-white font-semibold hover:bg-emerald-700 transition disabled:opacity-50 disabled:cursor-not-allowed"
          >
            <ArrowRight className="h-5 w-5" />
            Continue to Report Viewer
          </button>
        </div>

        <p className="text-xs text-gray-500 mt-3">
          Note: This page assumes uploads were completed on a previous processing step.
        </p>
      </section>

      {statusMessage ? (
        <p className="text-sm text-red-600">{statusMessage}</p>
      ) : null}

      <PageFooter note="Workflow: Processing -> Review uploads -> Report viewer -> Edit -> Export" />
    </PageShell>
  );
}
