"use client";

import { useEffect, useMemo, useState } from "react";

import { ExternalLink, Loader2, MessageSquarePlus, Pencil, UserPlus, XCircle } from "lucide-react";

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Markdown } from "@/components/atoms/Markdown";
import {
  getForgejoIssue,
  type ForgejoIssue,
  type ForgejoIssueDetail,
} from "@/lib/api-forgejo";
import { AssignIssueAgentDialog } from "@/components/git/AssignIssueAgentDialog";
import { CloseForgejoIssueDialog } from "@/components/git/CloseForgejoIssueDialog";
import { EditForgejoIssueDialog } from "@/components/git/EditForgejoIssueDialog";
import { PostForgejoCommentDialog } from "@/components/git/PostForgejoCommentDialog";

type ForgejoIssueDetailDialogProps = {
  issue: ForgejoIssue | null;
  repositoryName: string;
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onRefresh?: () => void;
  canClose?: boolean;
};

const formatDateTime = (value: string | null | undefined): string => {
  if (!value) return "—";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString(undefined, {
    dateStyle: "medium",
    timeStyle: "short",
  });
};

const objectList = (value: unknown): Record<string, unknown>[] => {
  if (!Array.isArray(value)) return [];
  return value.filter(
    (item): item is Record<string, unknown> =>
      typeof item === "object" && item !== null,
  );
};

const asString = (value: unknown): string | null =>
  typeof value === "string" && value.trim() ? value : null;

export function ForgejoIssueDetailDialog({
  issue,
  repositoryName,
  open,
  onOpenChange,
  onRefresh,
  canClose = false,
}: ForgejoIssueDetailDialogProps) {
  const [detail, setDetail] = useState<ForgejoIssueDetail | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [activeTab, setActiveTab] = useState("overview");

  const [isCommentDialogOpen, setIsCommentDialogOpen] = useState(false);
  const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
  const [isCloseIssueDialogOpen, setIsCloseIssueDialogOpen] = useState(false);
  const [isAssignDialogOpen, setIsAssignDialogOpen] = useState(false);

  const loadDetail = (id: string) => {
    let cancelled = false;
    setIsLoading(true);
    setError(null);
    (async () => {
      try {
        const result = await getForgejoIssue(id);
        if (!cancelled) setDetail(result);
      } catch (err) {
        if (!cancelled)
          setError(
            err instanceof Error
              ? err.message
              : "Could not load issue details from Pipeline.",
          );
      } finally {
        if (!cancelled) setIsLoading(false);
      }
    })();
    return () => { cancelled = true; };
  };

  useEffect(() => {
    if (!open || !issue) return;
    return loadDetail(issue.id);
  }, [issue, open]);

  const comments = useMemo(
    () => objectList(detail?.forgejo_comments_payload),
    [detail?.forgejo_comments_payload],
  );
  const timeline = useMemo(
    () => objectList(detail?.forgejo_timeline_payload),
    [detail?.forgejo_timeline_payload],
  );
  const reactions = useMemo(
    () => objectList(detail?.forgejo_reactions_payload),
    [detail?.forgejo_reactions_payload],
  );

  if (!issue) return null;

  const active = detail ?? issue;
  const body = detail?.body ?? issue.body ?? issue.body_preview ?? "";
  const stateVariant = active.state === "open" ? "success" : "default";
  const showCloseIssue = canClose && active.state === "open";

  const handleCloseIssueSuccess = () => {
    if (detail) setDetail({ ...detail, state: "closed" });
    if (issue) loadDetail(issue.id);
    onRefresh?.();
  };

  const handleCommentSuccess = () => {
    if (issue) loadDetail(issue.id);
    onRefresh?.();
  };

  const handleEditSuccess = (updated: {
    title: string;
    body: string | null;
    state: string;
  }) => {
    if (detail) {
      setDetail({
        ...detail,
        title: updated.title,
        body: updated.body,
        state: updated.state,
      });
    }
    if (issue) loadDetail(issue.id);
    onRefresh?.();
  };

  return (
    <>
      <Dialog open={open} onOpenChange={onOpenChange}>
        <DialogContent className="max-w-4xl">
          <DialogHeader className="gap-3">
            <div className="grid gap-3 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-start">
              <div className="min-w-0 space-y-2">
                <DialogTitle className="break-words text-base sm:text-lg">
                  {active.title}
                </DialogTitle>
                <DialogDescription className="flex flex-wrap items-center gap-2 text-xs sm:text-sm">
                  <span className="font-medium text-strong">
                    {repositoryName}
                  </span>
                  <span className="font-mono">
                    #{active.forgejo_issue_number}
                  </span>
                  <Badge variant={stateVariant}>{active.state}</Badge>
                  <span>Opened {formatDateTime(active.forgejo_created_at)}</span>
                  <span>Updated {formatDateTime(active.forgejo_updated_at)}</span>
                </DialogDescription>
              </div>
              {showCloseIssue ? (
                <Button
                  variant="outline"
                  size="sm"
                  className="h-9 justify-self-end gap-2 rounded-xl border-[color:rgba(248,113,113,0.45)] px-3 text-xs font-semibold text-[color:var(--danger)] hover:bg-[color:rgba(248,113,113,0.08)]"
                  onClick={() => setIsCloseIssueDialogOpen(true)}
                >
                  <XCircle className="h-3.5 w-3.5" />
                  Close Issue
                </Button>
              ) : null}
            </div>
            <div className="flex flex-wrap items-center gap-2 sm:justify-end">
              <Button
                variant="outline"
                size="sm"
                className="h-9 gap-2 rounded-xl px-3 text-xs font-semibold"
                onClick={() => setIsEditDialogOpen(true)}
              >
                <Pencil className="h-3.5 w-3.5" />
                Edit
              </Button>
              <Button
                variant="outline"
                size="sm"
                className="h-9 gap-2 rounded-xl px-3 text-xs font-semibold"
                onClick={() => {
                  setActiveTab("comments");
                  setIsCommentDialogOpen(true);
                }}
              >
                <MessageSquarePlus className="h-3.5 w-3.5" />
                Comment
              </Button>
              <Button
                variant="outline"
                size="sm"
                className="h-9 gap-2 rounded-xl px-3 text-xs font-semibold"
                onClick={() => setIsAssignDialogOpen(true)}
              >
                <UserPlus className="h-3.5 w-3.5" />
                Assign Agent
              </Button>
              <a
                href={active.html_url}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex h-9 items-center gap-2 rounded-xl border border-[color:var(--border)] px-3 text-xs font-semibold text-muted transition hover:border-[color:var(--accent)] hover:text-[color:var(--accent)]"
              >
                Open in Forgejo
                <ExternalLink className="h-3.5 w-3.5" />
              </a>
            </div>
          </DialogHeader>

          {isLoading ? (
            <div className="flex items-center gap-2 rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4 text-sm text-muted">
              <Loader2 className="h-4 w-4 animate-spin text-[color:var(--accent)]" />
              Loading issue details…
            </div>
          ) : null}

          {error ? (
            <div className="rounded-xl border border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.08)] p-3 text-sm text-[color:var(--danger)]">
              {error}
            </div>
          ) : null}

          <Tabs value={activeTab} onValueChange={setActiveTab}>
            <TabsList>
              <TabsTrigger value="overview">Overview</TabsTrigger>
              <TabsTrigger value="comments">
                Comments ({comments.length})
              </TabsTrigger>
              <TabsTrigger value="timeline">
                Timeline ({timeline.length})
              </TabsTrigger>
              <TabsTrigger value="reactions">
                Reactions ({reactions.length})
              </TabsTrigger>
            </TabsList>

            <TabsContent value="overview">
              <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4">
                {body ? (
                  <Markdown content={body} variant="comment" />
                ) : (
                  <p className="text-sm text-muted">No issue body provided.</p>
                )}
              </div>
            </TabsContent>

            <TabsContent value="comments">
              <div className="space-y-3">
                {comments.length === 0 ? (
                  <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4 text-sm text-muted">
                    No comments yet.{" "}
                    <button
                      type="button"
                      className="text-[color:var(--accent)] underline-offset-2 hover:underline"
                      onClick={() => setIsCommentDialogOpen(true)}
                    >
                      Post the first one.
                    </button>
                  </div>
                ) : (
                  <>
                    {comments.map((comment, idx) => {
                      const login =
                        asString(
                          comment.user &&
                            (comment.user as Record<string, unknown>).login,
                        ) ?? "Unknown";
                      const bodyText = asString(comment.body) ?? "";
                      return (
                        <article
                          key={String(comment.id ?? idx)}
                          className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4"
                        >
                          <div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-muted">
                            <span className="font-medium text-strong">
                              {login}
                            </span>
                            <span>
                              {formatDateTime(asString(comment.created_at))}
                            </span>
                          </div>
                          {bodyText ? (
                            <Markdown content={bodyText} variant="comment" />
                          ) : (
                            <p className="text-sm text-muted">
                              No comment text.
                            </p>
                          )}
                        </article>
                      );
                    })}
                    <Button
                      variant="outline"
                      size="sm"
                      className="w-full gap-2"
                      onClick={() => setIsCommentDialogOpen(true)}
                    >
                      <MessageSquarePlus className="h-4 w-4" />
                      Post a comment
                    </Button>
                  </>
                )}
              </div>
            </TabsContent>

            <TabsContent value="timeline">
              <div className="space-y-2">
                {timeline.length === 0 ? (
                  <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4 text-sm text-muted">
                    No timeline events found.
                  </div>
                ) : (
                  timeline.map((event, idx) => {
                    const label =
                      asString(event.type) ??
                      asString(event.action) ??
                      asString(event.event) ??
                      "event";
                    const actor =
                      asString(
                        event.user &&
                          (event.user as Record<string, unknown>).login,
                      ) ?? "system";
                    return (
                      <div
                        key={String(event.id ?? idx)}
                        className="rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-muted)] px-3 py-2 text-sm"
                      >
                        <span className="font-medium text-strong">{label}</span>{" "}
                        <span className="text-muted">by {actor}</span>
                        <span className="ml-2 text-xs text-muted">
                          {formatDateTime(asString(event.created_at))}
                        </span>
                      </div>
                    );
                  })
                )}
              </div>
            </TabsContent>

            <TabsContent value="reactions">
              <div className="space-y-2">
                {reactions.length === 0 ? (
                  <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4 text-sm text-muted">
                    No reactions on this issue.
                  </div>
                ) : (
                  reactions.map((reaction, idx) => {
                    const content =
                      asString(reaction.content) ?? "reaction";
                    const login =
                      asString(
                        reaction.user &&
                          (reaction.user as Record<string, unknown>).login,
                      ) ?? "Unknown";
                    return (
                      <div
                        key={String(reaction.id ?? idx)}
                        className="flex items-center justify-between rounded-lg border border-[color:var(--border)] bg-[color:var(--surface-muted)] px-3 py-2 text-sm"
                      >
                        <span className="font-medium text-strong">
                          {content}
                        </span>
                        <span className="text-xs text-muted">{login}</span>
                      </div>
                    );
                  })
                )}
              </div>
            </TabsContent>
          </Tabs>

          <div className="mt-4 flex justify-end">
            <Button variant="outline" onClick={() => onOpenChange(false)}>
              Close Window
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <AssignIssueAgentDialog
        issue={issue}
        repositoryName={repositoryName}
        open={isAssignDialogOpen}
        onOpenChange={setIsAssignDialogOpen}
        onSuccess={() => {
          setIsAssignDialogOpen(false);
          onRefresh?.();
        }}
      />

      <CloseForgejoIssueDialog
        issue={issue}
        repositoryName={repositoryName}
        open={isCloseIssueDialogOpen}
        onOpenChange={setIsCloseIssueDialogOpen}
        onCloseSuccess={handleCloseIssueSuccess}
      />

      <PostForgejoCommentDialog
        issue={issue}
        repositoryName={repositoryName}
        open={isCommentDialogOpen}
        onOpenChange={setIsCommentDialogOpen}
        onSuccess={handleCommentSuccess}
      />

      <EditForgejoIssueDialog
        issue={detail ?? issue}
        repositoryName={repositoryName}
        open={isEditDialogOpen}
        onOpenChange={setIsEditDialogOpen}
        onSuccess={handleEditSuccess}
      />
    </>
  );
}
