import {
  IconAlertTriangle,
  IconBulb,
  IconChevronDown,
  IconInfoCircle,
  IconLink,
} from "@tabler/icons-react";
import dynamic from "next/dynamic";
import Image from "next/image";
import type { ComponentPropsWithoutRef } from "react";
import { CopyButton } from "@/components/blog/copy-button";
import { FAQItem as FAQAccordionItem } from "@/components/ui/faq-item";
import { Link } from "@/i18n/navigation";

const chartLoadingFallback = (
  <div className="h-[400px] w-full animate-pulse rounded-lg bg-white/5" />
);

const ComparisonChart = dynamic(
  () =>
    import("./comparison-chart").then((m) => ({ default: m.ComparisonChart })),
  { loading: () => chartLoadingFallback }
);
const RadarComparisonChart = dynamic(
  () =>
    import("./radar-comparison-chart").then((m) => ({
      default: m.RadarComparisonChart,
    })),
  { loading: () => chartLoadingFallback }
);
const TrendLineChart = dynamic(
  () =>
    import("./trend-line-chart").then((m) => ({ default: m.TrendLineChart })),
  { loading: () => chartLoadingFallback }
);
const CostChart = dynamic(
  () => import("./cost-chart").then((m) => ({ default: m.CostChart })),
  { loading: () => chartLoadingFallback }
);
const PerformanceChart = dynamic(
  () =>
    import("./performance-chart").then((m) => ({
      default: m.PerformanceChart,
    })),
  { loading: () => chartLoadingFallback }
);

function slugify(text: string): string {
  return text
    .toLowerCase()
    .replace(/[^a-z0-9\s-]/g, "")
    .replace(/\s+/g, "-")
    .replace(/-+/g, "-")
    .trim();
}

function HeadingAnchor({
  as: Tag,
  children,
  ...props
}: ComponentPropsWithoutRef<"h1"> & { as: "h1" | "h2" | "h3" | "h4" }) {
  const text = typeof children === "string" ? children : "";
  const id = slugify(text);

  return (
    <Tag className="group relative scroll-mt-24" id={id} {...props}>
      <a
        aria-label={`Link to ${text}`}
        className="absolute top-1/2 -left-6 -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:opacity-100"
        href={`#${id}`}
      >
        <IconLink className="text-neutral-500 hover:text-[#fd105e]" size={18} />
      </a>
      {children}
    </Tag>
  );
}

interface CalloutProps {
  children: React.ReactNode;
  variant?: "info" | "warning" | "tip";
}

function Callout({ variant = "info", children }: CalloutProps) {
  const config = {
    info: {
      icon: <IconInfoCircle size={20} />,
      border: "border-blue-500/30",
      bg: "bg-blue-500/5",
      iconColor: "text-blue-400",
    },
    warning: {
      icon: <IconAlertTriangle size={20} />,
      border: "border-amber-500/30",
      bg: "bg-amber-500/5",
      iconColor: "text-amber-400",
    },
    tip: {
      icon: <IconBulb size={20} />,
      border: "border-emerald-500/30",
      bg: "bg-emerald-500/5",
      iconColor: "text-emerald-400",
    },
  };

  const { icon, border, bg, iconColor } = config[variant];

  return (
    <aside
      className={`my-6 flex gap-3 rounded-lg border ${border} ${bg} p-4`}
      role="note"
    >
      <span className={`mt-0.5 shrink-0 ${iconColor}`}>{icon}</span>
      <div className="text-neutral-200 text-sm leading-relaxed">{children}</div>
    </aside>
  );
}

interface HowToStep {
  name: string;
  text: string;
}

function HowTo({
  name,
  description,
  steps,
  totalTime,
}: {
  name: string;
  description?: string;
  steps: HowToStep[];
  totalTime?: string;
}) {
  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "HowTo",
    name,
    ...(description && { description }),
    ...(totalTime && { totalTime }),
    step: steps.map((step, i) => ({
      "@type": "HowToStep",
      position: i + 1,
      name: step.name,
      text: step.text,
    })),
  };

  return (
    <details className="group my-8 rounded-2xl border border-white/10 bg-white/[0.02]">
      <script
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
        type="application/ld+json"
      />
      <summary className="flex cursor-pointer items-center justify-between p-5 font-bold text-base text-white [&::-webkit-details-marker]:hidden">
        <span>
          {name} ({steps.length} etapes)
        </span>
        <IconChevronDown
          className="shrink-0 text-neutral-500 transition-transform duration-200 group-open:rotate-180"
          size={16}
          stroke={2}
        />
      </summary>
      <ol className="grid grid-cols-1 gap-2 px-5 pb-5 sm:grid-cols-2">
        {steps.map((step, i) => (
          <li className="flex items-center gap-3" key={step.name}>
            <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[#fd105e]/10 font-bold text-[#fd105e] text-sm">
              {i + 1}
            </span>
            <p className="text-neutral-300 text-sm">
              <span className="font-medium text-white">{step.name}</span>
              {" — "}
              {step.text}
            </p>
          </li>
        ))}
      </ol>
    </details>
  );
}

function FAQBox({ children }: { children: React.ReactNode }) {
  return (
    <div className="my-8 divide-y divide-white/10 rounded-2xl border border-white/10 bg-white/[0.02]">
      {children}
    </div>
  );
}

// biome-ignore lint/suspicious/noExplicitAny: MDX components accept varied props
export const mdxComponents: Record<string, React.ComponentType<any>> = {
  h1: (props: ComponentPropsWithoutRef<"h1">) => (
    <HeadingAnchor as="h1" {...props} />
  ),
  h2: (props: ComponentPropsWithoutRef<"h2">) => (
    <HeadingAnchor as="h2" {...props} />
  ),
  h3: (props: ComponentPropsWithoutRef<"h3">) => (
    <HeadingAnchor as="h3" {...props} />
  ),
  h4: (props: ComponentPropsWithoutRef<"h4">) => (
    <HeadingAnchor as="h4" {...props} />
  ),

  a: ({
    href,
    children,
    ...props
  }: ComponentPropsWithoutRef<"a"> & { href?: string }) => {
    if (href?.startsWith("http")) {
      return (
        <a
          className="text-[#fd105e] underline decoration-[#fd105e]/30 underline-offset-2 transition-colors duration-200 hover:decoration-[#fd105e]"
          href={href}
          rel="noopener noreferrer"
          target="_blank"
          {...props}
        >
          {children}
        </a>
      );
    }
    return (
      <Link
        className="text-[#fd105e] underline decoration-[#fd105e]/30 underline-offset-2 transition-colors duration-200 hover:decoration-[#fd105e]"
        href={href ?? "/"}
      >
        {children}
      </Link>
    );
  },

  img: ({
    src,
    alt,
    width,
    height,
  }: {
    src?: string;
    alt?: string;
    width?: string | number;
    height?: string | number;
  }) => (
    <Image
      alt={alt ?? ""}
      className="my-6 rounded-lg"
      height={Number(height) || 450}
      src={src ?? ""}
      width={Number(width) || 800}
    />
  ),

  table: (props: ComponentPropsWithoutRef<"table">) => (
    <div className="my-6 overflow-x-auto rounded-lg border border-white/10">
      <table
        className="w-full border-collapse text-neutral-300 text-sm"
        {...props}
      />
    </div>
  ),
  thead: (props: ComponentPropsWithoutRef<"thead">) => (
    <thead
      className="bg-white/5 text-left text-neutral-400 text-xs uppercase tracking-wider"
      {...props}
    />
  ),
  tbody: (props: ComponentPropsWithoutRef<"tbody">) => (
    <tbody className="divide-y divide-white/5" {...props} />
  ),
  tr: (props: ComponentPropsWithoutRef<"tr">) => (
    <tr className="transition-colors hover:bg-white/[0.02]" {...props} />
  ),
  th: (props: ComponentPropsWithoutRef<"th">) => (
    <th className="px-4 py-3 font-semibold" {...props} />
  ),
  td: (props: ComponentPropsWithoutRef<"td">) => (
    <td className="px-4 py-3" {...props} />
  ),

  figure: ({
    children,
    ...props
  }: ComponentPropsWithoutRef<"figure"> & {
    "data-rehype-pretty-code-figure"?: string;
  }) => {
    const isPrettyCode = "data-rehype-pretty-code-figure" in props;
    if (!isPrettyCode) {
      return <figure {...props}>{children}</figure>;
    }
    return (
      <figure className="group/code relative my-6" {...props}>
        {children}
      </figure>
    );
  },

  figcaption: ({
    children,
    ...props
  }: ComponentPropsWithoutRef<"figcaption"> & {
    "data-rehype-pretty-code-title"?: string;
  }) => {
    const isTitle = "data-rehype-pretty-code-title" in props;
    if (!isTitle) {
      return <figcaption {...props}>{children}</figcaption>;
    }
    return (
      <figcaption
        className="rounded-t-lg border border-white/10 border-b-0 bg-white/[0.03] px-4 py-2 font-mono text-neutral-400 text-xs"
        {...props}
      >
        {children}
      </figcaption>
    );
  },

  pre: ({ children, ...props }: ComponentPropsWithoutRef<"pre">) => {
    const extractText = (node: unknown): string => {
      if (typeof node === "string") {
        return node;
      }
      if (Array.isArray(node)) {
        return node.map(extractText).join("");
      }
      if (node && typeof node === "object" && "props" in node) {
        const el = node as { props: { children?: unknown } };
        return extractText(el.props.children);
      }
      return "";
    };
    const codeText = extractText(children);
    return (
      <div className="relative">
        <pre
          className="overflow-x-auto rounded-lg border border-white/10 bg-[#0d1117] p-4 text-sm leading-relaxed"
          {...props}
        >
          {children}
        </pre>
        {codeText && <CopyButton text={codeText} />}
      </div>
    );
  },

  code: ({ children, ...props }: ComponentPropsWithoutRef<"code">) => {
    const isInline = !("data-language" in props || "data-theme" in props);
    if (isInline) {
      return (
        <code
          className="rounded-md border border-white/10 bg-white/[0.06] px-1.5 py-0.5 font-mono text-[#fd105e] text-[0.85em]"
          {...props}
        >
          {children}
        </code>
      );
    }
    return <code {...props}>{children}</code>;
  },

  PerformanceChart,
  ComparisonChart,
  CostChart,
  RadarComparisonChart,
  TrendLineChart,
  Callout,
  FAQBox,
  FAQItem: FAQAccordionItem,
  HowTo,
};
