import {PortableText, type PortableTextComponents} from "@portabletext/react";
import {AlertCircle, CircleCheck, CircleDashed, Info} from "lucide-react";
import Image from "next/image";
import type {ReactNode} from "react";

import {Accordion, AccordionContent, AccordionItem, AccordionTrigger} from "@/components/ui/accordion";
import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert";
import {Badge} from "@/components/ui/badge";
import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card";
import {urlFor} from "@/lib/sanity/client";
import type {
  ChapterBodyBlock,
  DropdownBlock,
  ImageLayoutBlock,
  InfoBoxBlock,
  TimelineBlock,
  TimelineItemBlock,
} from "@/lib/sanity/types";
import {cn} from "@/lib/utils";

type Props = {
  value: ChapterBodyBlock[];
};

const components: PortableTextComponents = {
  block: {
    h2: ({children}) => <h2 className="mt-8 text-balance text-2xl font-semibold">{children}</h2>,
    h3: ({children}) => <h3 className="mt-6 text-balance text-xl font-semibold">{children}</h3>,
    normal: ({children}) => <p className="mt-4 leading-8 text-foreground/90">{children}</p>,
    blockquote: ({children}) => (
      <blockquote className="mt-4 border-l-4 border-primary/30 pl-4 italic text-muted-foreground">
        {children}
      </blockquote>
    ),
  },
  list: {
    bullet: ({children}) => <ul className="mt-4 list-disc space-y-2 pl-6">{children}</ul>,
    number: ({children}) => <ol className="mt-4 list-decimal space-y-2 pl-6">{children}</ol>,
  },
  types: {
    timelineBlock: ({value}) => {
      const block = (value || {}) as TimelineBlock;
      const items = block.items || [];
      return (
      <Card className="mt-8 overflow-hidden border-border/80 bg-card">
        <CardHeader className="pb-3">
          <div className="flex items-center gap-2">
            <Badge variant="secondary">Timeline</Badge>
            <CardTitle className="text-lg">{block.heading || "Timeline"}</CardTitle>
          </div>
        </CardHeader>
        <CardContent>
          <ol className="space-y-3">
          {items.map((item: TimelineItemBlock, index: number) => (
            <li
              key={item?._key || `${item?.title}-${index}`}
              className="rounded-lg border border-border/80 bg-muted/40 p-3"
            >
              <p className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
                <CircleDashed className="size-4" />
                {item?.label}
              </p>
              <p className="mt-1 text-base font-semibold">{item?.title}</p>
              {item?.description ? <p className="mt-1 leading-7 text-foreground/85">{item.description}</p> : null}
            </li>
          ))}
          </ol>
        </CardContent>
      </Card>
      );
    },
    infoboxBlock: ({value}) => {
      const block = (value || {}) as InfoBoxBlock;
      const variant = block.variant || "info";
      const iconByVariant: Record<string, ReactNode> = {
        info: <Info className="size-4" />,
        success: <CircleCheck className="size-4" />,
        warning: <AlertCircle className="size-4" />,
        error: <AlertCircle className="size-4" />,
      };

      return (
        <Alert
          className={cn("mt-8", {
            "border-[var(--medical-info)] bg-[color-mix(in_oklch,var(--medical-info),white_65%)] text-foreground":
              variant === "info",
            "border-[var(--medical-calm)] bg-[color-mix(in_oklch,var(--medical-calm),white_55%)] text-foreground":
              variant === "success",
            "border-[var(--medical-warning)] bg-[color-mix(in_oklch,var(--medical-warning),white_55%)] text-foreground":
              variant === "warning",
            "border-[var(--medical-critical)] bg-[color-mix(in_oklch,var(--medical-critical),white_65%)] text-foreground":
              variant === "error",
          })}
        >
          {iconByVariant[variant] ?? <Info className="size-4" />}
          <AlertTitle>{block.title}</AlertTitle>
          <AlertDescription className="mt-2 text-inherit/90">
            <PortableText value={block.body || []} components={components} />
          </AlertDescription>
        </Alert>
      );
    },
    dropdownBlock: ({value}) => {
      const block = (value || {}) as DropdownBlock;
      const sectionValue = block._key || block.question || "dropdown-item";
      return (
        <Accordion
          defaultValue={block.initiallyOpen ? [sectionValue] : []}
          className="mt-6 rounded-lg border border-border px-4"
        >
          <AccordionItem value={sectionValue} className="border-none">
            <AccordionTrigger className="cursor-pointer text-left font-semibold">
              {block.question || "Details"}
            </AccordionTrigger>
            <AccordionContent className="pb-4">
              <PortableText value={block.answer || []} components={components} />
            </AccordionContent>
          </AccordionItem>
        </Accordion>
      );
    },
    imageLayoutBlock: ({value}) => {
      const block = (value || {}) as ImageLayoutBlock;
      const images = block.images || [];
      return (
        <section className="mt-8">
        <div
          className={
            block.layout === "twoColumn"
              ? "grid gap-4 md:grid-cols-2"
              : block.layout === "gallery"
                ? "grid gap-4 sm:grid-cols-2 lg:grid-cols-3"
                : "space-y-4"
          }
        >
          {images.map((item, index: number) => (
            <figure key={item?._key || `${item?.alt}-${index}`} className="space-y-2">
              {item?.image ? (
                <Image
                  src={urlFor(item.image).width(1200).auto("format").url()}
                  alt={item?.alt || ""}
                  width={1200}
                  height={800}
                  className="h-auto w-full rounded-lg border border-border object-cover"
                />
              ) : null}
              {item?.caption ? <figcaption className="text-sm text-muted-foreground">{item.caption}</figcaption> : null}
            </figure>
          ))}
        </div>
      </section>
      );
    },
  },
};

export function PortableContent({value}: Props) {
  return <PortableText value={value} components={components} />;
}
