"use client";

import { useMemo } from "react";
import { clsx } from "clsx";

interface AssistantInsightMetric {
  label: string;
  value: string;
  tone?: "neutral" | "good" | "warn" | "danger" | "info";
}

interface AssistantInsightSection {
  title: string;
  metrics: AssistantInsightMetric[];
}

interface AssistantInsight {
  kind: "chargeability" | "resource_match" | "holiday_region" | "resource_holidays";
  title: string;
  subtitle?: string;
  metrics: AssistantInsightMetric[];
  sections?: AssistantInsightSection[];
}

interface ChatMessageProps {
  role: "user" | "assistant";
  content: string;
  insights?: AssistantInsight[];
}

function renderMarkdown(text: string) {
  const lines = text.split("\n");
  const elements: React.ReactNode[] = [];
  let listItems: React.ReactNode[] = [];
  let listType: "ul" | "ol" | null = null;

  const flushList = () => {
    if (listItems.length > 0 && listType) {
      const Tag = listType;
      elements.push(
        <Tag key={`list-${elements.length}`} className={listType === "ul" ? "my-1 list-disc space-y-0.5 pl-4" : "my-1 list-decimal space-y-0.5 pl-4"}>
          {listItems}
        </Tag>,
      );
      listItems = [];
      listType = null;
    }
  };

  for (const [i, line] of lines.entries()) {
    const bulletMatch = line.match(/^[\s]*[-*]\s+(.*)/);
    if (bulletMatch?.[1]) {
      if (listType !== "ul") flushList();
      listType = "ul";
      listItems.push(<li key={`li-${i}`}>{inlineFormat(bulletMatch[1])}</li>);
      continue;
    }

    const numMatch = line.match(/^[\s]*\d+\.\s+(.*)/);
    if (numMatch?.[1]) {
      if (listType !== "ol") flushList();
      listType = "ol";
      listItems.push(<li key={`li-${i}`}>{inlineFormat(numMatch[1])}</li>);
      continue;
    }

    flushList();

    if (line.trim() === "") {
      elements.push(<div key={`br-${i}`} className="h-2" />);
      continue;
    }

    elements.push(<p key={`p-${i}`} className="my-0">{inlineFormat(line)}</p>);
  }

  flushList();
  return elements;
}

function inlineFormat(text: string): React.ReactNode {
  const parts: React.ReactNode[] = [];
  const regex = /(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`)/g;
  let lastIndex = 0;
  let match: RegExpExecArray | null;

  while ((match = regex.exec(text)) !== null) {
    if (match.index > lastIndex) {
      parts.push(text.slice(lastIndex, match.index));
    }

    if (match[2]) {
      parts.push(<strong key={`b-${match.index}`} className="font-semibold">{match[2]}</strong>);
    } else if (match[3]) {
      parts.push(<em key={`i-${match.index}`}>{match[3]}</em>);
    } else if (match[4]) {
      parts.push(
        <code key={`c-${match.index}`} className="rounded bg-black/10 px-1 py-0.5 text-xs font-mono dark:bg-white/10">
          {match[4]}
        </code>,
      );
    }

    lastIndex = match.index + match[0].length;
  }

  if (lastIndex < text.length) {
    parts.push(text.slice(lastIndex));
  }

  return parts.length === 1 ? parts[0] : <>{parts}</>;
}

function metricToneClasses(tone: AssistantInsightMetric["tone"] | undefined): string {
  switch (tone) {
    case "good":
      return "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-900/60 dark:bg-emerald-950/30 dark:text-emerald-300";
    case "warn":
      return "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-900/60 dark:bg-amber-950/30 dark:text-amber-300";
    case "danger":
      return "border-red-200 bg-red-50 text-red-700 dark:border-red-900/60 dark:bg-red-950/30 dark:text-red-300";
    case "info":
      return "border-sky-200 bg-sky-50 text-sky-700 dark:border-sky-900/60 dark:bg-sky-950/30 dark:text-sky-300";
    default:
      return "border-gray-200 bg-white text-gray-700 dark:border-slate-700 dark:bg-slate-900/60 dark:text-gray-200";
  }
}

function InsightMetric({ metric }: { metric: AssistantInsightMetric }) {
  return (
    <div className={clsx("rounded-xl border px-2.5 py-2", metricToneClasses(metric.tone))}>
      <div className="text-[10px] font-medium uppercase tracking-[0.08em] opacity-70">{metric.label}</div>
      <div className="mt-1 text-sm font-semibold leading-tight">{metric.value}</div>
    </div>
  );
}

function InsightCard({ insight }: { insight: AssistantInsight }) {
  return (
    <div className="rounded-2xl border border-slate-200 bg-white/90 p-3 shadow-sm dark:border-slate-700 dark:bg-slate-900/85">
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0">
          <div className="truncate text-sm font-semibold text-gray-900 dark:text-gray-100">{insight.title}</div>
          {insight.subtitle && (
            <div className="mt-0.5 text-[11px] text-gray-500 dark:text-gray-400">{insight.subtitle}</div>
          )}
        </div>
        <span className="rounded-full border border-slate-200 bg-slate-50 px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.08em] text-slate-600 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300">
          {insight.kind.replace("_", " ")}
        </span>
      </div>

      <div className="mt-3 grid grid-cols-2 gap-2">
        {insight.metrics.map((metric, index) => (
          <InsightMetric key={`${insight.kind}-${metric.label}-${index}`} metric={metric} />
        ))}
      </div>

      {insight.sections && insight.sections.length > 0 && (
        <div className="mt-3 space-y-2">
          {insight.sections.map((section, sectionIndex) => (
            <div key={`${insight.kind}-${section.title}-${sectionIndex}`} className="rounded-xl border border-dashed border-slate-200 bg-slate-50/70 p-2.5 dark:border-slate-700 dark:bg-slate-800/60">
              <div className="mb-2 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-500 dark:text-slate-400">
                {section.title}
              </div>
              <div className="grid grid-cols-2 gap-2">
                {section.metrics.map((metric, metricIndex) => (
                  <InsightMetric key={`${section.title}-${metric.label}-${metricIndex}`} metric={metric} />
                ))}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

export function ChatMessage({ role, content, insights }: ChatMessageProps) {
  const isUser = role === "user";
  const rendered = useMemo(() => (isUser ? null : renderMarkdown(content)), [isUser, content]);

  return (
    <div className={`flex ${isUser ? "justify-end" : "justify-start"}`}>
      <div
        className={`max-w-[85%] rounded-2xl px-4 py-2.5 text-sm leading-relaxed ${
          isUser
            ? "bg-brand-600 text-white"
            : "bg-gray-100 text-gray-800 dark:bg-slate-800 dark:text-gray-200"
        }`}
      >
        {isUser ? (
          <span className="whitespace-pre-wrap break-words">{content}</span>
        ) : (
          <>
            <span className="mb-1.5 inline-flex items-center gap-1 rounded bg-violet-100 px-1.5 py-0.5 text-[10px] font-medium text-violet-700 dark:bg-violet-900/30 dark:text-violet-300">
              <svg className="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
              </svg>
              AI Generated
            </span>
            {insights && insights.length > 0 && (
              <div className="mb-2 space-y-2">
                {insights.map((insight, index) => (
                  <InsightCard key={`${insight.kind}-${insight.title}-${index}`} insight={insight} />
                ))}
              </div>
            )}
            <div className="space-y-0.5 break-words">{rendered}</div>
          </>
        )}
      </div>
    </div>
  );
}

export function TypingIndicator() {
  return (
    <div className="flex justify-start">
      <div className="rounded-2xl bg-gray-100 px-4 py-3 dark:bg-slate-800">
        <div className="flex gap-1.5">
          <span className="h-2 w-2 animate-bounce rounded-full bg-gray-400 dark:bg-gray-500" style={{ animationDelay: "0ms" }} />
          <span className="h-2 w-2 animate-bounce rounded-full bg-gray-400 dark:bg-gray-500" style={{ animationDelay: "150ms" }} />
          <span className="h-2 w-2 animate-bounce rounded-full bg-gray-400 dark:bg-gray-500" style={{ animationDelay: "300ms" }} />
        </div>
      </div>
    </div>
  );
}
