"use client";

import { useState, useEffect, useCallback } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
  ChevronRight,
  Link2,
  Pencil,
  Send,
  Trash2,
  X,
} from "lucide-react";
import { toast } from "sonner";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Calendar } from "@/components/ui/calendar";
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "@/components/ui/popover";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Tooltip,
  TooltipTrigger,
  TooltipContent,
} from "@/components/ui/tooltip";
import { ActorAvatar } from "@/components/common/actor-avatar";
import type { Issue, Comment, UpdateIssueRequest } from "@multica/types";
import { StatusPicker, PriorityPicker, AssigneePicker } from "@/features/issues/components";
import { api } from "@/shared/api";
import { useAuthStore } from "@/features/auth";
import { useActorName } from "@/features/workspace";
import { useWSEvent } from "@/features/realtime";
import { useIssueStore } from "@/features/issues";
import type { CommentCreatedPayload, CommentUpdatedPayload, CommentDeletedPayload } from "@multica/types";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function timeAgo(dateStr: string): string {
  const diff = Date.now() - new Date(dateStr).getTime();
  const minutes = Math.floor(diff / 60000);
  if (minutes < 1) return "just now";
  if (minutes < 60) return `${minutes}m ago`;
  const hours = Math.floor(minutes / 60);
  if (hours < 24) return `${hours}h ago`;
  const days = Math.floor(hours / 24);
  return `${days}d ago`;
}

function shortDate(date: string | null): string {
  if (!date) return "—";
  return new Date(date).toLocaleDateString("en-US", {
    month: "short",
    day: "numeric",
  });
}

// ---------------------------------------------------------------------------
// Property row
// ---------------------------------------------------------------------------

function PropRow({
  label,
  children,
}: {
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div className="flex min-h-8 items-center gap-3 rounded-md px-2 -mx-2 hover:bg-accent/50 transition-colors">
      <span className="w-20 shrink-0 text-sm text-muted-foreground">{label}</span>
      <div className="flex min-w-0 flex-1 items-center justify-end gap-1.5 text-sm">
        {children}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Due Date Picker
// ---------------------------------------------------------------------------

function DueDatePicker({
  dueDate,
  onUpdate,
}: {
  dueDate: string | null;
  onUpdate: (updates: Partial<UpdateIssueRequest>) => void;
}) {
  const [open, setOpen] = useState(false);
  const date = dueDate ? new Date(dueDate) : undefined;
  const isOverdue = date ? date < new Date() : false;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger className="flex items-center gap-1.5 cursor-pointer rounded px-1 -mx-1 hover:bg-accent/30 transition-colors">
        {date ? (
          <span className={isOverdue ? "text-destructive" : ""}>
            {date.toLocaleDateString("en-US", { month: "short", day: "numeric" })}
          </span>
        ) : (
          <span className="text-muted-foreground">None</span>
        )}
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0" align="end">
        <Calendar
          mode="single"
          selected={date}
          onSelect={(d: Date | undefined) => {
            onUpdate({ due_date: d ? d.toISOString() : null });
            setOpen(false);
          }}
        />
        {date && (
          <div className="border-t px-3 py-2">
            <Button
              variant="ghost"
              size="xs"
              onClick={() => {
                onUpdate({ due_date: null });
                setOpen(false);
              }}
              className="text-muted-foreground hover:text-foreground"
            >
              Clear date
            </Button>
          </div>
        )}
      </PopoverContent>
    </Popover>
  );
}

// ---------------------------------------------------------------------------
// Acceptance Criteria Editor
// ---------------------------------------------------------------------------

function AcceptanceCriteriaEditor({
  criteria,
  onUpdate,
}: {
  criteria: string[];
  onUpdate: (updates: Partial<UpdateIssueRequest>) => void;
}) {
  const [newItem, setNewItem] = useState("");

  const addItem = () => {
    if (!newItem.trim()) return;
    onUpdate({ acceptance_criteria: [...criteria, newItem.trim()] });
    setNewItem("");
  };

  const removeItem = (index: number) => {
    onUpdate({ acceptance_criteria: criteria.filter((_, i) => i !== index) });
  };

  const [adding, setAdding] = useState(false);

  return (
    <div className="space-y-2">
      <h3 className="text-xs font-medium text-muted-foreground">Acceptance Criteria</h3>
      {criteria.length > 0 && (
        <div className="space-y-1">
          {criteria.map((item, i) => (
            <div key={i} className="group flex items-start gap-2 text-sm">
              <span className="mt-0.5 text-muted-foreground">&bull;</span>
              <span className="flex-1">{item}</span>
              <Button
                variant="ghost"
                size="icon-xs"
                onClick={() => removeItem(i)}
                className="opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground transition-opacity"
              >
                <X className="h-3.5 w-3.5" />
              </Button>
            </div>
          ))}
        </div>
      )}
      {(criteria.length > 0 || adding) ? (
        <form
          onSubmit={(e) => { e.preventDefault(); addItem(); }}
          className="flex items-center gap-2"
        >
          <input
            autoFocus={adding}
            value={newItem}
            onChange={(e) => setNewItem(e.target.value)}
            onBlur={() => { if (!newItem.trim()) setAdding(false); }}
            placeholder="Add criteria..."
            aria-label="Add acceptance criteria"
            className="flex-1 text-sm bg-transparent outline-none placeholder:text-muted-foreground"
          />
        </form>
      ) : (
        <Button
          variant="ghost"
          size="sm"
          className="text-muted-foreground h-7 px-2 text-xs"
          onClick={() => setAdding(true)}
        >
          + Add acceptance criteria
        </Button>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Context Refs Editor
// ---------------------------------------------------------------------------

function ContextRefsEditor({
  refs,
  onUpdate,
}: {
  refs: string[];
  onUpdate: (updates: Partial<UpdateIssueRequest>) => void;
}) {
  const [newRef, setNewRef] = useState("");

  const addRef = () => {
    if (!newRef.trim()) return;
    onUpdate({ context_refs: [...refs, newRef.trim()] });
    setNewRef("");
  };

  const removeRef = (index: number) => {
    onUpdate({ context_refs: refs.filter((_, i) => i !== index) });
  };

  const [adding, setAdding] = useState(false);

  const isUrl = (s: string) => s.startsWith("http://") || s.startsWith("https://");

  return (
    <div className="space-y-2">
      <h3 className="text-xs font-medium text-muted-foreground">Context References</h3>
      {refs.length > 0 && (
        <div className="space-y-1">
          {refs.map((ref, i) => (
            <div key={i} className="group flex items-center gap-2 text-sm">
              <Link2 className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
              {isUrl(ref) ? (
                <a href={ref} target="_blank" rel="noopener noreferrer" className="flex-1 text-info hover:underline truncate">
                  {ref}
                </a>
              ) : (
                <span className="flex-1 truncate">{ref}</span>
              )}
              <Button
                variant="ghost"
                size="icon-xs"
                onClick={() => removeRef(i)}
                className="opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-foreground transition-opacity"
              >
                <X className="h-3.5 w-3.5" />
              </Button>
            </div>
          ))}
        </div>
      )}
      {(refs.length > 0 || adding) ? (
        <form
          onSubmit={(e) => { e.preventDefault(); addRef(); }}
          className="flex items-center gap-2"
        >
          <input
            autoFocus={adding}
            value={newRef}
            onChange={(e) => setNewRef(e.target.value)}
            onBlur={() => { if (!newRef.trim()) setAdding(false); }}
            placeholder="Add reference URL..."
            aria-label="Add context reference URL"
            className="flex-1 text-sm bg-transparent outline-none placeholder:text-muted-foreground"
          />
        </form>
      ) : (
        <Button
          variant="ghost"
          size="sm"
          className="text-muted-foreground h-7 px-2 text-xs"
          onClick={() => setAdding(true)}
        >
          + Add context reference
        </Button>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Props
// ---------------------------------------------------------------------------

interface IssueDetailProps {
  issueId: string;
  showBreadcrumb?: boolean;
  onDelete?: () => void;
}

// ---------------------------------------------------------------------------
// IssueDetail
// ---------------------------------------------------------------------------

export function IssueDetail({ issueId, showBreadcrumb, onDelete }: IssueDetailProps) {
  const id = issueId;
  const router = useRouter();
  const user = useAuthStore((s) => s.user);
  const { getActorName } = useActorName();
  const [issue, setIssue] = useState<Issue | null>(null);
  const [comments, setComments] = useState<Comment[]>([]);
  const [loading, setLoading] = useState(true);
  const [commentText, setCommentText] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [deleting, setDeleting] = useState(false);
  const [editingCommentId, setEditingCommentId] = useState<string | null>(null);
  const [editContent, setEditContent] = useState("");
  const [editingTitle, setEditingTitle] = useState(false);
  const [titleDraft, setTitleDraft] = useState("");
  const [editingDesc, setEditingDesc] = useState(false);
  const [descDraft, setDescDraft] = useState("");

  // Watch the global issue store for real-time updates from other users/agents
  const storeIssue = useIssueStore((s) => s.issues.find((i) => i.id === id));

  useEffect(() => {
    if (storeIssue) {
      setIssue(storeIssue);
    }
  }, [storeIssue]);

  useEffect(() => {
    setIssue(null);
    setComments([]);
    setLoading(true);
    Promise.all([api.getIssue(id), api.listComments(id)])
      .then(([iss, cmts]) => {
        setIssue(iss);
        setComments(cmts);
      })
      .catch(console.error)
      .finally(() => setLoading(false));
  }, [id]);

  const handleSubmitComment = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!commentText.trim() || submitting || !user) return;
    const content = commentText.trim();
    const tempId = "temp-" + Date.now();
    const tempComment: Comment = {
      id: tempId,
      issue_id: id,
      author_type: "member",
      author_id: user.id,
      content,
      type: "comment",
      created_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    };
    setComments((prev) => [...prev, tempComment]);
    setCommentText("");
    setSubmitting(true);
    try {
      const comment = await api.createComment(id, content);
      setComments((prev) => prev.map((c) => (c.id === tempId ? comment : c)));
    } catch {
      setComments((prev) => prev.filter((c) => c.id !== tempId));
      toast.error("Failed to send comment");
    } finally {
      setSubmitting(false);
    }
  };

  const handleUpdateField = useCallback(
    (updates: Partial<UpdateIssueRequest>) => {
      if (!issue) return;
      const prev = issue;
      setIssue((curr) => (curr ? ({ ...curr, ...updates } as Issue) : curr));
      api.updateIssue(id, updates).catch(() => {
        setIssue(prev);
        toast.error("Failed to update issue");
      });
    },
    [issue, id],
  );

  const handleDelete = async () => {
    setDeleting(true);
    try {
      await api.deleteIssue(issue!.id);
      toast.success("Issue deleted");
      if (onDelete) onDelete();
      else router.push("/issues");
    } catch {
      toast.error("Failed to delete issue");
      setDeleting(false);
    }
  };

  const startEditComment = (c: Comment) => {
    setEditingCommentId(c.id);
    setEditContent(c.content);
  };

  const handleSaveEditComment = async () => {
    if (!editingCommentId || !editContent.trim()) return;
    try {
      const updated = await api.updateComment(editingCommentId, editContent.trim());
      setComments((prev) => prev.map((c) => (c.id === updated.id ? updated : c)));
      setEditingCommentId(null);
    } catch {
      toast.error("Failed to update comment");
    }
  };

  const handleDeleteComment = async (commentId: string) => {
    try {
      await api.deleteComment(commentId);
      setComments((prev) => prev.filter((c) => c.id !== commentId));
    } catch {
      toast.error("Failed to delete comment");
    }
  };

  // Real-time comment updates
  useWSEvent(
    "comment:created",
    useCallback((payload: unknown) => {
      const { comment } = payload as CommentCreatedPayload;
      if (comment.issue_id !== id) return;
      // Skip own comments — already added locally via API response
      if (comment.author_type === "member" && comment.author_id === user?.id) return;
      setComments((prev) => {
        if (prev.some((c) => c.id === comment.id)) return prev;
        return [...prev, comment];
      });
    }, [id, user?.id]),
  );

  useWSEvent(
    "comment:updated",
    useCallback((payload: unknown) => {
      const { comment } = payload as CommentUpdatedPayload;
      if (comment.issue_id === id) {
        setComments((prev) => prev.map((c) => (c.id === comment.id ? comment : c)));
      }
    }, [id]),
  );

  useWSEvent(
    "comment:deleted",
    useCallback((payload: unknown) => {
      const { comment_id, issue_id } = payload as CommentDeletedPayload;
      if (issue_id === id) {
        setComments((prev) => prev.filter((c) => c.id !== comment_id));
      }
    }, [id]),
  );

  if (loading) {
    return (
      <div className="flex flex-1 min-h-0 items-center justify-center text-sm text-muted-foreground">
        Loading...
      </div>
    );
  }

  if (!issue) {
    return (
      <div className="flex flex-1 min-h-0 items-center justify-center text-sm text-muted-foreground">
        Issue not found
      </div>
    );
  }

  return (
    <div className="flex flex-1 min-h-0">
      {/* LEFT: Content area */}
      <div className="flex-1 overflow-y-auto">
        {/* Header bar */}
        {showBreadcrumb !== false && (
          <div className="sticky top-0 z-10 flex h-11 items-center justify-between border-b bg-background px-6 text-sm">
            <div className="flex items-center gap-1.5">
              <Link
                href="/issues"
                className="text-muted-foreground hover:text-foreground transition-colors"
              >
                Issues
              </Link>
              <ChevronRight className="h-3 w-3 text-muted-foreground/50" />
              <span className="truncate text-muted-foreground">{issue.id.slice(0, 8)}</span>
            </div>
            <AlertDialog>
              <AlertDialogTrigger
                render={<Button variant="ghost" size="icon-xs" className="text-muted-foreground hover:bg-destructive/10 hover:text-destructive" />}
              >
                <Trash2 className="h-4 w-4" />
              </AlertDialogTrigger>
              <AlertDialogContent>
                <AlertDialogHeader>
                  <AlertDialogTitle>Delete issue</AlertDialogTitle>
                  <AlertDialogDescription>
                    This will permanently delete this issue and all its comments. This action cannot be undone.
                  </AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                  <AlertDialogCancel>Cancel</AlertDialogCancel>
                  <AlertDialogAction
                    onClick={handleDelete}
                    disabled={deleting}
                    className="bg-destructive text-white hover:bg-destructive/90"
                  >
                    {deleting ? "Deleting..." : "Delete"}
                  </AlertDialogAction>
                </AlertDialogFooter>
              </AlertDialogContent>
            </AlertDialog>
          </div>
        )}

        {/* Content */}
        <div className="mx-auto w-full max-w-3xl px-8 py-8">
          <div className="mb-1 text-sm text-muted-foreground">{issue.id.slice(0, 8)}</div>

          {editingTitle ? (
            <Input
              autoFocus
              value={titleDraft}
              onChange={(e) => setTitleDraft(e.target.value)}
              onBlur={() => {
                if (titleDraft.trim()) handleUpdateField({ title: titleDraft.trim() });
                setEditingTitle(false);
              }}
              onKeyDown={(e) => {
                if (e.key === "Enter") {
                  if (titleDraft.trim()) handleUpdateField({ title: titleDraft.trim() });
                  setEditingTitle(false);
                } else if (e.key === "Escape") {
                  setEditingTitle(false);
                }
              }}
              className="text-xl font-semibold leading-snug tracking-tight"
            />
          ) : (
            <h1
              className="text-xl font-semibold leading-snug tracking-tight cursor-pointer hover:bg-accent/50 rounded px-1 -mx-1"
              onClick={() => { setTitleDraft(issue.title); setEditingTitle(true); }}
            >
              {issue.title}
            </h1>
          )}

          {editingDesc ? (
            <Textarea
              autoFocus
              value={descDraft}
              onChange={(e) => setDescDraft(e.target.value)}
              onBlur={() => {
                handleUpdateField({ description: descDraft.trim() || undefined });
                setEditingDesc(false);
              }}
              onKeyDown={(e) => {
                if (e.key === "Escape") setEditingDesc(false);
              }}
              rows={4}
              className="mt-5 text-sm leading-relaxed resize-none"
            />
          ) : (
            <div
              className="mt-5 text-sm leading-relaxed whitespace-pre-wrap cursor-pointer hover:bg-accent/50 rounded px-1 -mx-1"
              onClick={() => { setDescDraft(issue.description || ""); setEditingDesc(true); }}
            >
              {issue.description ? (
                <span className="text-foreground/85">{issue.description}</span>
              ) : (
                <span className="text-muted-foreground">Add description...</span>
              )}
            </div>
          )}

          <div className="space-y-4 mt-4">
            <AcceptanceCriteriaEditor
              criteria={issue.acceptance_criteria}
              onUpdate={handleUpdateField}
            />
            <ContextRefsEditor
              refs={issue.context_refs}
              onUpdate={handleUpdateField}
            />
          </div>

          <div className="my-8 border-t" />

          {/* Activity / Comments */}
          <div>
            <h2 className="text-sm font-medium">Activity</h2>

            <div className="mt-4">
              {comments.map((comment) => {
                const isOwn = comment.author_type === "member" && comment.author_id === user?.id;
                return (
                  <div key={comment.id} className={`group relative py-3${comment.id.startsWith("temp-") ? " opacity-60" : ""}`}>
                    <div className="flex items-center gap-2.5">
                      <ActorAvatar
                        actorType={comment.author_type}
                        actorId={comment.author_id}
                        size={28}
                      />
                      <span className="text-sm font-medium">
                        {getActorName(comment.author_type, comment.author_id)}
                      </span>
                      <Tooltip>
                        <TooltipTrigger
                          render={
                            <span className="text-xs text-muted-foreground cursor-default">
                              {timeAgo(comment.created_at)}
                            </span>
                          }
                        />
                        <TooltipContent side="top">
                          {new Date(comment.created_at).toLocaleString()}
                        </TooltipContent>
                      </Tooltip>
                      {isOwn && (
                        <div className="ml-auto flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
                          <Button
                            variant="ghost"
                            size="icon-xs"
                            onClick={() => startEditComment(comment)}
                            className="text-muted-foreground hover:text-foreground"
                          >
                            <Pencil className="h-3 w-3" />
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon-xs"
                            onClick={() => handleDeleteComment(comment.id)}
                            className="text-muted-foreground hover:text-destructive"
                          >
                            <Trash2 className="h-3 w-3" />
                          </Button>
                        </div>
                      )}
                    </div>
                    {editingCommentId === comment.id ? (
                      <form onSubmit={(e) => { e.preventDefault(); handleSaveEditComment(); }} className="mt-2 pl-9.5">
                        <input
                          autoFocus
                          value={editContent}
                          onChange={(e) => setEditContent(e.target.value)}
                          aria-label="Edit comment"
                          className="w-full text-sm bg-transparent border-b outline-none"
                          onKeyDown={(e) => { if (e.key === "Escape") setEditingCommentId(null); }}
                        />
                      </form>
                    ) : (
                      <div className="mt-2 pl-9.5 text-sm leading-relaxed text-foreground/85 whitespace-pre-wrap">
                        {comment.content}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>

            {/* Comment input */}
            <form onSubmit={handleSubmitComment} className="mt-2 border-t pt-4">
              <div className="flex items-center gap-2">
                <Input
                  type="text"
                  value={commentText}
                  onChange={(e) => setCommentText(e.target.value)}
                  placeholder="Leave a comment..."
                  className="flex-1 text-sm"
                />
                <Button
                  type="submit"
                  size="icon"
                  disabled={!commentText.trim() || submitting}
                >
                  <Send className="h-3.5 w-3.5" />
                </Button>
              </div>
            </form>
          </div>
        </div>
      </div>

      {/* RIGHT: Properties sidebar */}
      <div className="w-60 shrink-0 overflow-y-auto border-l">
        <div className="p-4">
          <div className="mb-2 text-xs font-medium text-muted-foreground">
            Properties
          </div>

          <div className="space-y-0.5">
            <PropRow label="Status">
              <StatusPicker status={issue.status} onUpdate={handleUpdateField} />
            </PropRow>

            <PropRow label="Priority">
              <PriorityPicker priority={issue.priority} onUpdate={handleUpdateField} />
            </PropRow>

            <PropRow label="Assignee">
              <AssigneePicker
                assigneeType={issue.assignee_type}
                assigneeId={issue.assignee_id}
                onUpdate={handleUpdateField}
              />
            </PropRow>

            <PropRow label="Due date">
              <DueDatePicker dueDate={issue.due_date} onUpdate={handleUpdateField} />
            </PropRow>

            <PropRow label="Created by">
              <ActorAvatar
                actorType={issue.creator_type}
                actorId={issue.creator_id}
                size={18}
              />
              <span>{getActorName(issue.creator_type, issue.creator_id)}</span>
            </PropRow>
          </div>

          <div className="mt-4 border-t pt-3 space-y-0.5">
            <PropRow label="Created">
              <span className="text-muted-foreground">{shortDate(issue.created_at)}</span>
            </PropRow>
            <PropRow label="Updated">
              <span className="text-muted-foreground">{shortDate(issue.updated_at)}</span>
            </PropRow>
          </div>
        </div>
      </div>
    </div>
  );
}
