"use client";

import * as React from "react";
import { useParams, useRouter } from "next/navigation";
import Image from "next/image";
import { toast } from "sonner";
import {
  ArrowLeft,
  ArrowRight,
  Check,
  Download,
  ImageIcon,
  ChevronDown,
  ChevronUp,
  ScanLine,
  User,
  ClipboardList,
  ClipboardCheck,
  Code,
  RefreshCw,
  Loader2,
  AlertCircle,
  Activity,
  Clock,
  Monitor,
  LayoutGrid,
  Maximize2,
  X,
} from "lucide-react";

import { Header } from "@/components/layout/header";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
import { useUserProfile } from "@/lib/user-profile";
import { can } from "@/lib/permissions";
import { DynamicField, type FormFieldDef } from "@/components/cards/dynamic-field";

const SECTION_LABELS: Record<string, string> = {
  personal: "Personal Information",
  contact: "Contact Details",
  address: "Address",
  survey: "Survey Responses",
  followup: "Follow-Up",
  custom: "Custom Fields",
};

const SECTION_ORDER = ["personal", "contact", "address", "survey", "followup", "custom"];

const SECTION_ICONS: Record<string, string> = {
  personal: "user",
  contact: "user",
  address: "user",
  survey: "clipboardList",
  followup: "clipboardCheck",
  custom: "clipboardList",
};

const MESSAGE_TOPIC_OPTIONS = [
  "Stress/Anxiety", "Marriage", "Hearing God's Voice", "Dealing With Doubt",
  "Parenting", "Grief & Loss", "Forgiveness", "Finances", "Purpose/Calling",
  "Prayer", "Healthy Boundaries", "Understanding The Bible", "Emotional Health",
  "Sharing My Faith", "Decision Making", "Spiritual Disciplines", "Spiritual Gifts",
];

const NEXT_STEP_OPTIONS = ["Baptism", "Next Steps"];

const CAMPUS_OPTIONS = ["Beulah", "Pace/Milton", "Gulf Breeze", "Warrington"];

const HOW_HEARD_OPTIONS = [
  "This is my church home", "Regular Attender", "Drove by",
  "Social Media", "Google", "Personal Invite",
];

type TemplateData = {
  id: string;
  name: string;
  fields: FormFieldDef[];
};

type CardData = {
  id: string;
  firstName: string | null;
  lastName: string | null;
  name: string | null;
  gender: string | null;
  dateOfBirth: string | null;
  maritalStatus: string | null;
  maritalStatusOther: string | null;
  visitType: string | null;
  cellPhone: string | null;
  homePhone: string | null;
  email: string | null;
  address: string | null;
  aptNumber: string | null;
  city: string | null;
  state: string | null;
  zip: string | null;
  prayerRequests: string | null;
  prayerForTeam: boolean;
  prayerConfidential: boolean;
  messageTopics: string[] | null;
  messageTopicsOther: string | null;
  nextStep: string[] | null;
  attendanceDuration: string | null;
  campusPreference: string[] | null;
  campusPreferenceOther: string | null;
  howHeard: string[] | null;
  howHeardOther: string | null;
  serviceAttended: string | null;
  followUp: string | null;
  notes: string | null;
  serviceTime: string | null;
  planningCenter: string | null;
  iSaidYesBookSent: boolean;
  ftGuestLetterSent: boolean;
  firstTimeGuestDate: string | null;
  salvationDate: string | null;
  assignedToId: string | null;
  assignedById: string | null;
  assignedAt: string | null;
  reviewedById: string | null;
  reviewedAt: string | null;
  reviewNotes: string | null;
  ocrStatus: string;
  reviewStatus: string;
  ocrConfidence: number | null;
  ocrError: string | null;
  rawOcrResponse: Record<string, unknown> | null;
  mondayItemId: string | null;
  frontImageUrl: string | null;
  backImageUrl: string | null;
  fieldData: Record<string, unknown> | null;
  formTemplateId: string | null;
  formTemplate?: TemplateData | null;
};

type ActivityEntry = {
  id: string;
  createdAt: string;
  action: string;
  source: string;
  summary: string;
  changes: { field: string; from: string | null; to: string | null }[] | null;
};

type AssignableUser = { id: string; displayName: string };

export default function CardDetailPage() {
  const params = useParams();
  const router = useRouter();
  const id = params.id as string;
  const { role, userId } = useUserProfile();
  const isAdmin = role === "admin" || role === "owner";
  const isReviewer = role === "reviewer";
  const isViewer = role === "viewer";
  const canEditAnyCard = can(role, "cards.edit");
  const canReprocess = can(role, "cards.reprocess");
  const canAssign = can(role, "cards.assign");
  const canExport = can(role, "cards.edit");

  const [card, setCard] = React.useState<CardData | null>(null);
  const [loadError, setLoadError] = React.useState(false);
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [reprocessing, setReprocessing] = React.useState(false);
  const [edits, setEdits] = React.useState<Record<string, unknown>>({});
  const [showRawOcr, setShowRawOcr] = React.useState(false);
  const [showActivity, setShowActivity] = React.useState(false);
  const [activityLog, setActivityLog] = React.useState<ActivityEntry[]>([]);
  const [activityLoading, setActivityLoading] = React.useState(false);
  const [expandedEntry, setExpandedEntry] = React.useState<string | null>(null);
  const [pushingToMonday, setPushingToMonday] = React.useState(false);
  const [users, setUsers] = React.useState<AssignableUser[]>([]);
  const [prevNextIds, setPrevNextIds] = React.useState<{ prev: string | null; next: string | null }>({ prev: null, next: null });
  const [templateFields, setTemplateFields] = React.useState<FormFieldDef[] | null>(null);
  const [fieldDataEdits, setFieldDataEdits] = React.useState<Record<string, unknown>>({});

  const isAssignedToMe = card?.assignedToId && userId === card.assignedToId;
  const canEdit = canEditAnyCard || (isReviewer && !!isAssignedToMe);
  const canMarkComplete = canEditAnyCard || (isReviewer && !!isAssignedToMe);

  const fetchCard = React.useCallback(async () => {
    setLoading(true);
    setLoadError(false);
    try {
      const res = await fetch(`/api/cards/${id}`);
      if (!res.ok) throw new Error();
      const data = await res.json();
      setCard(data);
      setEdits({});
      setFieldDataEdits({});

      if (data.formTemplate?.fields) {
        setTemplateFields(data.formTemplate.fields);
      } else if (!data.formTemplateId) {
        fetch("/api/form-templates?default=true")
          .then((r) => r.json())
          .then((d) => {
            if (d.template?.fields) setTemplateFields(d.template.fields);
          })
          .catch(() => {});
      }
    } catch {
      setLoadError(true);
      toast.error("Failed to load card");
    } finally {
      setLoading(false);
    }
  }, [id]);

  React.useEffect(() => {
    fetchCard();
  }, [fetchCard]);

  React.useEffect(() => {
    if (!canAssign) return;
    fetch("/api/users")
      .then((r) => r.json())
      .then((data) => setUsers(data.users || []))
      .catch(() => {});
  }, [canAssign]);

  React.useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const assignedToId = params.get("assignedToId") || (isReviewer ? "me" : undefined);
    const apiParams = new URLSearchParams();
    apiParams.set("limit", "200");
    if (assignedToId) apiParams.set("assignedToId", assignedToId);

    fetch(`/api/cards?${apiParams.toString()}`)
      .then((r) => r.json())
      .then((data) => {
        const ids = (data.cards || []).map((c: { id: string }) => c.id);
        const idx = ids.indexOf(id);
        setPrevNextIds({
          prev: idx > 0 ? ids[idx - 1] : null,
          next: idx >= 0 && idx < ids.length - 1 ? ids[idx + 1] : null,
        });
      })
      .catch(() => {});
  }, [id, isReviewer]);

  React.useEffect(() => {
    if (card?.ocrStatus !== "processing") return;
    const interval = setInterval(async () => {
      try {
        const res = await fetch(`/api/cards/${id}`);
        if (!res.ok) return;
        const data = await res.json();
        setCard(data);
        if (data.ocrStatus !== "processing") {
          setReprocessing(false);
          if (data.ocrStatus === "complete") toast.success("Reprocessing complete");
          if (data.ocrStatus === "error") toast.error("Reprocessing failed");
        }
      } catch { /* ignore polling errors */ }
    }, 3000);
    return () => clearInterval(interval);
  }, [card?.ocrStatus, id]);

  const getValue = (field: keyof CardData): string => {
    if (field in edits) return String(edits[field] ?? "");
    const val = card?.[field];
    if (val === null || val === undefined) return "";
    return String(val);
  };

  const getArrayValue = (field: keyof CardData): string[] => {
    if (field in edits) return (edits[field] as string[]) ?? [];
    const val = card?.[field];
    if (Array.isArray(val)) return val;
    return [];
  };

  const getBoolValue = (field: keyof CardData): boolean => {
    if (field in edits) return Boolean(edits[field]);
    return Boolean(card?.[field]);
  };

  const getDateValue = (field: keyof CardData): string => {
    if (field in edits) {
      const v = edits[field];
      if (!v) return "";
      return String(v).slice(0, 10);
    }
    const val = card?.[field];
    if (!val) return "";
    return String(val).slice(0, 10);
  };

  const setField = (field: string, value: unknown) => {
    setEdits((prev) => ({ ...prev, [field]: value }));
  };

  const getDynamicValue = React.useCallback(
    (field: FormFieldDef): unknown => {
      if (field.isCore) {
        const key = field.key;
        if (key in edits) return edits[key];
        return (card as unknown as Record<string, unknown>)?.[key] ?? null;
      }
      if (field.key in fieldDataEdits) return fieldDataEdits[field.key];
      const fd = card?.fieldData as Record<string, unknown> | null;
      if (fd && field.key in fd) return fd[field.key];
      if (card && field.key in (card as unknown as Record<string, unknown>)) {
        return (card as unknown as Record<string, unknown>)[field.key];
      }
      return null;
    },
    [card, edits, fieldDataEdits]
  );

  const setDynamicValue = React.useCallback(
    (field: FormFieldDef, value: unknown) => {
      if (field.isCore) {
        setEdits((prev) => ({ ...prev, [field.key]: value }));
      } else {
        setFieldDataEdits((prev) => ({ ...prev, [field.key]: value }));
      }
    },
    []
  );

  const dynamicSections = React.useMemo(() => {
    if (!templateFields) return null;
    const grouped: Record<string, FormFieldDef[]> = {};
    for (const field of templateFields) {
      if (!grouped[field.section]) grouped[field.section] = [];
      grouped[field.section].push(field);
    }
    return SECTION_ORDER
      .filter((s) => grouped[s]?.length > 0)
      .map((s) => ({
        key: s,
        label: SECTION_LABELS[s] || s,
        iconKey: SECTION_ICONS[s] || "clipboardList",
        fields: grouped[s],
      }));
  }, [templateFields]);

  const handleSave = async () => {
    const hasFieldDataChanges = Object.keys(fieldDataEdits).length > 0;
    if (Object.keys(edits).length === 0 && !hasFieldDataChanges) return;
    setSaving(true);
    try {
      const payload: Record<string, unknown> = { ...edits };
      if (hasFieldDataChanges) {
        const currentFieldData = (card?.fieldData as Record<string, unknown>) || {};
        payload.fieldData = { ...currentFieldData, ...fieldDataEdits };
      }
      if (card?.reviewStatus === "assigned") {
        payload.reviewStatus = "in_review";
      }
      const res = await fetch(`/api/cards/${id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const err = await res.json();
        throw new Error(err.error || "Failed to save");
      }
      toast.success("Card updated");
      await fetchCard();
      router.refresh();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed to save");
    } finally {
      setSaving(false);
    }
  };

  const handleMarkComplete = async () => {
    setSaving(true);
    try {
      const payload: Record<string, unknown> = {
        ...edits,
        reviewStatus: "reviewed",
      };
      if (Object.keys(fieldDataEdits).length > 0) {
        const currentFieldData = (card?.fieldData as Record<string, unknown>) || {};
        payload.fieldData = { ...currentFieldData, ...fieldDataEdits };
      }
      const res = await fetch(`/api/cards/${id}`, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const err = await res.json();
        throw new Error(err.error || "Failed to complete review");
      }
      toast.success("Review complete — card will sync to Monday.com");
      await fetchCard();
      setEdits({});
      router.refresh();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed to complete review");
    } finally {
      setSaving(false);
    }
  };

  const handleReassign = async (userId: string) => {
    try {
      const res = await fetch("/api/cards/assign", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ cardIds: [id], assignToUserId: userId }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error);
      toast.success(`Reassigned to ${data.assignee}`);
      fetchCard();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Reassignment failed");
    }
  };

  const handleMarkReviewed = async () => {
    await fetch(`/api/cards/${id}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ reviewStatus: "reviewed" }),
    });
    toast.success("Marked as reviewed");
    fetchCard();
  };

  const handleExport = async () => {
    await fetch(`/api/cards/${id}/export`, { method: "POST" });
    toast.success("Marked as exported");
    fetchCard();
  };

  const handleReprocess = async () => {
    setReprocessing(true);
    try {
      const res = await fetch(`/api/cards/${id}/reprocess`, { method: "POST" });
      if (!res.ok) {
        const err = await res.json();
        throw new Error(err.error || "Failed to start reprocessing");
      }
      toast.success("Reprocessing started");
      await fetchCard();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed to start reprocessing");
      setReprocessing(false);
    }
  };

  const handlePushToMonday = async () => {
    setPushingToMonday(true);
    try {
      const res = await fetch(`/api/integrations/monday/push/${id}`, { method: "POST" });
      const data = await res.json();
      if (res.ok) {
        toast.success(data.action === "created" ? "Pushed to Monday.com" : "Updated in Monday.com");
        fetchCard();
      } else {
        toast.error(data.error || "Push to Monday.com failed");
      }
    } catch {
      toast.error("Failed to push to Monday.com");
    } finally {
      setPushingToMonday(false);
    }
  };

  const fetchActivity = React.useCallback(async () => {
    setActivityLoading(true);
    try {
      const res = await fetch(`/api/cards/${id}/activity`);
      if (res.ok) setActivityLog(await res.json());
    } catch { /* ignore */ }
    finally { setActivityLoading(false); }
  }, [id]);

  React.useEffect(() => {
    if (showActivity) fetchActivity();
  }, [showActivity, fetchActivity]);

  if (loading) {
    return (
      <div className="space-y-6">
        <Skeleton className="h-10 w-64 rounded-xl" />
        <div className="grid gap-4 sm:gap-6 grid-cols-1 lg:grid-cols-2">
          <Skeleton className="h-96 rounded-2xl" />
          <Skeleton className="h-96 rounded-2xl" />
        </div>
      </div>
    );
  }

  if (!card) {
    return (
      <div className="space-y-6">
        <Header title={loadError ? "Failed to Load Card" : "Card Not Found"} icon={loadError ? AlertCircle : ScanLine} />
        <div className="glass-card flex flex-col items-center justify-center rounded-2xl p-12 text-center">
          <AlertCircle className="mb-4 size-12 text-muted-foreground/40" />
          <h2 className="text-lg font-semibold">
            {loadError ? "Something went wrong" : "This card doesn't exist"}
          </h2>
          <p className="mt-1 max-w-sm text-sm text-muted-foreground">
            {loadError
              ? "We couldn't load this card. Check your connection and try again."
              : "The card you're looking for may have been deleted or the link is incorrect."}
          </p>
          <div className="mt-6 flex gap-3">
            {loadError && (
              <Button variant="outline" className="rounded-xl" onClick={fetchCard}>
                <RefreshCw className="mr-2 size-4" /> Retry
              </Button>
            )}
            <Button variant="outline" className="rounded-xl" onClick={() => router.push("/cards")}>
              <ArrowLeft className="mr-2 size-4" /> Go back to cards
            </Button>
          </div>
        </div>
      </div>
    );
  }

  const confidence = card.ocrConfidence;
  const ocrStatus = card.ocrStatus;
  const reviewStatus = card.reviewStatus;
  const hasEdits = Object.keys(edits).length > 0 || Object.keys(fieldDataEdits).length > 0;

  // Compute the header title from in-flight edits so it updates live as the
  // user types. Falls back through edits → fieldData edits → card columns →
  // legacy `card.name` so it works for both core and non-core templates.
  const editedFirst =
    "firstName" in edits
      ? String(edits.firstName ?? "")
      : "firstName" in fieldDataEdits
        ? String(fieldDataEdits.firstName ?? "")
        : (card.firstName ?? "");
  const editedLast =
    "lastName" in edits
      ? String(edits.lastName ?? "")
      : "lastName" in fieldDataEdits
        ? String(fieldDataEdits.lastName ?? "")
        : (card.lastName ?? "");
  const displayName =
    [editedFirst, editedLast].filter(Boolean).join(" ").trim() ||
    card.name ||
    "Unnamed Card";

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4">
        <Button variant="ghost" size="sm" className="w-fit rounded-xl" onClick={() => router.push("/")}>
          <ArrowLeft className="mr-1 size-4" /> Back
        </Button>
        <div className="flex flex-wrap items-center gap-2">
          <Badge variant="secondary" className={cn(
            "capitalize",
            ocrStatus === "complete" && "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
            ocrStatus === "error" && "bg-red-500/10 text-red-700 dark:text-red-300",
            ocrStatus === "processing" && "bg-primary/10 text-primary",
          )}>
            OCR: {ocrStatus}
          </Badge>
          <Badge variant="secondary" className={cn(
            "capitalize",
            reviewStatus === "reviewed" && "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
            reviewStatus === "exported" && "bg-primary/10 text-primary",
            reviewStatus === "unreviewed" && "bg-amber-500/10 text-amber-700 dark:text-amber-300",
          )}>
            {reviewStatus}
          </Badge>
          {confidence != null && (
            <Badge variant="outline" className={cn(
              "font-medium",
              confidence < 50 && "text-red-600 border-red-300 dark:border-red-800",
              confidence >= 50 && confidence <= 75 && "text-amber-600 border-amber-300 dark:border-amber-800",
              confidence > 75 && "text-emerald-600 border-emerald-300 dark:border-emerald-800",
            )}>
              {Math.round(confidence)}% confidence
            </Badge>
          )}
        </div>
      </div>

      {card.assignedToId && (
        <div className="flex items-center gap-2 rounded-xl border border-purple-300 bg-purple-500/10 px-4 py-2.5 dark:border-purple-800">
          <User className="size-4 text-purple-600 dark:text-purple-400" />
          <span className="text-sm">
            Assigned to <strong>{card.assignedToId === userId ? "you" : (card.assignedToId)}</strong>
            {card.assignedAt && (
              <> on {new Date(card.assignedAt).toLocaleDateString()}</>
            )}
          </span>
          {card.reviewedById && card.reviewedAt && (
            <span className="text-sm text-muted-foreground ml-2">
              · Reviewed {new Date(card.reviewedAt).toLocaleDateString()}
            </span>
          )}
        </div>
      )}

      <Header title={displayName} icon={ScanLine}>
        <div className="flex flex-wrap gap-2">
          {canReprocess && ocrStatus !== "processing" && (
            <Button variant="outline" size="sm" className="rounded-xl" onClick={handleReprocess} disabled={reprocessing}>
              {reprocessing ? (
                <><Loader2 className="mr-1 size-4 animate-spin" /> Reprocessing...</>
              ) : (
                <><RefreshCw className="mr-1 size-4" /> Reprocess</>
              )}
            </Button>
          )}
          {ocrStatus === "processing" && (
            <Badge variant="secondary" className="bg-primary/10 text-primary gap-1.5 py-1.5 px-3">
              <Loader2 className="size-3.5 animate-spin" /> Processing...
            </Badge>
          )}
          {isAdmin && (
            <Button
              variant="outline"
              size="sm"
              className="rounded-xl"
              onClick={handlePushToMonday}
              disabled={pushingToMonday || ocrStatus !== "complete"}
            >
              {pushingToMonday ? (
                <><Loader2 className="mr-1 size-4 animate-spin" /> Pushing...</>
              ) : (
                <><LayoutGrid className="mr-1 size-4" /> {card.mondayItemId ? "Update Monday" : "Push to Monday"}</>
              )}
            </Button>
          )}
          {canAssign && users.length > 0 && (
            <Select onValueChange={(v: string | null) => { if (v) handleReassign(v); }}>
              <SelectTrigger className="w-[160px] rounded-xl h-8 text-sm">
                <SelectValue placeholder="Reassign..." />
              </SelectTrigger>
              <SelectContent>
                {users.map((u) => (
                  <SelectItem key={u.id} value={u.id}>{u.displayName}</SelectItem>
                ))}
              </SelectContent>
            </Select>
          )}
          {canMarkComplete && reviewStatus !== "reviewed" && reviewStatus !== "exported" && (
            <Button size="sm" className="rounded-xl bg-emerald-600 hover:bg-emerald-700 text-white" onClick={handleMarkComplete} disabled={saving}>
              <Check className="mr-1 size-4" /> Mark Complete
            </Button>
          )}
          {canExport && reviewStatus !== "exported" && (
            <Button variant="outline" size="sm" className="rounded-xl" onClick={handleExport}>
              <Download className="mr-1 size-4" /> Export
            </Button>
          )}
          {hasEdits && canEdit && (
            <Button size="sm" className="rounded-xl" onClick={handleSave} disabled={saving}>
              {saving ? "Saving..." : "Save Changes"}
            </Button>
          )}
        </div>
      </Header>

      {ocrStatus === "error" && card.ocrError && (
        <div className="flex items-start gap-3 rounded-xl border border-red-300 bg-red-500/10 p-4 dark:border-red-800">
          <AlertCircle className="mt-0.5 size-4 shrink-0 text-red-600 dark:text-red-400" />
          <div>
            <p className="text-sm font-medium text-red-700 dark:text-red-300">OCR Processing Error</p>
            <p className="mt-0.5 text-sm text-red-600 dark:text-red-400">{card.ocrError}</p>
          </div>
        </div>
      )}

      <div className="grid gap-4 sm:gap-6 grid-cols-1 xl:grid-cols-2">
        <Card variant="glass">
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <ImageIcon className="size-4 text-primary" />
              Scanned Images
            </CardTitle>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="grid gap-4 grid-cols-1 sm:grid-cols-2">
              <ImagePanel label="Response Card (Front)" url={card.backImageUrl as string | null} />
              <ImagePanel label="Survey (Back)" url={card.frontImageUrl as string | null} />
            </div>
          </CardContent>
        </Card>

        {dynamicSections ? (
          dynamicSections.map((section) => {
            const IconComp =
              section.iconKey === "user" ? User :
              section.iconKey === "clipboardCheck" ? ClipboardCheck :
              ClipboardList;
            const isWide = section.key === "survey" || section.key === "custom";
            return (
              <Card key={section.key} variant="glass" className={isWide ? "xl:col-span-2" : ""}>
                <CardHeader>
                  <CardTitle className="flex items-center gap-2 text-base">
                    <IconComp className="size-4 text-primary" />
                    {section.label}
                  </CardTitle>
                </CardHeader>
                <CardContent>
                  <div className={cn(
                    "grid gap-4 grid-cols-1 sm:grid-cols-2",
                    isWide && "lg:grid-cols-3"
                  )}>
                    {section.fields.map((field) => (
                      <DynamicField
                        key={field.id}
                        field={field}
                        value={getDynamicValue(field)}
                        onChange={(v) => setDynamicValue(field, v)}
                        readOnly={!canEdit}
                      />
                    ))}
                  </div>
                </CardContent>
              </Card>
            );
          })
        ) : (
          <>
            <Card variant="glass">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <User className="size-4 text-primary" />
                  Personal Information
                </CardTitle>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="grid gap-4 grid-cols-1 sm:grid-cols-2">
                  <Field label="Name" value={getValue("name")} onChange={(v) => setField("name", v)} readOnly={!canEdit} />
                  <Field label="Email" value={getValue("email")} onChange={(v) => setField("email", v)} readOnly={!canEdit} />
                  <Field label="Cell Phone" value={getValue("cellPhone")} onChange={(v) => setField("cellPhone", v)} readOnly={!canEdit} />
                  <Field label="Home Phone" value={getValue("homePhone")} onChange={(v) => setField("homePhone", v)} readOnly={!canEdit} />
                  <SelectField label="Gender" value={getValue("gender")} options={["Male", "Female"]} onChange={(v) => setField("gender", v)} readOnly={!canEdit} />
                  <Field label="Date of Birth" value={getValue("dateOfBirth")} onChange={(v) => setField("dateOfBirth", v)} readOnly={!canEdit} />
                  <SelectField label="Marital Status" value={getValue("maritalStatus")} options={["Married", "Single", "Other"]} onChange={(v) => setField("maritalStatus", v)} readOnly={!canEdit} />
                  <SelectField label="Visit Type" value={getValue("visitType")} options={["First/Second Time Guest", "Update My Information"]} onChange={(v) => setField("visitType", v)} readOnly={!canEdit} />
                </div>
                <Separator className="opacity-50" />
                <div className="grid gap-4 grid-cols-1 sm:grid-cols-2">
                  <Field label="Address" value={getValue("address")} onChange={(v) => setField("address", v)} readOnly={!canEdit} />
                  <Field label="Apt #" value={getValue("aptNumber")} onChange={(v) => setField("aptNumber", v)} readOnly={!canEdit} />
                  <Field label="City" value={getValue("city")} onChange={(v) => setField("city", v)} readOnly={!canEdit} />
                  <Field label="State" value={getValue("state")} onChange={(v) => setField("state", v)} readOnly={!canEdit} />
                  <Field label="Zip" value={getValue("zip")} onChange={(v) => setField("zip", v)} readOnly={!canEdit} />
                </div>
                <Separator className="opacity-50" />
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Prayer Requests</Label>
                  <Textarea
                    value={getValue("prayerRequests") || ""}
                    onChange={(e) => setField("prayerRequests", e.target.value)}
                    rows={3}
                    readOnly={!canEdit}
                    className={!canEdit ? "opacity-70 cursor-default" : ""}
                  />
                </div>
                <div className="flex flex-wrap gap-6">
                  <BooleanField label="For Prayer Team" value={getBoolValue("prayerForTeam")} onChange={(v) => setField("prayerForTeam", v)} readOnly={!canEdit} />
                  <BooleanField label="Confidential" value={getBoolValue("prayerConfidential")} onChange={(v) => setField("prayerConfidential", v)} readOnly={!canEdit} />
                </div>
              </CardContent>
            </Card>

            <Card variant="glass" className="xl:col-span-2">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <ClipboardList className="size-4 text-primary" />
                  Survey Responses
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div className="grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
                  <MultiSelectField
                    label="Message Topics"
                    value={getArrayValue("messageTopics")}
                    options={MESSAGE_TOPIC_OPTIONS}
                    onChange={(v) => setField("messageTopics", v)}
                    readOnly={!canEdit}
                  />
                  <MultiSelectField
                    label="Next Steps"
                    value={getArrayValue("nextStep")}
                    options={NEXT_STEP_OPTIONS}
                    onChange={(v) => setField("nextStep", v)}
                    readOnly={!canEdit}
                  />
                  <SelectField label="Attendance Duration" value={getValue("attendanceDuration")} options={["Less than 6 months", "6 Months - 1 Year", "1-3 Years", "4-6 Years", "7+ Years"]} onChange={(v) => setField("attendanceDuration", v)} readOnly={!canEdit} />
                  <MultiSelectField
                    label="Campus Preference"
                    value={getArrayValue("campusPreference")}
                    options={CAMPUS_OPTIONS}
                    onChange={(v) => setField("campusPreference", v)}
                    readOnly={!canEdit}
                  />
                  <MultiSelectField
                    label="How Heard"
                    value={getArrayValue("howHeard")}
                    options={HOW_HEARD_OPTIONS}
                    onChange={(v) => setField("howHeard", v)}
                    readOnly={!canEdit}
                  />
                  <SelectField label="Service Attended" value={getValue("serviceAttended")} options={["A", "B", "C", "D"]} onChange={(v) => setField("serviceAttended", v)} readOnly={!canEdit} />
                </div>
              </CardContent>
            </Card>
          </>
        )}

        <Card variant="glass" className="xl:col-span-2">
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <ClipboardCheck className="size-4 text-primary" />
              Workflow & Tracking
            </CardTitle>
          </CardHeader>
          <CardContent>
            <div className="grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
              <Field label="Follow-Up" value={getValue("followUp")} onChange={(v) => setField("followUp", v)} readOnly={!canEdit} />
              <Field label="Service Time" value={getValue("serviceTime")} onChange={(v) => setField("serviceTime", v)} readOnly={!canEdit} />
              <Field label="Planning Center" value={getValue("planningCenter")} onChange={(v) => setField("planningCenter", v)} readOnly={!canEdit} />
              <DateField label="First Time Guest Date" value={getDateValue("firstTimeGuestDate")} onChange={(v) => setField("firstTimeGuestDate", v || null)} readOnly={!canEdit} />
              <DateField label="Salvation Date" value={getDateValue("salvationDate")} onChange={(v) => setField("salvationDate", v || null)} readOnly={!canEdit} />
              <BooleanField label="I Said Yes Book Sent" value={getBoolValue("iSaidYesBookSent")} onChange={(v) => setField("iSaidYesBookSent", v)} readOnly={!canEdit} />
              <BooleanField label="FT Guest Letter Sent" value={getBoolValue("ftGuestLetterSent")} onChange={(v) => setField("ftGuestLetterSent", v)} readOnly={!canEdit} />
            </div>
            {(getValue("notes") || canEdit) && (
              <>
                <Separator className="my-4 opacity-50" />
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Notes</Label>
                  <Textarea
                    value={getValue("notes")}
                    onChange={(e) => setField("notes", e.target.value)}
                    rows={3}
                    readOnly={!canEdit}
                    className={!canEdit ? "opacity-70 cursor-default" : ""}
                  />
                </div>
              </>
            )}
          </CardContent>
        </Card>

        {card.rawOcrResponse && (
          <Card variant="glass" className="xl:col-span-2">
            <CardHeader>
              <button
                className="flex w-full items-center justify-between text-left"
                onClick={() => setShowRawOcr(!showRawOcr)}
              >
                <CardTitle className="flex items-center gap-2 text-base">
                  <Code className="size-4 text-primary" />
                  Raw OCR Response
                </CardTitle>
                {showRawOcr ? <ChevronUp className="size-4" /> : <ChevronDown className="size-4" />}
              </button>
            </CardHeader>
            {showRawOcr && (
              <CardContent>
                <pre className="max-h-96 overflow-auto rounded-xl bg-muted/50 p-4 text-xs">
                  {JSON.stringify(card.rawOcrResponse, null, 2)}
                </pre>
              </CardContent>
            )}
          </Card>
        )}
      </div>

      <Card variant="glass">
        <CardHeader>
          <button
            className="flex w-full items-center justify-between text-left"
            onClick={() => setShowActivity(!showActivity)}
          >
            <CardTitle className="flex items-center gap-2 text-base">
              <Activity className="size-4 text-primary" />
              Activity Log
            </CardTitle>
            {showActivity ? <ChevronUp className="size-4" /> : <ChevronDown className="size-4" />}
          </button>
        </CardHeader>
        {showActivity && (
          <CardContent>
            {activityLoading ? (
              <div className="flex items-center justify-center py-6">
                <Loader2 className="size-5 animate-spin text-muted-foreground" />
              </div>
            ) : activityLog.length === 0 ? (
              <p className="text-sm text-muted-foreground text-center py-6">No activity recorded yet</p>
            ) : (
              <div className="space-y-0">
                {activityLog.map((entry) => {
                  const isExpanded = expandedEntry === entry.id;
                  const hasChanges = entry.changes && entry.changes.length > 0;
                  const sourceColor =
                    entry.source === "monday.com" ? "bg-blue-500/10 text-blue-700 dark:text-blue-300" :
                    entry.source === "user" ? "bg-amber-500/10 text-amber-700 dark:text-amber-300" :
                    "bg-muted text-muted-foreground";
                  const sourceIcon =
                    entry.source === "monday.com" ? <LayoutGrid className="size-3" /> :
                    entry.source === "user" ? <User className="size-3" /> :
                    <Monitor className="size-3" />;

                  return (
                    <div key={entry.id} className="relative flex gap-3 py-2.5">
                      <div className="flex flex-col items-center">
                        <div className={cn("flex size-6 shrink-0 items-center justify-center rounded-full", sourceColor)}>
                          {sourceIcon}
                        </div>
                        <div className="w-px flex-1 bg-border/50" />
                      </div>
                      <div className="min-w-0 flex-1 pb-2">
                        <div className="flex items-center gap-2 mb-0.5">
                          <Badge variant="secondary" className={cn("text-[10px] px-1.5 py-0 capitalize", sourceColor)}>
                            {entry.source}
                          </Badge>
                          <span className="text-[10px] text-muted-foreground flex items-center gap-1">
                            <Clock className="size-2.5" />
                            {formatTimeAgo(entry.createdAt)}
                          </span>
                        </div>
                        <button
                          className={cn("text-sm text-left", hasChanges && "hover:underline cursor-pointer")}
                          onClick={() => hasChanges && setExpandedEntry(isExpanded ? null : entry.id)}
                          disabled={!hasChanges}
                        >
                          {entry.summary}
                        </button>
                        {isExpanded && entry.changes && (
                          <div className="mt-2 space-y-1 rounded-lg border border-border/50 bg-muted/20 p-2.5">
                            {entry.changes.map((ch, i) => (
                              <div key={i} className="text-xs">
                                <span className="font-medium capitalize text-foreground">{ch.field}: </span>
                                {ch.from && <span className="text-muted-foreground line-through mr-1">{ch.from}</span>}
                                {ch.from && ch.to && <span className="text-muted-foreground mr-1">&rarr;</span>}
                                {ch.to && <span className="text-emerald-600 dark:text-emerald-400">{ch.to}</span>}
                              </div>
                            ))}
                          </div>
                        )}
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </CardContent>
        )}
      </Card>

      <div className="flex flex-col gap-3 border-t border-border/50 pt-4 sm:flex-row sm:items-center sm:justify-between">
        <Button variant="outline" size="sm" className="w-fit rounded-xl" onClick={() => router.push("/")}>
          <ArrowLeft className="mr-1 size-4" /> All Cards
        </Button>
        <div className="flex gap-2">
          <Button
            variant="outline"
            size="sm"
            className="rounded-xl"
            disabled={!prevNextIds.prev}
            onClick={() => prevNextIds.prev && router.push(`/cards/${prevNextIds.prev}`)}
          >
            <ArrowLeft className="mr-1 size-4" /> Previous
          </Button>
          <Button
            variant="outline"
            size="sm"
            className="rounded-xl"
            disabled={!prevNextIds.next}
            onClick={() => prevNextIds.next && router.push(`/cards/${prevNextIds.next}`)}
          >
            Next <ArrowRight className="ml-1 size-4" />
          </Button>
        </div>
      </div>
    </div>
  );
}

function ImagePanel({ label, url }: { label: string; url: string | null }) {
  const [lightboxOpen, setLightboxOpen] = React.useState(false);

  React.useEffect(() => {
    if (!lightboxOpen) return;
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") setLightboxOpen(false);
    };
    window.addEventListener("keydown", handleKey);
    return () => window.removeEventListener("keydown", handleKey);
  }, [lightboxOpen]);

  return (
    <div>
      <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">{label}</Label>
      {url ? (
        <div className="group relative aspect-[3/4] overflow-hidden rounded-xl border border-border/50 bg-muted/30">
          <Image src={url} alt={label} fill className="object-contain" unoptimized />
          <button
            type="button"
            onClick={() => setLightboxOpen(true)}
            className="absolute inset-0 flex items-center justify-center bg-black/0 opacity-0 transition-all group-hover:bg-black/20 group-hover:opacity-100"
          >
            <div className="rounded-full bg-background/90 p-2 shadow-lg">
              <Maximize2 className="size-4 text-foreground" />
            </div>
          </button>
        </div>
      ) : (
        <div className="flex aspect-[3/4] items-center justify-center rounded-xl border border-border/50 bg-muted/20">
          <ImageIcon className="size-12 text-muted-foreground/20" />
        </div>
      )}

      {lightboxOpen && url && (
        <div
          className="fixed inset-0 z-[100] flex items-center justify-center bg-black/80 backdrop-blur-sm animate-in fade-in-0 duration-200"
          onClick={() => setLightboxOpen(false)}
        >
          <button
            type="button"
            onClick={() => setLightboxOpen(false)}
            className="absolute right-4 top-4 z-10 rounded-full bg-background/20 p-2 text-white transition-colors hover:bg-background/40"
          >
            <X className="size-6" />
          </button>
          <div
            className="relative max-h-[90vh] max-w-[90vw]"
            onClick={(e) => e.stopPropagation()}
          >
            <Image
              src={url}
              alt={label}
              width={1200}
              height={1600}
              className="max-h-[90vh] w-auto rounded-lg object-contain"
              unoptimized
            />
          </div>
        </div>
      )}
    </div>
  );
}

function Field({ label, value, onChange, readOnly }: { label: string; value: string; onChange: (v: string) => void; readOnly?: boolean }) {
  return (
    <div>
      <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">{label}</Label>
      <Input value={value || ""} onChange={(e) => onChange(e.target.value)} readOnly={readOnly} className={readOnly ? "opacity-70 cursor-default" : ""} />
    </div>
  );
}

function formatTimeAgo(dateStr: string): string {
  const diff = Date.now() - new Date(dateStr).getTime();
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hours = Math.floor(mins / 60);
  if (hours < 24) return `${hours}h ago`;
  const days = Math.floor(hours / 24);
  if (days < 30) return `${days}d ago`;
  return new Date(dateStr).toLocaleDateString();
}

function SelectField({ label, value, options, onChange, readOnly }: { label: string; value: string; options: string[]; onChange: (v: string) => void; readOnly?: boolean }) {
  if (readOnly) {
    return (
      <div>
        <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">{label}</Label>
        <Input value={value || "—"} readOnly className="opacity-70 cursor-default" />
      </div>
    );
  }
  return (
    <div>
      <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">{label}</Label>
      <Select value={value || "__none__"} onValueChange={(v: string | null) => onChange(!v || v === "__none__" ? "" : v)}>
        <SelectTrigger>
          <SelectValue placeholder={`Select ${label.toLowerCase()}`} />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="__none__">—</SelectItem>
          {options.map((opt) => (
            <SelectItem key={opt} value={opt}>{opt}</SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
}

function MultiSelectField({
  label,
  value,
  options,
  onChange,
  readOnly,
}: {
  label: string;
  value: string[];
  options: string[];
  onChange: (v: string[]) => void;
  readOnly?: boolean;
}) {
  const selected = new Set(value);

  const toggle = (opt: string) => {
    if (readOnly) return;
    const next = new Set(selected);
    if (next.has(opt)) next.delete(opt);
    else next.add(opt);
    onChange(Array.from(next));
  };

  return (
    <div>
      <Label className="mb-2 block text-xs font-medium text-muted-foreground">{label}</Label>
      <div className="flex flex-wrap gap-1.5">
        {options.map((opt) => {
          const isOn = selected.has(opt);
          return (
            <button
              key={opt}
              type="button"
              onClick={() => toggle(opt)}
              disabled={readOnly}
              className={cn(
                "inline-flex items-center rounded-lg border px-2.5 py-1 text-xs font-medium transition-colors",
                isOn
                  ? "border-primary/40 bg-primary/10 text-primary hover:bg-primary/20"
                  : "border-border bg-muted/30 text-muted-foreground hover:bg-muted/60 hover:text-foreground",
                readOnly && "cursor-default opacity-70"
              )}
            >
              {opt}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function DateField({ label, value, onChange, readOnly }: { label: string; value: string; onChange: (v: string) => void; readOnly?: boolean }) {
  return (
    <div>
      <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">{label}</Label>
      <Input type="date" value={value || ""} onChange={(e) => onChange(e.target.value)} readOnly={readOnly} className={readOnly ? "opacity-70 cursor-default" : ""} />
    </div>
  );
}

function BooleanField({
  label,
  value,
  onChange,
  readOnly,
}: {
  label: string;
  value: boolean;
  onChange: (v: boolean) => void;
  readOnly?: boolean;
}) {
  return (
    <div className="flex items-center gap-3">
      <Switch checked={value} onCheckedChange={readOnly ? undefined : onChange} size="sm" disabled={readOnly} />
      <Label className={cn("text-sm", readOnly ? "cursor-default opacity-70" : "cursor-pointer")} onClick={readOnly ? undefined : () => onChange(!value)}>
        {label}
      </Label>
    </div>
  );
}
