import { CircleCheck, CircleDot } from "lucide-react";
import type { Metadata } from "next";
import { Suspense } from "react";
import { notFound, redirect } from "next/navigation";

import { UserLink } from "@/components/users/user-link";
import { FromNowHoverCard } from "@/components/from-now-card";
import { EditableField } from "@/components/issues/editable-field";
import { Badge } from "@/components/ui/badge";
import {
  ThreadSubscription,
  ThreadSubscriptionSkeleton,
} from "@/components/notifications/thread-subscription";
import { createServerClient } from "@/lib/api/server";
import { cn } from "@/lib/utils";

export async function generateMetadata({
  params,
}: LayoutProps<"/[username]/[repo]/issues/[number]">): Promise<Metadata> {
  const { username, repo, number } = await params;
  const client = await createServerClient();
  const { data } = await client.GET(
    "/api/repositories/{username}/{repo}/issues/{number}",
    { params: { path: { username, repo, number: Number(number) } } },
  );

  const title = data
    ? `${data.title} · Issue #${data.number} · ${username}/${repo}`
    : `Issue #${number} · ${username}/${repo}`;

  return { title, openGraph: { title } };
}

export default async function IssueLayout({
  params,
  children,
}: LayoutProps<"/[username]/[repo]/issues/[number]">) {
  const { username, repo, number } = await params;

  const client = await createServerClient();
  const issue = await client.GET(
    "/api/repositories/{username}/{repo}/issues/{number}",
    { params: { path: { username, repo, number: Number(number) } } },
  );

  if (issue.response.status === 404) notFound();
  if (!issue.data) {
    throw new Error(`Failed to load issue #${number}`);
  }
  // `#N` always links to `/issues/N`, whichever kind N turns out to be.
  if (issue.data.isPullRequest)
    redirect(`/${username}/${repo}/pulls/${number}`);

  // Server-computed: the author, or whoever can write to the repository.
  const canEdit = issue.data.viewerCanEdit;
  const Icon = issue.data.state === "open" ? CircleDot : CircleCheck;

  return (
    <div className="flex flex-col gap-4">
      <div className="flex flex-col gap-2">
        <EditableField
          username={username}
          repo={repo}
          number={issue.data.number}
          noun="issue"
          field="title"
          value={issue.data.title}
          canEdit={canEdit}
        >
          <h1 className="text-xl font-semibold">
            {issue.data.title}{" "}
            <span className="font-normal text-muted-foreground">
              #{issue.data.number}
            </span>
          </h1>
        </EditableField>

        <div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
          <Badge
            className={cn(
              "gap-1.5 rounded-full capitalize",
              issue.data.state === "closed" && "bg-red-600 text-white",
              issue.data.state === "open" && "bg-emerald-600 text-white",
            )}
          >
            <Icon className="size-3.5" />
            {issue.data.state}
          </Badge>

          <span>
            <UserLink username={issue.data.authorUsername} /> opened this issue{" "}
            <FromNowHoverCard date={issue.data.createdAt} />
          </span>

          {issue.data.state === "closed" && issue.data.closedByUsername && (
            <span>
              · closed by {issue.data.closedByUsername}{" "}
              {issue.data.closedAt && (
                <FromNowHoverCard date={issue.data.closedAt} />
              )}
            </span>
          )}

          <div className="ml-auto">
            <Suspense fallback={<ThreadSubscriptionSkeleton />}>
              <ThreadSubscription
                username={username}
                repo={repo}
                number={Number(number)}
              />
            </Suspense>
          </div>
        </div>
      </div>

      {children}
    </div>
  );
}
