"use client";

import { useState, useEffect, useRef, useCallback } from "react";
import Link from "next/link";
import Image from "next/image";
import { ReviewPlayer, type ReviewPlayerRef } from "@/components/player/ReviewPlayer";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { ScrollArea } from "@/components/ui/scroll-area";
import { useToast } from "@/components/ui/use-toast";
import { cn, frameToTimecode, getInitials } from "@/lib/utils";
import {
  Film,
  ArrowLeft,
  CheckCircle2,
  XCircle,
  AlertCircle,
  MessageSquare,
  Send,
  Clock,
  ChevronLeft,
  ChevronRight,
  Copy,
  Check,
  Download,
} from "lucide-react";
import { useReviewStore } from "@/hooks/use-review-player";
import { ReviewPasswordGate } from "@/components/clients/ReviewPasswordGate";

interface Comment {
  id: string;
  frameNumber: number;
  timestamp: number;
  text: string;
  isResolved: boolean;
  createdAt: string;
  author: { id: string; name: string | null; image: string | null; email: string };
  replies: { id: string; text: string; createdAt: string; author: { name: string | null } }[];
}

interface Version {
  id: string;
  versionNumber: number;
  fileUrl: string;
  fps: number;
  duration: number | null;
  approvalStatus: string;
  notes: string | null;
  // Top-level high-res flags (normalised from either shot or task.shot)
  hasHighRes?: boolean;
  highResShotId?: string | null;
  highResFilename?: string | null;
  shot?: {
    id: string;
    shotCode: string;
    hasHighRes?: boolean;
    highResFilename?: string | null;
    project: { id: string; name: string; code: string };
  } | null;
  task?: {
    id: string;
    title: string;
    type: string;
    project: { id: string; name: string; code: string };
    shot?: { id: string; shotCode: string } | null;
    asset?: { assetCode: string; name: string } | null;
  } | null;
}

const APPROVAL_STATUS_STYLES: Record<string, string> = {
  PENDING_REVIEW: "bg-amber-500/10 text-amber-400 border-amber-500/20",
  APPROVED: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20",
  REJECTED: "bg-red-500/10 text-red-400 border-red-500/20",
  NEEDS_CHANGES: "bg-orange-500/10 text-orange-400 border-orange-500/20",
};

const QUEUE_KEY = 'client-portal-queue';

export default function ClientReviewPage({
  params,
}: {
  params: Promise<{ token: string; versionId: string }>;
}) {
  const [token, setToken] = useState("");
  const [version, setVersion] = useState<Version | null>(null);
  const [comments, setComments] = useState<Comment[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [requiresPassword, setRequiresPassword] = useState(false);
  const [versionId, setVersionId] = useState("");

  const currentFrame = useReviewStore((s) => s.currentFrame);

  // Comment form state
  const [commentText, setCommentText] = useState("");
  const [commentFrame, setCommentFrame] = useState<number | null>(null);
  const [submittingComment, setSubmittingComment] = useState(false);

  // Approval dialog
  const [approvalDialog, setApprovalDialog] = useState<{
    open: boolean;
    status: "APPROVED" | "REJECTED" | "NEEDS_CHANGES" | null;
  }>({ open: false, status: null });
  const [approvalNotes, setApprovalNotes] = useState("");
  const [submittingApproval, setSubmittingApproval] = useState(false);
  const [currentApprovalStatus, setCurrentApprovalStatus] = useState("PENDING_REVIEW");
  const [nextReview, setNextReview] = useState<{ versionId: string; label: string } | null>(null);
  const [prevReview, setPrevReview] = useState<{ versionId: string; label: string } | null>(null);
  const [copiedTaskName, setCopiedTaskName] = useState(false);
  const [downloadingHighRes, setDownloadingHighRes] = useState(false);
  const [commentsOpen, setCommentsOpen] = useState(true);

  const playerRef = useRef<ReviewPlayerRef>(null);
  const { toast } = useToast();

  useEffect(() => {
    params.then(({ token: t, versionId: vId }) => {
      setToken(t);
      setVersionId(vId);
      loadVersion(t, vId);
    });
  }, [params]);

  useEffect(() => {
    if (!versionId) return;
    try {
      const queueJson = sessionStorage.getItem(QUEUE_KEY);
      if (!queueJson) { setNextReview(null); setPrevReview(null); return; }
      const queue: Array<{ versionId: string; label: string }> = JSON.parse(queueJson);
      const idx = queue.findIndex((item) => item.versionId === versionId);
      setNextReview(idx >= 0 && idx < queue.length - 1 ? queue[idx + 1] : null);
      setPrevReview(idx > 0 ? queue[idx - 1] : null);
    } catch {
      setNextReview(null);
      setPrevReview(null);
    }
  }, [versionId]);

  const loadVersion = (t: string, vId: string) => {
    setLoading(true);
    setError(null);
    fetch(`/api/client/${t}/versions/${vId}`)
      .then(async (r) => {
        if (r.status === 401) {
          const data = await r.json().catch(() => ({}));
          if (data.requiresPassword) {
            setRequiresPassword(true);
            return null;
          }
        }
        if (!r.ok) throw new Error("Invalid or expired review link");
        return r.json();
      })
      .then((data) => {
        if (!data) return;
        setVersion(data.version);
        setComments(data.comments);
        setCurrentApprovalStatus(data.version.approvalStatus);
        setRequiresPassword(false);
      })
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  };

  const refreshComments = useCallback(async (t: string, vId: string) => {
    const res = await fetch(`/api/client/${t}/versions/${vId}`);
    if (res.ok) {
      const data = await res.json();
      setComments(data.comments);
    }
  }, []);

  const handlePlayerAddComment = useCallback((frameNumber: number, _timestamp: number) => {
    playerRef.current?.pause();
    setCommentFrame(frameNumber);
  }, []);

  const handleSubmitComment = async () => {
    if (!commentText.trim() || commentFrame === null || !version) return;
    setSubmittingComment(true);
    try {
      const res = await fetch(`/api/client/${token}/comment`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          versionId: version.id,
          frameNumber: commentFrame,
          timestamp: commentFrame / version.fps,
          text: commentText.trim(),
        }),
      });
      if (!res.ok) throw new Error("Failed to post comment");
      setCommentText("");
      setCommentFrame(null);
      await refreshComments(token, version.id);
      toast({ title: "Comment added" });
    } catch {
      toast({ title: "Failed to add comment", variant: "destructive" });
    } finally {
      setSubmittingComment(false);
    }
  };

  const handleDownloadHighRes = async () => {
    const shotId = version?.highResShotId ?? version?.shot?.id;
    if (!shotId || !token) return;
    setDownloadingHighRes(true);
    try {
      const res = await fetch(`/api/client/${token}/shots/${shotId}/highres/download`);
      if (!res.ok) throw new Error("Could not get download link");
      const { url } = await res.json();
      // Open the presigned URL — the Content-Disposition header forces a download
      window.open(url, "_blank", "noopener,noreferrer");
    } catch {
      toast({ title: "Download failed", variant: "destructive" });
    } finally {
      setDownloadingHighRes(false);
    }
  };

  const handleSubmitApproval = async () => {
    if (!approvalDialog.status || !version) return;
    setSubmittingApproval(true);
    try {
      const res = await fetch(`/api/client/${token}/approve`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          versionId: version.id,
          status: approvalDialog.status,
          notes: approvalNotes,
        }),
      });
      if (!res.ok) throw new Error("Failed to submit decision");
      setCurrentApprovalStatus(approvalDialog.status);
      setApprovalDialog({ open: false, status: null });
      setApprovalNotes("");
      toast({
        title:
          approvalDialog.status === "APPROVED"
            ? "Shot approved!"
            : approvalDialog.status === "REJECTED"
            ? "Version rejected"
            : "Changes requested",
        description:
          approvalDialog.status === "APPROVED"
            ? "The shot has been marked as client approved."
            : undefined,
      });
    } catch {
      toast({ title: "Failed to submit decision", variant: "destructive" });
    } finally {
      setSubmittingApproval(false);
    }
  };

  if (loading) {
    return (
      <div className="min-h-screen bg-zinc-950 flex items-center justify-center">
        <div className="h-8 w-8 border-2 border-amber-500 border-t-transparent rounded-full animate-spin" />
      </div>
    );
  }

  if (requiresPassword) {
    return (
      <ReviewPasswordGate
        token={token}
        onUnlocked={() => loadVersion(token, versionId)}
      />
    );
  }

  if (error || !version) {
    return (
      <div className="min-h-screen bg-zinc-950 flex flex-col items-center justify-center gap-4 text-center px-4">
        <Film className="h-10 w-10 text-zinc-600" />
        <h1 className="text-xl font-semibold text-white">Version unavailable</h1>
        <p className="text-zinc-400 text-sm">{error}</p>
      </div>
    );
  }

  const approvalStyle = APPROVAL_STATUS_STYLES[currentApprovalStatus] ?? "";

  return (
    <div className="flex flex-col h-screen bg-zinc-950 text-white overflow-hidden">
      {/* Header */}
      <header className="grid grid-cols-[1fr_auto_1fr] items-center gap-2 px-4 py-2.5 border-b border-zinc-800 bg-zinc-900 shrink-0">
        {/* Left: back + shot path */}
        <div className="flex items-center gap-3 min-w-0">
          <Link
            href={`/client/${token}`}
            className="text-zinc-400 hover:text-white transition-colors flex items-center gap-1.5 text-sm shrink-0"
          >
            <ArrowLeft className="h-4 w-4" />
            <span className="hidden sm:inline">All Shots</span>
          </Link>

          <div className="h-4 w-px bg-zinc-700 shrink-0" />

          <div className="flex items-center gap-2 min-w-0">
            <div className="w-5 h-5 rounded bg-black flex items-center justify-center shrink-0">
              <Image src="/logo.svg" alt="Logo" width={14} height={14} />
            </div>
            {(() => {
              const project = version.shot?.project ?? version.task?.project;
              const contextCode =
                version.shot?.shotCode ??
                version.task?.shot?.shotCode ??
                version.task?.asset?.assetCode ??
                null;
              const taskName = version.task?.title ?? null;
              return (
                <>
                  <span className="text-xs text-zinc-500 hidden sm:block">{project?.code}</span>
                  <span className="text-zinc-600">/</span>
                  {contextCode && (
                    <span className="font-mono font-semibold">{contextCode}</span>
                  )}
                  {taskName && (
                    <>
                      <span className="text-zinc-600">/</span>
                      <span className="font-mono text-sm text-zinc-300 truncate hidden sm:block">{taskName}</span>
                      <button
                        onClick={() => {
                          navigator.clipboard.writeText(taskName).then(() => {
                            setCopiedTaskName(true);
                            setTimeout(() => setCopiedTaskName(false), 1500);
                          });
                        }}
                        className="shrink-0 p-0.5 rounded text-zinc-500 hover:text-zinc-300 transition-colors"
                        title="Copy task name"
                      >
                        {copiedTaskName ? (
                          <Check className="h-3 w-3 text-emerald-400" />
                        ) : (
                          <Copy className="h-3 w-3" />
                        )}
                      </button>
                    </>
                  )}
                </>
              );
            })()}
          </div>
        </div>

        {/* Center: status badge + decision buttons */}
        <div className="flex items-center gap-2 shrink-0">
          <span
            className={cn(
              "text-xs px-2.5 py-1 rounded-full border hidden sm:inline-flex items-center gap-1 shrink-0",
              approvalStyle
            )}
          >
            {currentApprovalStatus === "PENDING_REVIEW" ? (
              <Clock className="h-3 w-3" />
            ) : currentApprovalStatus === "APPROVED" ? (
              <CheckCircle2 className="h-3 w-3" />
            ) : currentApprovalStatus === "NEEDS_CHANGES" ? (
              <AlertCircle className="h-3 w-3" />
            ) : (
              <XCircle className="h-3 w-3" />
            )}
            {currentApprovalStatus.replace(/_/g, " ")}
          </span>
          <Button
            size="sm"
            variant="outline"
            className="h-8 text-xs gap-1 text-orange-400 border-orange-500/30 hover:bg-orange-500/10"
            onClick={() => setApprovalDialog({ open: true, status: "NEEDS_CHANGES" })}
          >
            <AlertCircle className="h-3.5 w-3.5" />
            <span className="hidden sm:inline">Needs Changes</span>
          </Button>
          <Button
            size="sm"
            className="h-8 text-xs gap-1 bg-emerald-600 hover:bg-emerald-500 text-white"
            onClick={() => setApprovalDialog({ open: true, status: "APPROVED" })}
          >
            <CheckCircle2 className="h-3.5 w-3.5" />
            Approve
          </Button>
          {(version.hasHighRes || version.shot?.hasHighRes) && (
            <Button
              size="sm"
              variant="outline"
              className="h-8 text-xs gap-1 text-sky-400 border-sky-500/30 hover:bg-sky-500/10"
              disabled={downloadingHighRes}
              onClick={handleDownloadHighRes}
              title={version.highResFilename ?? version.shot?.highResFilename ?? "Download high-res file"}
            >
              <Download className="h-3.5 w-3.5" />
              <span className="hidden sm:inline">{downloadingHighRes ? "Getting link…" : "High Res"}</span>
            </Button>
          )}
        </div>

        {/* Right: Prev / Next navigation */}
        <div className="flex items-center gap-2 justify-end shrink-0">
          {prevReview ? (
            <Link
              href={`/client/${token}/review/${prevReview.versionId}`}
              className="inline-flex items-center gap-1 text-sm font-medium text-zinc-300 hover:text-white transition-colors shrink-0"
            >
              <ChevronLeft className="h-4 w-4" />
              <span className="hidden sm:inline">Prev</span>
              <span className="font-mono text-xs text-zinc-500 hidden md:inline">{prevReview.label}</span>
            </Link>
          ) : (
            <span className="w-14" />
          )}
          {(prevReview || nextReview) && <div className="h-6 w-px bg-zinc-700" />}
          {nextReview ? (
            <Link
              href={`/client/${token}/review/${nextReview.versionId}`}
              className="inline-flex items-center gap-1 text-sm font-medium text-zinc-300 hover:text-white transition-colors shrink-0"
            >
              <span className="font-mono text-xs text-zinc-500 hidden md:inline">{nextReview.label}</span>
              <span className="hidden sm:inline">Next</span>
              <ChevronRight className="h-4 w-4" />
            </Link>
          ) : (
            <span className="w-14" />
          )}
        </div>
      </header>

      {/* Main: player + comments — stacked on mobile, side-by-side on md+ */}
      <div className="flex flex-col md:flex-row flex-1 overflow-hidden">
        {/* Player */}
        <div className="flex-1 min-w-0 min-h-0 overflow-hidden flex flex-col bg-black">
          <ReviewPlayer
            ref={playerRef}
            videoUrl={version.fileUrl}
            fps={version.fps}
            comments={comments as any}
            versionId={version.id}
            onAddComment={handlePlayerAddComment}
            saveAnnotationFn={async (data) => {
              const res = await fetch(`/api/client/${token}/annotation`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(data),
              });
              if (!res.ok) throw new Error("Failed to save annotation");
            }}
            addCommentFn={async (data) => {
              const res = await fetch(`/api/client/${token}/comment`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(data),
              });
              if (!res.ok) throw new Error("Failed to post comment");
              await refreshComments(token, version.id);
            }}
          />
        </div>

        {/* Comment panel — collapsible */}
        <div
          className={cn(
            "shrink-0 flex flex-col border-t md:border-t-0 md:border-l border-zinc-800 bg-zinc-900 transition-all duration-200",
            commentsOpen ? "h-64 md:h-auto md:w-72 xl:w-80" : "h-10 md:h-auto md:w-10"
          )}
        >
          {/* Collapse toggle */}
          <button
            onClick={() => setCommentsOpen((o) => !o)}
            className="flex items-center justify-center h-10 w-full border-b border-zinc-800 hover:bg-zinc-800/60 transition-colors shrink-0"
            title={commentsOpen ? "Collapse notes" : "Expand notes"}
          >
            {commentsOpen ? (
              <ChevronRight className="h-4 w-4 text-zinc-400" />
            ) : (
              <ChevronLeft className="h-4 w-4 text-zinc-400" />
            )}
            {!commentsOpen && (
              <MessageSquare className="h-4 w-4 text-zinc-400 mt-1" />
            )}
          </button>

          {commentsOpen && (
            <div className="px-4 py-3 border-b border-zinc-800 flex items-center gap-2 shrink-0">
              <MessageSquare className="h-4 w-4 text-zinc-400" />
              <h3 className="text-sm font-semibold text-white">Notes</h3>
              {comments.length > 0 && (
                <span className="text-xs text-zinc-500">({comments.length})</span>
              )}
            </div>
          )}

          {commentsOpen && <ScrollArea className="flex-1 px-4 py-3">
            {comments.length === 0 ? (
              <div className="text-center py-8 text-zinc-500 text-sm">
                <MessageSquare className="h-8 w-8 mx-auto mb-2 opacity-30" />
                <p>No notes yet.</p>
                <p className="text-xs mt-1">Pause the video and add a note at any frame.</p>
              </div>
            ) : (
              <div className="space-y-3">
                {comments.map((comment) => (
                  <div key={comment.id} className="space-y-2">
                    <div
                      className="rounded-lg bg-zinc-800/70 p-3 space-y-2 cursor-pointer hover:bg-zinc-700/70 transition-colors"
                      onClick={() => playerRef.current?.seekToFrame(comment.frameNumber)}
                      title={`Jump to frame ${comment.frameNumber}`}
                    >
                      <div className="flex items-center gap-2">
                        <Avatar className="h-5 w-5">
                          <AvatarFallback className="text-[9px] bg-zinc-700">
                            {getInitials(comment.author.name ?? comment.author.email)}
                          </AvatarFallback>
                        </Avatar>
                        <span className="text-xs text-zinc-300 font-medium">
                          {comment.author.name ?? comment.author.email.split("@")[0]}
                        </span>
                        <span className="ml-auto font-mono text-xs text-amber-400/80">
                          {frameToTimecode(comment.frameNumber, version.fps)}
                        </span>
                      </div>
                      <p className="text-sm text-zinc-200 leading-relaxed">{comment.text}</p>
                    </div>
                    {comment.replies.map((reply) => (
                      <div key={reply.id} className="ml-4 rounded-lg bg-zinc-800/40 border border-zinc-700/50 p-2.5">
                        <span className="text-xs text-zinc-400 font-medium">
                          {reply.author.name ?? "Reply"}
                        </span>
                        <p className="text-xs text-zinc-300 mt-1">{reply.text}</p>
                      </div>
                    ))}
                  </div>
                ))}
              </div>
            )}
          </ScrollArea>}

          {commentsOpen && commentFrame !== null ? (
            <div className="border-t border-zinc-800 p-3 space-y-2">
              <p className="text-xs text-zinc-500 font-mono">
                Frame {commentFrame} · {frameToTimecode(commentFrame, version.fps)}
              </p>
              <Textarea
                placeholder="Add your note..."
                value={commentText}
                onChange={(e) => setCommentText(e.target.value)}
                className="min-h-[80px] text-sm resize-none"
                autoFocus
                onKeyDown={(e) => {
                  if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmitComment();
                  if (e.key === "Escape") setCommentFrame(null);
                }}
              />
              <div className="flex gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  className="flex-1 h-8 text-xs"
                  onClick={() => { setCommentFrame(null); setCommentText(""); }}
                >
                  Cancel
                </Button>
                <Button
                  size="sm"
                  className="flex-1 h-8 text-xs gap-1"
                  onClick={handleSubmitComment}
                  disabled={!commentText.trim() || submittingComment}
                >
                  <Send className="h-3 w-3" />
                  Send
                </Button>
              </div>
            </div>
          ) : commentsOpen ? (
            <div className="border-t border-zinc-800 p-3">
              <Button
                variant="outline"
                className="w-full text-sm gap-2 h-9"
                onClick={() => {
                  playerRef.current?.pause();
                  setCommentFrame(currentFrame);
                }}
              >
                <MessageSquare className="h-4 w-4" />
                Add Note at Current Frame
              </Button>
            </div>
          ) : null}
        </div>
      </div>

      {/* Approval dialog */}
      <Dialog
        open={approvalDialog.open}
        onOpenChange={(o) => !o && setApprovalDialog({ open: false, status: null })}
      >
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>
              {approvalDialog.status === "APPROVED"
                ? "✅ Approve this version"
                : approvalDialog.status === "NEEDS_CHANGES"
                ? "✏️ Request changes"
                : "❌ Reject this version"}
            </DialogTitle>
          </DialogHeader>
          <p className="text-sm text-zinc-400">
            {approvalDialog.status === "APPROVED"
              ? "Confirm you're happy with this version. You can add an optional note below."
              : "Describe what needs to change so the team can action it quickly."}
          </p>
          <Textarea
            value={approvalNotes}
            onChange={(e) => setApprovalNotes(e.target.value)}
            placeholder={
              approvalDialog.status === "APPROVED"
                ? "Looks great! (optional)"
                : "Please describe the changes needed..."
            }
            className="min-h-[100px]"
            autoFocus
          />
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setApprovalDialog({ open: false, status: null })}
            >
              Cancel
            </Button>
            <Button
              onClick={handleSubmitApproval}
              disabled={submittingApproval}
              className={cn(
                approvalDialog.status === "APPROVED"
                  ? "bg-emerald-600 hover:bg-emerald-500 text-white"
                  : approvalDialog.status === "NEEDS_CHANGES"
                  ? "bg-orange-600 hover:bg-orange-500 text-white"
                  : "bg-red-700 hover:bg-red-600 text-white"
              )}
            >
              {submittingApproval
                ? "Submitting..."
                : approvalDialog.status === "APPROVED"
                ? "Approve"
                : approvalDialog.status === "NEEDS_CHANGES"
                ? "Request Changes"
                : "Reject"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
