import type { ReactNode } from "react";
import type { EvalScores, EvalState, QueryResponse } from "../types";
import CitationList from "./CitationList";
import PlotlyChart from "./PlotlyChart";

interface Props {
  response: QueryResponse;
  showInlineChart?: boolean;
  evalState?: EvalState;
}

const FULL_LABELS: Record<string, string> = {
  Ctx: "Context Relevance",
  Grd: "Groundedness",
  Ans: "Answer Relevance",
};

function ScoreBadge({ label, score }: { label: string; score: number | null }) {
  if (score === null) return null;

  const pct = Math.round(score * 100);
  const colorClass =
    score >= 0.85 ? "text-emerald-600 bg-emerald-50 border-emerald-200"
    : score >= 0.5 ? "text-amber-600 bg-amber-50 border-amber-200"
    : "text-red-600 bg-red-50 border-red-200";

  return (
    <span
      title={`${FULL_LABELS[label] ?? label}: ${score.toFixed(3)}`}
      className={`inline-flex items-center gap-0.5 text-[10px] font-medium px-1.5 py-0.5 rounded border ${colorClass}`}
    >
      <span className="text-[9px] font-normal opacity-70">{label}</span>
      {pct}%
    </span>
  );
}

/** Shimmer pill shown while eval scores are loading. */
function EvalLoadingPill() {
  return (
    <span
      className="inline-block w-24 h-3.5 rounded shimmer"
      aria-label="Loading evaluation scores"
    />
  );
}

function EvalScoreBadges({ scores }: { scores: EvalScores }) {
  return (
    <>
      <span className="text-[11px] text-slate-300" aria-hidden>·</span>
      <ScoreBadge label="Ctx" score={scores.relevance_score} />
      <ScoreBadge label="Grd" score={scores.groundedness_score} />
      <ScoreBadge label="Ans" score={scores.answer_relevance_score} />
    </>
  );
}

// ── Inline markdown: **bold**, *italic*, `code` ────────────────────────────
function renderInline(text: string): ReactNode {
  const parts = text.split(/(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)/g);
  return parts.map((part, i) => {
    if (part.startsWith("**") && part.endsWith("**"))
      return <strong key={i} className="font-semibold text-slate-900">{part.slice(2, -2)}</strong>;
    if (part.startsWith("*") && part.endsWith("*"))
      return <em key={i} className="italic">{part.slice(1, -1)}</em>;
    if (part.startsWith("`") && part.endsWith("`"))
      return (
        <code key={i} className="bg-slate-100 text-slate-800 text-[0.8em] font-mono px-1.5 py-0.5 rounded border border-slate-200">
          {part.slice(1, -1)}
        </code>
      );
    return part;
  });
}

// ── Block markdown parser ──────────────────────────────────────────────────
function renderMarkdown(text: string): ReactNode {
  const lines = text.split("\n");
  const out: ReactNode[] = [];
  let i = 0;
  let key = 0;

  while (i < lines.length) {
    const line = lines[i];

    // Fenced code block
    if (line.startsWith("```")) {
      const lang = line.slice(3).trim();
      const code: string[] = [];
      i++;
      while (i < lines.length && !lines[i].startsWith("```")) {
        code.push(lines[i]);
        i++;
      }
      out.push(
        <div key={key++} className="my-3 rounded-lg overflow-hidden border border-slate-200 text-xs">
          {lang && (
            <div className="bg-slate-800 px-3 py-1.5 font-mono text-slate-400 uppercase tracking-widest text-[10px]">
              {lang}
            </div>
          )}
          <pre className="bg-slate-900 text-slate-100 px-4 py-3 font-mono overflow-x-auto leading-relaxed">
            <code>{code.join("\n")}</code>
          </pre>
        </div>,
      );
    }
    // H3
    else if (line.startsWith("### ")) {
      out.push(
        <h3 key={key++} className="font-semibold text-slate-800 text-sm mt-4 mb-1">
          {renderInline(line.slice(4))}
        </h3>,
      );
    }
    // H2
    else if (line.startsWith("## ")) {
      out.push(
        <h2 key={key++} className="font-semibold text-slate-900 text-[0.9375rem] mt-5 mb-1.5">
          {renderInline(line.slice(3))}
        </h2>,
      );
    }
    // H1
    else if (line.startsWith("# ")) {
      out.push(
        <h1 key={key++} className="font-bold text-slate-900 text-base mt-5 mb-2">
          {renderInline(line.slice(2))}
        </h1>,
      );
    }
    // Unordered list — collect consecutive items
    else if (/^[-*+] /.test(line)) {
      const items: string[] = [];
      while (i < lines.length && /^[-*+] /.test(lines[i])) {
        items.push(lines[i].replace(/^[-*+] /, ""));
        i++;
      }
      out.push(
        <ul key={key++} className="my-2 space-y-1.5 pl-1">
          {items.map((item, idx) => (
            <li key={idx} className="flex gap-2.5 text-sm text-slate-700 leading-relaxed">
              <span className="mt-2 w-1.5 h-1.5 rounded-full bg-brand-400 shrink-0" />
              <span>{renderInline(item)}</span>
            </li>
          ))}
        </ul>,
      );
      continue;
    }
    // Ordered list
    else if (/^\d+\. /.test(line)) {
      const items: string[] = [];
      while (i < lines.length && /^\d+\. /.test(lines[i])) {
        items.push(lines[i].replace(/^\d+\. /, ""));
        i++;
      }
      out.push(
        <ol key={key++} className="my-2 space-y-1.5 pl-1">
          {items.map((item, idx) => (
            <li key={idx} className="flex gap-2.5 text-sm text-slate-700 leading-relaxed">
              <span className="shrink-0 text-brand-500 font-semibold tabular-nums text-xs mt-0.5 w-4 text-right">
                {idx + 1}.
              </span>
              <span>{renderInline(item)}</span>
            </li>
          ))}
        </ol>,
      );
      continue;
    }
    // Horizontal rule
    else if (/^---+$/.test(line.trim())) {
      out.push(<hr key={key++} className="my-4 border-slate-200" />);
    }
    // Blank line → spacer paragraph gap
    else if (line.trim() === "") {
      // handled by space-y on the container
    }
    // Paragraph
    else {
      out.push(
        <p key={key++} className="text-sm text-slate-700 leading-relaxed">
          {renderInline(line)}
        </p>,
      );
    }

    i++;
  }

  return <div className="space-y-1.5">{out}</div>;
}

// ── Component ──────────────────────────────────────────────────────────────
export default function ResponseDisplay({ response, showInlineChart = true, evalState }: Props) {
  const time = new Date(response.created_at).toLocaleTimeString([], {
    hour: "2-digit",
    minute: "2-digit",
  });

  const PROVIDER_LABELS: Record<string, string> = {
    openai: "OpenAI",
    azure_openai: "Azure OpenAI",
    gemini: "Gemini",
  };

  return (
    <div className="animate-slide-up space-y-2">
      {/* User query — right-aligned bubble */}
      <div className="flex justify-end">
        <div className="max-w-[80%] bg-brand-600 text-white rounded-2xl rounded-tr-sm px-4 py-2.5 text-sm leading-relaxed shadow-sm">
          {response.query}
        </div>
      </div>

      {/* AI response — left-aligned with avatar */}
      <div className="flex gap-2.5 items-start">
        {/* Avatar */}
        <div
          className="w-7 h-7 rounded-full bg-white border border-slate-200 shadow-sm flex items-center justify-center shrink-0 mt-0.5"
          aria-hidden="true"
        >
          <svg className="w-3.5 h-3.5 text-brand-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.75}>
            <path strokeLinecap="round" strokeLinejoin="round" d="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09Z" />
          </svg>
        </div>

        {/* Response card */}
        <div className="flex-1 min-w-0 bg-white rounded-2xl rounded-tl-sm border border-slate-200 shadow-sm overflow-hidden">
          {/* Answer body */}
          <div className="px-5 pt-4 pb-3">
            {renderMarkdown(response.answer)}
          </div>

          {/* Inline chart (only when viz panel is not active) */}
          {showInlineChart && response.chart_data && (
            <div className="px-5 pb-4">
              <PlotlyChart spec={response.chart_data} />
            </div>
          )}

          {/* Citations */}
          {response.citations.length > 0 && (
            <div className="px-5 pb-4 border-t border-slate-100 pt-3">
              <CitationList citations={response.citations} />
            </div>
          )}

          {/* Metadata footer */}
          <div className="px-5 py-2 bg-slate-50 border-t border-slate-100 flex items-center gap-2 flex-wrap">
            <span className="text-[11px] text-slate-400 tabular-nums">{time}</span>
            <span className="text-[11px] text-slate-300" aria-hidden>·</span>
            <span className="text-[11px] text-slate-400">
              {PROVIDER_LABELS[response.model_provider] ?? response.model_provider}
            </span>
            <span className="text-[11px] text-slate-300" aria-hidden>·</span>
            <span className="text-[11px] text-slate-400">
              {response.agent_steps} step{response.agent_steps !== 1 ? "s" : ""}
            </span>
            {evalState?.loading && <EvalLoadingPill />}
            {evalState && !evalState.loading && evalState.scores && (
              <EvalScoreBadges scores={evalState.scores} />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
