import { useEffect, useState, useRef } from "react";
import { Hash, Calendar, Sparkles, TrendingUp, MessageSquare, ChevronDown, ChevronUp, Activity } from "lucide-react";
import { getDVScreen, getDetailView, getInstance, type InstanceResponse } from "../api/viewService";
import { WORKFLOW_ID, STATE_IDS, ACTIVITY_IDS } from "../config";
import { fmtAct } from "../lib/activity";

interface Field { field_key: string; output_label: string; data_type: string }
interface Props  { viewId: number | string; instanceId: string }

type GroupKey = "hero" | "customer" | "vehicle" | "booking" | "feedback" | "ai" | "general";

// ---------------------------------------------------------------------------
// Classification — Mahindra test-drive workflow
// ---------------------------------------------------------------------------

function classify(key: string): GroupKey {
  const k = key.toLowerCase();
  if (k === "customer_name") return "hero";
  if (k.startsWith("customer_") || k === "lead_source" || k === "phone" || k === "email") return "customer";
  if (k === "model_interest" || k.startsWith("vehicle_") || k === "variant" || k === "color" || k === "fuel_type") return "vehicle";
  if (k.startsWith("booking_") || k === "dealer_name" || k === "dealer_id" || k === "slot_start" || k === "slot_end") return "booking";
  if (k.startsWith("feedback_") || k === "test_drive_outcome" || k === "would_recommend" || k === "rating") return "feedback";
  if (k.startsWith("ai_") || k.startsWith("call_") || k.includes("summary") || k.includes("failure_reason") ||
      k.includes("confidence") || k.includes("reasoning") || k.includes("escalation")) return "ai";
  return "general";
}

// ---------------------------------------------------------------------------
// Status
// ---------------------------------------------------------------------------

const STATUS: Record<string, { pill: string; dot: string; bar: string; pulse?: boolean }> = {
  "Awaiting Scheduler Call": {
    pill: "text-rose-700 bg-rose-50 ring-rose-200 dark:text-rose-300 dark:bg-rose-950/30 dark:ring-rose-900",
    dot: "bg-rose-500", bar: "bg-rose-500", pulse: true,
  },
  "Scheduled": {
    pill: "text-amber-700 bg-amber-50 ring-amber-200 dark:text-amber-300 dark:bg-amber-950/30 dark:ring-amber-900",
    dot: "bg-amber-500", bar: "bg-amber-500",
  },
  "Awaiting Feedback Call": {
    pill: "text-rose-700 bg-rose-50 ring-rose-200 dark:text-rose-300 dark:bg-rose-950/30 dark:ring-rose-900",
    dot: "bg-rose-500", bar: "bg-rose-500", pulse: true,
  },
  "Feedback Collected": {
    pill: "text-emerald-700 bg-emerald-50 ring-emerald-200 dark:text-emerald-300 dark:bg-emerald-950/30 dark:ring-emerald-900",
    dot: "bg-emerald-500", bar: "bg-emerald-500",
  },
  "Scheduling Call Failed": {
    pill: "text-red-700 bg-red-50 ring-red-200 dark:text-red-300 dark:bg-red-950/30 dark:ring-red-900",
    dot: "bg-red-500", bar: "bg-red-500",
  },
  "Feedback Call Failed": {
    pill: "text-red-700 bg-red-50 ring-red-200 dark:text-red-300 dark:bg-red-950/30 dark:ring-red-900",
    dot: "bg-red-500", bar: "bg-red-500",
  },
  "End State": {
    pill: "text-stone-600 bg-stone-100 ring-stone-200 dark:text-zinc-400 dark:bg-zinc-800 dark:ring-zinc-700",
    dot: "bg-stone-400", bar: "bg-stone-400",
  },
};
const DS = { pill: "text-stone-600 bg-stone-100 ring-stone-200 dark:text-zinc-400 dark:bg-zinc-800 dark:ring-zinc-700", dot: "bg-stone-400", bar: "bg-stone-300" };

const SKIP_KEYS = new Set(["analysis_so_far"]);

// ---------------------------------------------------------------------------
// Skeleton
// ---------------------------------------------------------------------------

function DetailSkeleton() {
  return (
    <div className="bg-white dark:bg-zinc-900 rounded-2xl border border-stone-200/80 dark:border-zinc-700/60 overflow-hidden">
      <div className="h-[3px] bg-stone-100 dark:bg-zinc-800" />
      <div className="px-7 pt-5 pb-4 border-b border-stone-100 dark:border-zinc-800 space-y-3">
        <div className="h-6 w-48 bg-stone-100 dark:bg-zinc-800 rounded animate-pulse" />
        <div className="h-4 w-32 bg-stone-100 dark:bg-zinc-800 rounded animate-pulse" />
      </div>
      <div className="px-7 py-5 grid grid-cols-2 gap-6">
        {Array.from({ length: 6 }).map((_, i) => (
          <div key={i} className="space-y-2">
            <div className="h-3 w-20 bg-stone-100 dark:bg-zinc-800 rounded animate-pulse" />
            <div className="h-4 w-32 bg-stone-100 dark:bg-zinc-800 rounded animate-pulse" />
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

export default function DetailViewPanel({ viewId, instanceId }: Props) {
  const [data, setData]       = useState<Record<string, unknown> | null>(null);
  const [fields, setFields]   = useState<Field[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError]     = useState<string | null>(null);

  useEffect(() => {
    if (!instanceId) return;
    setLoading(true); setError(null);
    getDVScreen(viewId)
      .then(dv => getDetailView(dv.dv_template_uid, instanceId))
      .catch(() => getDetailView(viewId, instanceId))
      .then(res => {
        setFields(res.config?.fields?.filter((f: any) => f.field_key !== "") ?? []);
        setData(res.data ?? {});
      })
      .catch((e: any) => setError(e.message))
      .finally(() => setLoading(false));
  }, [viewId, instanceId]);

  if (loading) return <DetailSkeleton />;
  if (error)   return <p className="text-sm text-red-500 dark:text-red-400">{error}</p>;
  if (!data || !fields.length) return null;

  const sys = new Set(["instance_id", "current_state_name", "created_at", "updated_at"]);
  const groups: Record<GroupKey, Field[]> = { hero: [], customer: [], vehicle: [], booking: [], feedback: [], ai: [], general: [] };

  for (const f of fields) {
    if (sys.has(f.field_key) || SKIP_KEYS.has(f.field_key)) continue;
    const g = classify(f.field_key);
    groups[g].push(f);
  }

  const heroField = groups.hero[0];
  const heroValue = heroField ? String(data[heroField.field_key] ?? "") : "";
  const stateName = String(data.current_state_name ?? "");
  const sc        = STATUS[stateName] ?? DS;

  const phone = fmtPhone(data.customer_phone);
  const model = String(data.model_interest ?? "");

  const leftGroups = [
    { label: "Customer", fields: groups.customer },
    { label: "Vehicle",  fields: groups.vehicle },
    { label: "Other",    fields: groups.general },
  ].filter(g => g.fields.length > 0);

  const rightGroups = [
    { label: "Booking",  fields: groups.booking },
    { label: "Feedback", fields: groups.feedback },
  ].filter(g => g.fields.length > 0);

  const isScore = (f: Field) => f.field_key.toLowerCase().includes("confidence") || f.field_key.toLowerCase().includes("rating") || f.field_key.toLowerCase().includes("score");
  const isLongText = (f: Field) => { const v = data[f.field_key]; return typeof v === "string" && v.length > 55; };

  const aiShort = groups.ai.filter(f => isScore(f) || !isLongText(f));
  const aiLong  = groups.ai.filter(f => !isScore(f) && isLongText(f));

  return (
    <div className="bg-white dark:bg-zinc-900 rounded-2xl border border-stone-200/80 dark:border-zinc-700/60 overflow-hidden">

      {/* Status bar */}
      <div className={`h-[3px] ${sc.bar}`} />

      {/* ── Header ──────────────────────────────────────────────────── */}
      <div className="px-7 pt-5 pb-4 border-b border-stone-100 dark:border-zinc-800">
        <div className="flex items-start justify-between gap-6 mb-3">
          <div className="min-w-0 flex items-center gap-3 flex-wrap">
            {heroValue && (
              <h1 className="text-[20px] font-bold tracking-tight text-stone-900 dark:text-white leading-none">
                {heroValue}
              </h1>
            )}
            {stateName && (
              <span className={`inline-flex items-center gap-1.5 text-[11px] font-semibold px-2.5 py-1 rounded-full ring-1 shrink-0 ${sc.pill}`}>
                <span className={`w-1.5 h-1.5 rounded-full ${sc.dot} ${sc.pulse ? "animate-pulse" : ""}`} />
                {stateName}
              </span>
            )}
          </div>

          {model && (
            <div className="text-right shrink-0">
              <p className="text-[10px] font-medium text-stone-400 dark:text-zinc-600 mb-0.5 uppercase tracking-wider">Model Interest</p>
              <p className="text-[18px] font-bold text-stone-900 dark:text-white leading-none">{model}</p>
            </div>
          )}
        </div>

        <div className="flex items-center gap-3 flex-wrap text-[12px]">
          {phone && (
            <span className="font-medium text-stone-600 dark:text-zinc-300">{phone}</span>
          )}
          {phone && (data.created_at || data.instance_id) && (
            <span className="text-stone-200 dark:text-zinc-700">·</span>
          )}
          {data.created_at && (
            <span className="flex items-center gap-1 text-stone-400 dark:text-zinc-500">
              <Calendar size={11} />{fmtDate(String(data.created_at))}
            </span>
          )}
          {data.instance_id && (
            <span className="flex items-center gap-1 text-stone-400 dark:text-zinc-500 font-mono text-[11px]">
              <Hash size={10} />Lead #{String(data.instance_id)}
            </span>
          )}
        </div>
      </div>

      {/* ── Two-column metadata ──────────────────────────────────────── */}
      {(leftGroups.length > 0 || rightGroups.length > 0) && (
        <div className="grid lg:grid-cols-2 divide-y lg:divide-y-0 lg:divide-x divide-stone-100 dark:divide-zinc-800 border-b border-stone-100 dark:border-zinc-800">
          <div className="px-7 py-5 space-y-6">
            {leftGroups.map(({ label, fields: fs }) => (
              <section key={label}>
                <p className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-zinc-600 mb-3">{label}</p>
                <dl className="grid grid-cols-2 gap-x-8 gap-y-4">
                  {fs.map(f => (
                    <div key={f.field_key}>
                      <dt className="text-[11px] text-stone-400 dark:text-zinc-500 mb-0.5">{fmtLabel(f.output_label)}</dt>
                      <dd className="text-[14px] font-medium text-stone-900 dark:text-zinc-100 break-words">
                        {fmtVal(data[f.field_key], f.data_type, f.field_key)}
                      </dd>
                    </div>
                  ))}
                </dl>
              </section>
            ))}
          </div>

          <div className="px-7 py-5 space-y-6">
            {rightGroups.length > 0 ? rightGroups.map(({ label, fields: fs }) => (
              <section key={label}>
                <p className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-zinc-600 mb-3 flex items-center gap-1.5">
                  {label === "Booking" && <TrendingUp size={11} className="text-amber-500" />}
                  {label === "Feedback" && <MessageSquare size={11} className="text-emerald-500" />}
                  {label}
                </p>
                <dl className="grid grid-cols-2 gap-x-8 gap-y-4">
                  {fs.map(f => (
                    <div key={f.field_key}>
                      <dt className="text-[11px] text-stone-400 dark:text-zinc-500 mb-0.5">{fmtLabel(f.output_label)}</dt>
                      <dd className="text-[14px] font-medium text-stone-900 dark:text-zinc-100 break-words">
                        {fmtVal(data[f.field_key], f.data_type, f.field_key)}
                      </dd>
                    </div>
                  ))}
                </dl>
              </section>
            )) : (
              <div className="text-[13px] text-stone-300 dark:text-zinc-700 italic">
                Booking and feedback details will appear here once the AI completes its call.
              </div>
            )}
          </div>
        </div>
      )}

      {/* ── AI Analysis ─────────────────────────────────────────────── */}
      {groups.ai.length > 0 && (
        <div className="px-7 py-5">
          <p className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-zinc-600 mb-4 flex items-center gap-1.5">
            <Sparkles size={10} className="text-[#C8102E]" />AI · Call Outcome
          </p>

          {aiShort.length > 0 && (
            <dl className="grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-5 mb-5">
              {aiShort.map(f => {
                const val    = data[f.field_key];
                const score  = isScore(f);
                const num    = score ? Number(val) : null;
                const pct    = num !== null ? Math.min(num > 1 ? num : num * 100, 100) : 0;
                const barCls = pct >= 70 ? "bg-emerald-500" : pct >= 40 ? "bg-amber-500" : "bg-red-500";
                const pctCls = pct >= 70 ? "text-emerald-600 dark:text-emerald-400" : pct >= 40 ? "text-amber-600 dark:text-amber-400" : "text-red-500";
                return (
                  <div key={f.field_key}>
                    <dt className="text-[11px] text-stone-400 dark:text-zinc-500 mb-1">{fmtLabel(f.output_label)}</dt>
                    {score && num !== null ? (
                      <dd className="flex items-center gap-2.5">
                        <div className="flex-1 h-1.5 bg-stone-100 dark:bg-zinc-800 rounded-full overflow-hidden">
                          <div className={`h-full rounded-full ${barCls}`} style={{ width: `${pct}%` }} />
                        </div>
                        <span className={`text-[12px] font-bold tabular-nums w-8 text-right ${pctCls}`}>{pct.toFixed(0)}%</span>
                      </dd>
                    ) : (
                      <dd className="text-[14px] font-semibold text-stone-900 dark:text-zinc-100">
                        {fmtVal(val, f.data_type, f.field_key)}
                      </dd>
                    )}
                  </div>
                );
              })}
            </dl>
          )}

          {aiLong.length > 0 && (
            <div className="space-y-4 border-t border-stone-100 dark:border-zinc-800 pt-4">
              {aiLong.map(f => {
                const val      = data[f.field_key];
                const isClarif = f.field_key.includes("clarification") || f.field_key.includes("response");
                return (
                  <div key={f.field_key} className="border-b border-stone-50 dark:border-zinc-800/50 pb-4 last:border-0 last:pb-0">
                    <div className="flex items-center gap-1.5 mb-1.5">
                      {isClarif && <MessageSquare size={11} className="text-amber-400 shrink-0" />}
                      <span className="text-[11px] font-medium text-stone-400 dark:text-zinc-500">{fmtLabel(f.output_label)}</span>
                    </div>
                    <ClampedText text={String(val ?? "—")} />
                  </div>
                );
              })}
            </div>
          )}
        </div>
      )}

      {/* ── Activity timeline ──────────────────────────────────────── */}
      {data.instance_id && <TimelineSection instanceId={String(data.instance_id)} />}
    </div>
  );
}

// ---------------------------------------------------------------------------
// TimelineSection — derived from instance.data._activities (no audit endpoint
// needed). INIT is synthesised from instance.created_at since the platform
// doesn't write INIT into _activities.
// ---------------------------------------------------------------------------

interface ActivityRecord {
  _system?: { created_at?: string; user_id?: string; user_roles?: string[] | null };
}

interface TimelineEntry {
  activityId: string;
  createdAt: string;
  userRoles: string[] | null;
  synthetic: boolean;
}

const FAILURE_STATE_IDS = new Set<string>([
  STATE_IDS.SCHEDULING_CALL_FAILED,
  STATE_IDS.FEEDBACK_CALL_FAILED,
]);

function TimelineSection({ instanceId }: { instanceId: string }) {
  const [inst, setInst] = useState<InstanceResponse | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!instanceId) return;
    let cancelled = false;
    setInst(null); setError(null);
    getInstance(WORKFLOW_ID, instanceId)
      .then((r) => !cancelled && setInst(r))
      .catch((e: any) => !cancelled && setError(e?.message ?? "failed to load"));
    return () => { cancelled = true; };
  }, [instanceId]);

  if (error) return null;
  if (inst === null) {
    return (
      <div className="px-7 py-5 border-t border-stone-100 dark:border-zinc-800 text-[12px] text-stone-300 dark:text-zinc-700">
        Loading activity timeline…
      </div>
    );
  }

  const activities = (inst.data as { _activities?: Record<string, ActivityRecord> } | null)?._activities;
  const entries: TimelineEntry[] = [];

  // Synthesise INIT from instance.created_at — _activities never includes it.
  entries.push({
    activityId: ACTIVITY_IDS.INIT_ACTIVITY,
    createdAt: inst.created_at,
    userRoles: null,
    synthetic: true,
  });

  if (activities) {
    for (const [activityId, record] of Object.entries(activities)) {
      entries.push({
        activityId,
        createdAt: record._system?.created_at ?? inst.created_at,
        userRoles: record._system?.user_roles ?? null,
        synthetic: false,
      });
    }
  }

  entries.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());

  const lastIdx = entries.length - 1;
  const inFailureState = FAILURE_STATE_IDS.has(inst.current_state_id);

  return (
    <div className="px-7 py-5 border-t border-stone-100 dark:border-zinc-800">
      <p className="text-[10px] font-bold uppercase tracking-widest text-stone-400 dark:text-zinc-600 mb-4 flex items-center gap-1.5">
        <Activity size={10} className="text-[#C8102E]" /> Activity Timeline
      </p>
      <ol className="relative pl-6">
        <span aria-hidden className="absolute left-[7px] top-1 bottom-1 w-px bg-stone-200 dark:bg-zinc-700" />
        {entries.map((e, i) => {
          const isLast = i === lastIdx;
          const isFirst = i === 0;
          const failed = isLast && inFailureState;
          const dotBg = failed ? "#dc2626" : isLast ? "#C8102E" : isFirst ? "#10b981" : "#d1d5db";
          const actor = (e.userRoles && e.userRoles.length > 0) ? e.userRoles.join(", ") : "system";
          return (
            <li key={`${e.activityId}-${e.createdAt}`} className="relative pb-4 last:pb-0">
              <span
                aria-hidden
                className={`absolute -left-[22px] top-1 w-3.5 h-3.5 rounded-full border-2 border-white dark:border-zinc-900 shadow-sm ${isLast ? "ring-2 ring-rose-200 dark:ring-rose-900" : ""}`}
                style={{ background: dotBg, boxShadow: isLast ? "0 0 8px rgba(200,16,46,0.5)" : undefined }}
              />
              <div className="flex items-center gap-2 flex-wrap">
                <span className={`text-[13px] font-medium ${
                  failed
                    ? "text-red-600 dark:text-red-400"
                    : isLast
                      ? "text-[#9D0D24] dark:text-rose-300"
                      : "text-stone-700 dark:text-zinc-200"
                }`}>
                  {fmtAct(e.activityId)}
                </span>
                {failed && (
                  <span className="text-[10px] font-semibold px-1.5 py-0.5 rounded-full bg-red-50 text-red-700 dark:bg-red-950/30 dark:text-red-300">
                    Failed
                  </span>
                )}
                {isLast && !failed && (
                  <span className="text-[10px] font-semibold px-1.5 py-0.5 rounded-full"
                        style={{ background: "rgba(200,16,46,0.10)", color: "#C8102E" }}>
                    Latest
                  </span>
                )}
              </div>
              <div className="text-[11px] text-stone-400 dark:text-zinc-500 mt-0.5">
                {new Date(e.createdAt).toLocaleString("en-IN", {
                  day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit",
                })}
                <span className="mx-1.5 text-stone-200 dark:text-zinc-700">·</span>
                <span className="text-stone-500 dark:text-zinc-400">{actor}</span>
              </div>
            </li>
          );
        })}
      </ol>
    </div>
  );
}

// ---------------------------------------------------------------------------
// ClampedText
// ---------------------------------------------------------------------------

function ClampedText({ text }: { text: string }) {
  const [expanded, setExpanded] = useState(false);
  const [clamped, setClamped]   = useState(false);
  const ref = useRef<HTMLParagraphElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (el) setClamped(el.scrollHeight > el.clientHeight + 2);
  }, [text]);

  return (
    <div>
      <p
        ref={ref}
        className={`text-[13px] leading-relaxed text-stone-700 dark:text-zinc-200 transition-all ${expanded ? "" : "line-clamp-3"}`}
      >
        {text}
      </p>
      {(clamped || expanded) && (
        <button
          onClick={() => setExpanded(e => !e)}
          className="mt-1.5 flex items-center gap-1 text-[11px] font-semibold text-rose-600 dark:text-rose-400 hover:text-rose-700 dark:hover:text-rose-300 transition-colors"
        >
          {expanded ? <><ChevronUp size={12} /> Show less</> : <><ChevronDown size={12} /> Show more</>}
        </button>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function fmtLabel(label: string): string {
  return label.replace(/_/g, " ").replace(/\b\w/g, c => c.toUpperCase());
}

function fmtVal(val: unknown, type: string, key: string): string {
  if (val == null || val === "") return "—";
  if (type === "phone" && typeof val === "object") {
    const p = val as { phone_with_dial_code?: string; phone?: string; dial_code?: string };
    return p.phone_with_dial_code || (p.dial_code && p.phone ? `${p.dial_code}${p.phone}` : p.phone || "—");
  }
  if (type === "number") {
    const n = Number(val);
    if (["amount","tax","price","cost"].some(x => key.toLowerCase().includes(x))) return fmtCurrency(n);
    return n.toLocaleString("en-IN");
  }
  if (type === "datetime" || type === "date") return fmtDate(String(val));
  return String(val);
}

function fmtCurrency(n: number): string {
  return n.toLocaleString("en-IN", { style: "currency", currency: "INR", maximumFractionDigits: 0 });
}

function fmtDate(val: string): string {
  try { return new Date(val).toLocaleDateString("en-IN", { day: "2-digit", month: "short", year: "numeric" }); }
  catch { return val; }
}

function fmtPhone(val: unknown): string {
  if (val == null || val === "") return "";
  if (typeof val === "object") {
    const p = val as { phone_with_dial_code?: string; phone?: string; dial_code?: string };
    return p.phone_with_dial_code || (p.dial_code && p.phone ? `${p.dial_code}${p.phone}` : p.phone || "");
  }
  return String(val);
}
