"use client";

import * as React from "react";
import { Sparkles, User } from "lucide-react";

import { cn } from "@/lib/utils";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";

export type AIMessageProps = {
  role: "user" | "assistant" | "system";
  content: string;
  timestamp?: Date;
};

/** Minimal markdown: **bold**, *italic*, `code`, lists */
function renderAssistantMarkdown(content: string): React.ReactNode {
  const lines = content.split("\n");
  const blocks: React.ReactNode[] = [];
  let listBuf: { ordered: boolean; items: string[] } | null = null;
  let blockKey = 0;

  const parseInline = (text: string, keyPrefix: string): React.ReactNode[] => {
    const nodes: React.ReactNode[] = [];
    let remaining = text;
    let i = 0;
    while (remaining.length > 0) {
      const tick = remaining.match(/^`([^`]+)`/);
      if (tick) {
        nodes.push(
          <code
            key={`${keyPrefix}-c-${i++}`}
            className="rounded bg-muted/80 px-1.5 py-0.5 font-mono text-[0.85em] text-foreground"
          >
            {tick[1]}
          </code>,
        );
        remaining = remaining.slice(tick[0].length);
        continue;
      }
      const bold = remaining.match(/^\*\*([^*]+)\*\*/);
      if (bold) {
        nodes.push(
          <strong key={`${keyPrefix}-b-${i++}`} className="font-semibold text-foreground">
            {bold[1]}
          </strong>,
        );
        remaining = remaining.slice(bold[0].length);
        continue;
      }
      const italic = remaining.match(/^\*([^*]+)\*/);
      if (italic) {
        nodes.push(
          <em key={`${keyPrefix}-i-${i++}`} className="italic">
            {italic[1]}
          </em>,
        );
        remaining = remaining.slice(italic[0].length);
        continue;
      }
      const nextSpecial = remaining.search(/[`\*]/);
      if (nextSpecial === -1) {
        nodes.push(remaining);
        break;
      }
      if (nextSpecial > 0) {
        nodes.push(remaining.slice(0, nextSpecial));
        remaining = remaining.slice(nextSpecial);
        continue;
      }
      nodes.push(remaining[0]);
      remaining = remaining.slice(1);
    }
    return nodes;
  };

  const flushList = () => {
    if (!listBuf || listBuf.items.length === 0) return;
    const { ordered, items } = listBuf;
    listBuf = null;
    const lis = items.map((line, i) => (
      <li key={i} className="ml-1 list-inside leading-relaxed marker:text-muted-foreground">
        {parseInline(line, `li-${i}`)}
      </li>
    ));
    if (ordered) {
      blocks.push(
        <ol key={`ol-${blockKey++}`} className="list-decimal space-y-1 pl-4">
          {lis}
        </ol>,
      );
    } else {
      blocks.push(
        <ul key={`ul-${blockKey++}`} className="list-disc space-y-1 pl-4">
          {lis}
        </ul>,
      );
    }
  };

  for (const line of lines) {
    const ul = line.match(/^\s*[-*]\s+(.*)$/);
    const ol = line.match(/^\s*\d+\.\s+(.*)$/);
    if (ul) {
      if (listBuf?.ordered) flushList();
      if (!listBuf) listBuf = { ordered: false, items: [] };
      listBuf.items.push(ul[1] ?? "");
      continue;
    }
    if (ol) {
      if (listBuf && !listBuf.ordered) flushList();
      if (!listBuf) listBuf = { ordered: true, items: [] };
      listBuf.items.push(ol[1] ?? "");
      continue;
    }
    flushList();
    if (line.trim() === "") {
      blocks.push(<div key={`sp-${blockKey++}`} className="h-2" />);
    } else {
      blocks.push(
        <p key={`p-${blockKey++}`} className="leading-relaxed">
          {parseInline(line, `p-${blockKey}`)}
        </p>,
      );
    }
  }
  flushList();

  return <div className="space-y-2 text-sm">{blocks}</div>;
}

export function AIMessage({ role, content, timestamp }: AIMessageProps) {
  if (role === "system") {
    return (
      <div className="flex justify-center px-2 py-1">
        <p className="max-w-[90%] text-center text-xs text-muted-foreground">{content}</p>
      </div>
    );
  }

  const isUser = role === "user";

  return (
    <div
      className={cn(
        "flex gap-3 px-1 py-2",
        isUser ? "flex-row-reverse" : "flex-row",
      )}
    >
      <Avatar className="mt-0.5 h-8 w-8 shrink-0 border border-border/60">
        <AvatarFallback
          className={cn(
            "text-xs",
            isUser
              ? "bg-primary/15 text-primary"
              : "bg-teal-500/15 text-teal-600 dark:text-teal-400",
          )}
        >
          {isUser ? <User className="size-4" /> : <Sparkles className="size-4" />}
        </AvatarFallback>
      </Avatar>
      <div
        className={cn(
          "flex min-w-0 max-w-[min(100%,28rem)] flex-col gap-1",
          isUser ? "items-end" : "items-start",
        )}
      >
        <div
          className={cn(
            "rounded-2xl px-4 py-2.5 shadow-sm",
            isUser
              ? "rounded-tr-md bg-primary text-primary-foreground"
              : "rounded-tl-md border border-border/80 bg-card text-card-foreground",
          )}
        >
          {isUser ? (
            <p className="whitespace-pre-wrap text-sm leading-relaxed">{content}</p>
          ) : (
            <div className="prose prose-sm dark:prose-invert max-w-none prose-p:my-1 prose-headings:my-2">
              {renderAssistantMarkdown(content)}
            </div>
          )}
        </div>
        {timestamp ? (
          <time
            dateTime={timestamp.toISOString()}
            className="text-[10px] text-muted-foreground"
          >
            {timestamp.toLocaleTimeString(undefined, {
              hour: "numeric",
              minute: "2-digit",
            })}
          </time>
        ) : null}
      </div>
    </div>
  );
}
