"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Kpi, KpiStrip } from "@/components/ui/kpi";
import { EmptyState } from "@/components/ui/empty-state";
import { Tooltip } from "@/components/ui/tooltip";
import { useAlertConfirm } from "@/components/ui/alert-dialog";
import { useLocalStorage } from "@/lib/hooks/use-local-storage";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import { formatDate } from "@/lib/utils";
import {
  SOCIAL_PLATFORM_LIST,
  SOCIAL_PLATFORMS,
  type SocialPlatformId,
} from "@/lib/social/platforms";
import {
  captionFor,
  type PostMediaRef,
  type PostStatus,
  type PostVariants,
  type SocialPost,
} from "@/lib/social/post-types";
import { SocialPlatformPreview } from "@/components/app/social-platform-preview";
import { CanvaPicker } from "@/components/app/canva-picker";
import { snapshotForAgentCall } from "@/lib/agents/context-snapshot";

const STATUSES: PostStatus[] = [
  "Draft",
  "Pending Review",
  "Scheduled",
  "Posted",
  "Failed",
  "Cancelled",
];

const STATUS_BADGE: Record<PostStatus, "default" | "info" | "success" | "destructive" | "outline" | "warning"> = {
  Draft: "outline",
  "Pending Review": "warning",
  Scheduled: "info",
  Posted: "success",
  Failed: "destructive",
  Cancelled: "outline",
};

type ViewMode = "list" | "month";

export function SocialCalendar() {
  const [posts, setPosts] = useLocalStorage<SocialPost[]>("sag.social.posts.v2", []);
  const [legacyPosts, setLegacyPosts] = useLocalStorage<LegacyPost[]>("sag.social.posts", []);
  const [showAdd, setShowAdd] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [filterEntity, setFilterEntity] = useState<string>("all");
  const [filterStatus, setFilterStatus] = useState<"all" | PostStatus>("all");
  const [filterPlatform, setFilterPlatform] = useState<"all" | SocialPlatformId>("all");
  const [view, setView] = useState<ViewMode>("list");
  const [monthCursor, setMonthCursor] = useState<Date>(() => new Date());
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const { confirm: confirmAlert, AlertConfirmPortal } = useAlertConfirm();

  // One-shot migration from legacy schema (sag.social.posts → sag.social.posts.v2).
  useEffect(() => {
    if (!legacyPosts || legacyPosts.length === 0) return;
    if (posts.length > 0) return;
    const migrated: SocialPost[] = legacyPosts.map((p) => ({
      id: p.id,
      organizationSlug: p.organizationSlug,
      content: p.content,
      platforms: (p.platforms as SocialPlatformId[]).filter(
        (x): x is SocialPlatformId => x in SOCIAL_PLATFORMS
      ),
      scheduledAt: p.scheduledAt,
      media: (p.mediaUrls ?? []).map((url) => ({
        id: url.split("/").pop() ?? url,
        mime: "image/png",
      })),
      status: p.status === "Draft" ? "Draft" : (p.status as PostStatus),
      notes: p.notes,
      createdAt: p.createdAt,
    }));
    setPosts(migrated);
    setLegacyPosts([]);
    // We deliberately run this once; depending only on legacyPosts.length is fine.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const filtered = useMemo(() => {
    return posts.filter((p) => {
      if (filterEntity !== "all" && p.organizationSlug !== filterEntity) return false;
      if (filterStatus !== "all" && p.status !== filterStatus) return false;
      if (filterPlatform !== "all" && !p.platforms.includes(filterPlatform)) return false;
      return true;
    });
  }, [posts, filterEntity, filterStatus, filterPlatform]);

  const sorted = useMemo(
    () => [...filtered].sort((a, b) => a.scheduledAt.localeCompare(b.scheduledAt)),
    [filtered]
  );

  const stats = useMemo(
    () => ({
      total: posts.length,
      drafts: posts.filter((p) => p.status === "Draft").length,
      pending: posts.filter((p) => p.status === "Pending Review").length,
      scheduled: posts.filter((p) => p.status === "Scheduled").length,
      posted: posts.filter((p) => p.status === "Posted").length,
    }),
    [posts]
  );

  function upsertPost(p: SocialPost) {
    setPosts((prev) => {
      const idx = prev.findIndex((x) => x.id === p.id);
      if (idx >= 0) {
        const copy = [...prev];
        copy[idx] = p;
        return copy;
      }
      return [p, ...prev];
    });
  }

  function newPost(p: Omit<SocialPost, "id" | "createdAt">) {
    const id = `post-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    upsertPost({ ...p, id, createdAt: new Date().toISOString() });
    setShowAdd(false);
    setEditingId(null);
  }

  function updatePost(id: string, patch: Partial<SocialPost>) {
    setPosts((prev) => prev.map((p) => (p.id === id ? { ...p, ...patch } : p)));
  }

  async function deletePost(id: string) {
    const ok = await confirmAlert({
      title: "Delete this post?",
      description: "This permanently removes the record. Cannot be undone.",
      actionLabel: "Delete",
      destructive: true,
    });
    if (!ok) return;
    setPosts((prev) => prev.filter((p) => p.id !== id));
    setSelected((s) => {
      const next = new Set(s);
      next.delete(id);
      return next;
    });
  }

  function reschedule(id: string, newDateISO: string) {
    const current = posts.find((p) => p.id === id);
    if (!current) return;
    const oldDate = new Date(current.scheduledAt);
    const target = new Date(newDateISO);
    target.setHours(oldDate.getHours(), oldDate.getMinutes(), 0, 0);
    updatePost(id, { scheduledAt: target.toISOString() });
  }

  function bulkUpdate(status: PostStatus) {
    if (selected.size === 0) return;
    setPosts((prev) =>
      prev.map((p) =>
        selected.has(p.id)
          ? {
              ...p,
              status,
              approvedAt: status === "Scheduled" ? new Date().toISOString() : p.approvedAt,
              approvedBy: status === "Scheduled" ? "Glenn" : p.approvedBy,
            }
          : p
      )
    );
    setSelected(new Set());
  }

  function bulkReschedule(days: number) {
    if (selected.size === 0) return;
    setPosts((prev) =>
      prev.map((p) => {
        if (!selected.has(p.id)) return p;
        const d = new Date(p.scheduledAt);
        d.setDate(d.getDate() + days);
        return { ...p, scheduledAt: d.toISOString() };
      })
    );
    setSelected(new Set());
  }

  async function bulkDelete() {
    if (selected.size === 0) return;
    const ok = await confirmAlert({
      title: `Delete ${selected.size} post${selected.size === 1 ? "" : "s"}?`,
      description: "This permanently removes the records. Cannot be undone.",
      actionLabel: "Delete",
      destructive: true,
    });
    if (!ok) return;
    setPosts((prev) => prev.filter((p) => !selected.has(p.id)));
    setSelected(new Set());
  }

  const editingPost = editingId ? posts.find((p) => p.id === editingId) : undefined;

  return (
    <>
    <div className="space-y-6">
      <KpiStrip cols={5}>
        <Kpi label="Total" value={String(stats.total)} />
        <Kpi label="Drafts" value={String(stats.drafts)} />
        <Kpi label="Pending review" value={String(stats.pending)} tone="amber" />
        <Kpi label="Scheduled" value={String(stats.scheduled)} tone="violet" />
        <Kpi label="Posted" value={String(stats.posted)} tone="emerald" />
      </KpiStrip>

      <Card>
        <CardContent className="p-4 flex flex-wrap items-center gap-3">
          <select
            value={filterEntity}
            onChange={(e) => setFilterEntity(e.target.value)}
            className="h-10 rounded-md border border-input bg-background px-3 text-sm"
          >
            <option value="all">All entities + managed</option>
            {ALL_ORGANIZATIONS.map((o) => (
              <option key={o.slug} value={o.slug}>
                {o.emoji} {o.name}
              </option>
            ))}
          </select>
          <select
            value={filterStatus}
            onChange={(e) => setFilterStatus(e.target.value as "all" | PostStatus)}
            className="h-10 rounded-md border border-input bg-background px-3 text-sm"
          >
            <option value="all">All statuses</option>
            {STATUSES.map((s) => (
              <option key={s} value={s}>
                {s}
              </option>
            ))}
          </select>
          <select
            value={filterPlatform}
            onChange={(e) => setFilterPlatform(e.target.value as "all" | SocialPlatformId)}
            className="h-10 rounded-md border border-input bg-background px-3 text-sm"
          >
            <option value="all">All platforms</option>
            {SOCIAL_PLATFORM_LIST.map((p) => (
              <option key={p.id} value={p.id}>
                {p.icon} {p.label}
              </option>
            ))}
          </select>
          <span className="text-xs text-muted-foreground tabular-nums">
            {filtered.length} of {posts.length}
          </span>

          <div className="ml-auto flex items-center gap-2">
            <div className="rounded-md border bg-background p-0.5 flex">
              <Button
                variant={view === "list" ? "brand" : "ghost"}
                size="sm"
                onClick={() => setView("list")}
              >
                List
              </Button>
              <Button
                variant={view === "month" ? "brand" : "ghost"}
                size="sm"
                onClick={() => setView("month")}
              >
                Month
              </Button>
            </div>
            <Button
              variant="brand"
              size="sm"
              onClick={() => {
                setShowAdd((v) => !v);
                setEditingId(null);
              }}
            >
              {showAdd ? "Cancel" : "+ Schedule post"}
            </Button>
          </div>
        </CardContent>
      </Card>

      {selected.size > 0 && (
        <Card>
          <CardContent className="p-3 flex items-center gap-2 flex-wrap text-sm">
            <span className="text-muted-foreground">{selected.size} selected</span>
            <Button size="sm" variant="outline" onClick={() => bulkUpdate("Scheduled")}>
              Approve + schedule
            </Button>
            <Button size="sm" variant="outline" onClick={() => bulkUpdate("Pending Review")}>
              Send for review
            </Button>
            <Button size="sm" variant="outline" onClick={() => bulkReschedule(1)}>
              +1 day
            </Button>
            <Button size="sm" variant="outline" onClick={() => bulkReschedule(7)}>
              +1 week
            </Button>
            <Button size="sm" variant="ghost" onClick={bulkDelete}>
              Delete
            </Button>
            <Button size="sm" variant="ghost" className="ml-auto" onClick={() => setSelected(new Set())}>
              Clear selection
            </Button>
          </CardContent>
        </Card>
      )}

      {(showAdd || editingPost) && (
        <PostComposer
          key={editingId ?? "new"}
          initial={editingPost}
          onSave={(post) => {
            if (editingPost) {
              upsertPost({ ...editingPost, ...post });
              setEditingId(null);
            } else {
              newPost(post);
            }
          }}
          onCancel={() => {
            setShowAdd(false);
            setEditingId(null);
          }}
        />
      )}

      {view === "list" ? (
        <ListView
          posts={sorted}
          selected={selected}
          setSelected={setSelected}
          onEdit={(id) => {
            setEditingId(id);
            setShowAdd(false);
          }}
          onStatus={(id, s) => updatePost(id, { status: s })}
          onDelete={deletePost}
        />
      ) : (
        <MonthView
          posts={filtered}
          monthCursor={monthCursor}
          setMonthCursor={setMonthCursor}
          onReschedule={reschedule}
          onEdit={(id) => {
            setEditingId(id);
            setShowAdd(false);
          }}
        />
      )}

      <p className="text-xs text-muted-foreground">
        Posts saved locally. Connect platforms at <a href="/app/social/accounts" className="underline">Accounts</a> — once
        Meta + TikTok + X app reviews land, the “Scheduled” status flips to actual publishing.
      </p>
    </div>
    <AlertConfirmPortal />
    </>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// List view
// ──────────────────────────────────────────────────────────────────────────

function ListView({
  posts,
  selected,
  setSelected,
  onEdit,
  onStatus,
  onDelete,
}: {
  posts: SocialPost[];
  selected: Set<string>;
  setSelected: (s: Set<string>) => void;
  onEdit: (id: string) => void;
  onStatus: (id: string, s: PostStatus) => void;
  onDelete: (id: string) => void;
}) {
  const grouped = useMemo(() => {
    const map = new Map<string, SocialPost[]>();
    for (const p of posts) {
      const day = p.scheduledAt.slice(0, 10);
      const list = map.get(day) ?? [];
      list.push(p);
      map.set(day, list);
    }
    return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b));
  }, [posts]);

  if (grouped.length === 0) {
    return (
      <EmptyState
        icon="📣"
        title="No posts match"
        description="Adjust filters or schedule a post above. The Marketing Agent can draft per-platform variants from a single brief."
      />
    );
  }

  function toggleAllInDay(dayPosts: SocialPost[]) {
    const next = new Set(selected);
    const allSelected = dayPosts.every((p) => next.has(p.id));
    for (const p of dayPosts) {
      if (allSelected) next.delete(p.id);
      else next.add(p.id);
    }
    setSelected(next);
  }

  function toggleOne(id: string) {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    setSelected(next);
  }

  return (
    <div className="space-y-4">
      {grouped.map(([day, dayPosts]) => (
        <div key={day}>
          <div className="flex items-center justify-between mb-2">
            <h3 className="text-sm font-semibold">{formatDate(day)}</h3>
            <button
              onClick={() => toggleAllInDay(dayPosts)}
              className="text-[11px] text-muted-foreground hover:underline"
            >
              {dayPosts.every((p) => selected.has(p.id)) ? "Deselect day" : "Select day"}
            </button>
          </div>
          <div className="space-y-2">
            {dayPosts.map((p) => {
              const org = ALL_ORGANIZATIONS.find((o) => o.slug === p.organizationSlug);
              const time = new Date(p.scheduledAt).toLocaleTimeString("en-US", {
                hour: "numeric",
                minute: "2-digit",
              });
              const isSelected = selected.has(p.id);
              return (
                <Card key={p.id} className={isSelected ? "border-[var(--sag-brand)]" : ""}>
                  <CardContent className="p-4">
                    <div className="flex items-start justify-between gap-3 flex-wrap">
                      <input
                        type="checkbox"
                        checked={isSelected}
                        onChange={() => toggleOne(p.id)}
                        className="mt-1 shrink-0"
                      />
                      <div className="min-w-0 flex-1">
                        <div className="flex items-center gap-2 mb-1 flex-wrap">
                          <span className="text-xs font-mono">{time}</span>
                          <Badge variant={STATUS_BADGE[p.status]}>{p.status}</Badge>
                          <span className="text-xs text-muted-foreground inline-flex items-center gap-1">
                            {org?.emoji} {org?.name}
                          </span>
                          <div className="flex gap-1">
                            {p.platforms.map((pl) => {
                              const def = SOCIAL_PLATFORMS[pl];
                              return (
                                <span key={pl} title={def.label} className="text-sm">
                                  {def.icon}
                                </span>
                              );
                            })}
                          </div>
                          {p.approvedBy && (
                            <span className="text-[10px] text-muted-foreground italic">
                              ✓ {p.approvedBy}
                            </span>
                          )}
                        </div>
                        <p className="text-sm whitespace-pre-wrap leading-relaxed">{p.content}</p>
                        {p.hashtags && p.hashtags.length > 0 && (
                          <p className="mt-1 text-xs text-blue-700 dark:text-blue-400">
                            {p.hashtags.map((t) => `#${t.replace(/^#/, "")}`).join(" ")}
                          </p>
                        )}
                        {p.media.length > 0 && (
                          <div className="mt-2 flex gap-2 flex-wrap">
                            {p.media.map((m) => (
                              <MediaThumb key={m.id} media={m} />
                            ))}
                          </div>
                        )}
                        {p.notes && (
                          <p className="mt-2 text-[11px] text-muted-foreground italic">{p.notes}</p>
                        )}
                      </div>
                      <div className="flex items-center gap-1 shrink-0">
                        {p.status === "Draft" && (
                          <Button variant="outline" size="sm" onClick={() => onStatus(p.id, "Pending Review")}>
                            Send for review
                          </Button>
                        )}
                        {p.status === "Pending Review" && (
                          <Button variant="brand" size="sm" onClick={() => onStatus(p.id, "Scheduled")}>
                            Approve
                          </Button>
                        )}
                        {p.status === "Scheduled" && (
                          <Button variant="brand" size="sm" onClick={() => onStatus(p.id, "Posted")}>
                            Mark posted
                          </Button>
                        )}
                        <Button variant="ghost" size="sm" onClick={() => onEdit(p.id)}>
                          Edit
                        </Button>
                        <Button variant="ghost" size="sm" onClick={() => onDelete(p.id)}>
                          ×
                        </Button>
                      </div>
                    </div>
                  </CardContent>
                </Card>
              );
            })}
          </div>
        </div>
      ))}
    </div>
  );
}

function MediaThumb({ media }: { media: PostMediaRef }) {
  if (media.mime.startsWith("image/")) {
    return (
      // eslint-disable-next-line @next/next/no-img-element
      <img
        src={`/api/social/media/${media.id}`}
        alt=""
        className="w-16 h-16 rounded-md border object-cover"
      />
    );
  }
  if (media.mime.startsWith("video/")) {
    return (
      <div className="w-16 h-16 rounded-md border bg-muted flex items-center justify-center text-xl">
        🎬
      </div>
    );
  }
  return (
    <div className="w-16 h-16 rounded-md border bg-muted flex items-center justify-center text-xl">
      📄
    </div>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Month view
// ──────────────────────────────────────────────────────────────────────────

function MonthView({
  posts,
  monthCursor,
  setMonthCursor,
  onReschedule,
  onEdit,
}: {
  posts: SocialPost[];
  monthCursor: Date;
  setMonthCursor: (d: Date) => void;
  onReschedule: (id: string, newDateISO: string) => void;
  onEdit: (id: string) => void;
}) {
  const [dragId, setDragId] = useState<string | null>(null);
  const [hoverDay, setHoverDay] = useState<string | null>(null);

  const year = monthCursor.getFullYear();
  const month = monthCursor.getMonth();
  const firstOfMonth = new Date(year, month, 1);
  const dayOfWeek = firstOfMonth.getDay();
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const cells: Array<{ key: string; day: number | null; dateISO?: string }> = [];
  for (let i = 0; i < dayOfWeek; i++) cells.push({ key: `pre-${i}`, day: null });
  for (let d = 1; d <= daysInMonth; d++) {
    const dt = new Date(year, month, d);
    cells.push({ key: `d-${d}`, day: d, dateISO: dt.toISOString().slice(0, 10) });
  }
  while (cells.length % 7 !== 0) cells.push({ key: `post-${cells.length}`, day: null });

  const postsByDay = useMemo(() => {
    const map = new Map<string, SocialPost[]>();
    for (const p of posts) {
      const day = p.scheduledAt.slice(0, 10);
      const list = map.get(day) ?? [];
      list.push(p);
      map.set(day, list);
    }
    return map;
  }, [posts]);

  const monthName = monthCursor.toLocaleString("en-US", { month: "long", year: "numeric" });
  const todayISO = new Date().toISOString().slice(0, 10);

  return (
    <Card>
      <CardContent className="p-4">
        <div className="flex items-center justify-between mb-4 flex-wrap gap-2">
          <h3 className="text-base font-semibold">{monthName}</h3>
          <div className="flex items-center gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => setMonthCursor(new Date(year, month - 1, 1))}
            >
              ←
            </Button>
            <Button variant="ghost" size="sm" onClick={() => setMonthCursor(new Date())}>
              Today
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={() => setMonthCursor(new Date(year, month + 1, 1))}
            >
              →
            </Button>
          </div>
        </div>

        <div className="grid grid-cols-7 section-label mb-1">
          {["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((d) => (
            <div key={d} className="px-1 py-1">
              {d}
            </div>
          ))}
        </div>

        <div className="grid grid-cols-7 gap-1">
          {cells.map((cell) => {
            const isToday = cell.dateISO === todayISO;
            const isHover = hoverDay === cell.dateISO;
            const dayPosts = cell.dateISO ? postsByDay.get(cell.dateISO) ?? [] : [];
            return (
              <div
                key={cell.key}
                className={`min-h-[88px] rounded-md border p-1 ${
                  cell.day == null
                    ? "bg-muted/30 border-transparent"
                    : isHover
                      ? "bg-accent/60 border-[var(--sag-brand)]"
                      : isToday
                        ? "bg-accent/30"
                        : "bg-background"
                }`}
                onDragOver={(e) => {
                  if (!cell.dateISO || !dragId) return;
                  e.preventDefault();
                  if (hoverDay !== cell.dateISO) setHoverDay(cell.dateISO);
                }}
                onDragLeave={() => {
                  if (hoverDay === cell.dateISO) setHoverDay(null);
                }}
                onDrop={(e) => {
                  e.preventDefault();
                  if (cell.dateISO && dragId) {
                    onReschedule(dragId, cell.dateISO);
                  }
                  setDragId(null);
                  setHoverDay(null);
                }}
              >
                {cell.day != null && (
                  <>
                    <div className="text-[10px] font-medium text-muted-foreground mb-1">
                      {cell.day}
                    </div>
                    <div className="space-y-0.5">
                      {dayPosts.slice(0, 3).map((p) => {
                        const firstPlat = p.platforms[0];
                        const plat = firstPlat ? SOCIAL_PLATFORMS[firstPlat] : undefined;
                        const color = plat?.color ?? "#666";
                        return (
                          <div
                            key={p.id}
                            draggable
                            onDragStart={() => setDragId(p.id)}
                            onDragEnd={() => setDragId(null)}
                            onClick={() => onEdit(p.id)}
                            className="text-[10px] rounded px-1 py-0.5 truncate cursor-grab active:cursor-grabbing flex items-center gap-1"
                            style={{ backgroundColor: `${color}25`, color }}
                            title={p.content}
                          >
                            {plat?.icon}
                            <span className="truncate text-foreground/85">{p.content}</span>
                          </div>
                        );
                      })}
                      {dayPosts.length > 3 && (
                        <div className="text-[10px] text-muted-foreground">
                          +{dayPosts.length - 3} more
                        </div>
                      )}
                    </div>
                  </>
                )}
              </div>
            );
          })}
        </div>

        <p className="mt-3 text-[11px] text-muted-foreground">
          Drag a post to a new day to reschedule (time of day preserved). Click a post to edit.
        </p>
      </CardContent>
    </Card>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Composer (full upgrade)
// ──────────────────────────────────────────────────────────────────────────

function PostComposer({
  initial,
  onSave,
  onCancel,
}: {
  initial?: SocialPost;
  onSave: (post: Omit<SocialPost, "id" | "createdAt">) => void;
  onCancel: () => void;
}) {
  const [form, setForm] = useState<Omit<SocialPost, "id" | "createdAt">>(() => ({
    organizationSlug: initial?.organizationSlug ?? ALL_ORGANIZATIONS[0]?.slug ?? "south-armz-global",
    content: initial?.content ?? "",
    variants: initial?.variants ?? {},
    platforms: initial?.platforms ?? ["instagram"],
    scheduledAt:
      initial?.scheduledAt ??
      new Date(Date.now() + 24 * 3600 * 1000).toISOString(),
    media: initial?.media ?? [],
    hashtags: initial?.hashtags ?? [],
    status: initial?.status ?? "Draft",
    notes: initial?.notes,
    approvedAt: initial?.approvedAt,
    approvedBy: initial?.approvedBy,
    reviewRequestedAt: initial?.reviewRequestedAt,
  }));
  const [brief, setBrief] = useState("");
  const [drafting, setDrafting] = useState(false);
  const [hashtagging, setHashtagging] = useState(false);
  const [varianting, setVarianting] = useState<SocialPlatformId | null>(null);
  const [agentDraft, setAgentDraft] = useState<string>("");
  const [agentError, setAgentError] = useState<string>("");
  const [showCanva, setShowCanva] = useState(false);
  const [variantPanelOpen, setVariantPanelOpen] = useState<Set<SocialPlatformId>>(new Set());
  const fileInputRef = useRef<HTMLInputElement>(null);

  function togglePlatform(p: SocialPlatformId) {
    const has = form.platforms.includes(p);
    setForm({
      ...form,
      platforms: has ? form.platforms.filter((x) => x !== p) : [...form.platforms, p],
    });
  }

  function toggleVariantPanel(p: SocialPlatformId) {
    setVariantPanelOpen((prev) => {
      const next = new Set(prev);
      if (next.has(p)) next.delete(p);
      else next.add(p);
      return next;
    });
  }

  function setVariant(p: SocialPlatformId, text: string) {
    const variants: PostVariants = { ...(form.variants ?? {}) };
    if (text.trim()) variants[p] = text;
    else delete variants[p];
    setForm({ ...form, variants });
  }

  async function uploadFiles(files: FileList) {
    for (const file of Array.from(files)) {
      try {
        const fd = new FormData();
        fd.append("file", file);
        const resp = await fetch("/api/social/media", { method: "POST", body: fd });
        const data = await resp.json();
        if (!resp.ok) throw new Error(data.error || "Upload failed");
        setForm((f) => ({
          ...f,
          media: [...f.media, { id: data.media.id, mime: data.media.mime, source: "upload" }],
        }));
      } catch (e) {
        alert(`Upload failed: ${e instanceof Error ? e.message : "unknown"}`);
      }
    }
  }

  function removeMedia(id: string) {
    setForm((f) => ({ ...f, media: f.media.filter((m) => m.id !== id) }));
  }

  async function generateCaption() {
    setAgentError("");
    setDrafting(true);
    setAgentDraft("");
    try {
      const org = ALL_ORGANIZATIONS.find((o) => o.slug === form.organizationSlug);
      const platforms = form.platforms.map((p) => SOCIAL_PLATFORMS[p].label).join(", ");
      const prompt = `Write a social media post for ${org?.name ?? form.organizationSlug}. Brief: ${brief || "(no specific brief — write something on-brand for an organic content drop)"}. Target platforms: ${platforms}. Return three caption variants (short / medium / long) followed by 5–10 hashtags. Match the entity's brand voice.`;
      const resp = await fetch("/api/agents/marketing", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          messages: [{ role: "user", content: prompt }],
          contextSnapshot: snapshotForAgentCall(),
        }),
      });
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      setAgentDraft(data.message);
    } catch (e) {
      setAgentError(e instanceof Error ? e.message : "Unknown error");
    } finally {
      setDrafting(false);
    }
  }

  async function generateHashtags() {
    setAgentError("");
    setHashtagging(true);
    try {
      const org = ALL_ORGANIZATIONS.find((o) => o.slug === form.organizationSlug);
      const platforms = form.platforms.map((p) => SOCIAL_PLATFORMS[p].label).join(", ");
      const prompt = `Generate 8–12 hashtags for a ${org?.name ?? form.organizationSlug} social post about: "${form.content || brief || "(general)"}". Target platforms: ${platforms}. Return ONLY a comma-separated list of hashtags WITHOUT the # symbol — no explanation, no numbering, no other text.`;
      const resp = await fetch("/api/agents/marketing", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          messages: [{ role: "user", content: prompt }],
          contextSnapshot: snapshotForAgentCall(),
        }),
      });
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      const tags = String(data.message ?? "")
        .replace(/[#\n\r]/g, " ")
        .split(/[,\s]+/)
        .map((t) => t.trim())
        .filter((t) => t.length > 1 && /^[A-Za-z0-9_]+$/.test(t))
        .slice(0, 15);
      setForm((f) => ({ ...f, hashtags: tags }));
    } catch (e) {
      setAgentError(e instanceof Error ? e.message : "Unknown error");
    } finally {
      setHashtagging(false);
    }
  }

  async function generateVariant(platform: SocialPlatformId) {
    setAgentError("");
    setVarianting(platform);
    try {
      const plat = SOCIAL_PLATFORMS[platform];
      const org = ALL_ORGANIZATIONS.find((o) => o.slug === form.organizationSlug);
      const prompt = `Rewrite the following caption for ${plat.label} (max ${plat.charLimit} characters, recommended hashtags: ${plat.maxHashtags}). Keep ${org?.name ?? "the brand"}'s voice. Caption to adapt:\n\n${form.content || brief}\n\nReturn ONLY the rewritten caption — no preamble, no explanation.`;
      const resp = await fetch("/api/agents/marketing", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          messages: [{ role: "user", content: prompt }],
          contextSnapshot: snapshotForAgentCall(),
        }),
      });
      const data = await resp.json();
      if (!resp.ok) throw new Error(data.error || "Failed");
      setVariant(platform, String(data.message ?? "").trim());
      setVariantPanelOpen((prev) => new Set(prev).add(platform));
    } catch (e) {
      setAgentError(e instanceof Error ? e.message : "Unknown error");
    } finally {
      setVarianting(null);
    }
  }

  function suggestNextBestTime() {
    if (form.platforms.length === 0) return;
    const window = SOCIAL_PLATFORMS[form.platforms[0]].bestTimes[0];
    alert(`Suggested for ${SOCIAL_PLATFORMS[form.platforms[0]].label}: ${window.label}\n\n${window.rationale}`);
  }

  function submit() {
    if (!form.content.trim() || form.platforms.length === 0) {
      alert("Add a caption and select at least one platform.");
      return;
    }
    onSave({
      ...form,
      scheduledAt: new Date(form.scheduledAt).toISOString(),
    });
  }

  // Convert ISO → datetime-local format
  const dtLocalValue = useMemo(() => {
    const d = new Date(form.scheduledAt);
    const pad = (n: number) => String(n).padStart(2, "0");
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
  }, [form.scheduledAt]);

  return (
    <Card>
      <CardContent className="p-6 space-y-5">
        <div className="grid gap-3 md:grid-cols-2">
          <Field label="Entity">
            <select
              value={form.organizationSlug}
              onChange={(e) => setForm({ ...form, organizationSlug: e.target.value })}
              className="w-full h-10 rounded-md border border-input bg-background px-3 text-sm"
            >
              {ALL_ORGANIZATIONS.map((o) => (
                <option key={o.slug} value={o.slug}>
                  {o.emoji} {o.name}
                </option>
              ))}
            </select>
          </Field>
          <Field label="Scheduled at (local)">
            <div className="flex gap-2">
              <Input
                type="datetime-local"
                value={dtLocalValue}
                onChange={(e) => {
                  if (!e.target.value) return;
                  const d = new Date(e.target.value);
                  setForm({ ...form, scheduledAt: d.toISOString() });
                }}
              />
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={suggestNextBestTime}
                title="Suggest best time for first platform"
              >
                ⏰ Suggested
              </Button>
            </div>
          </Field>
        </div>

        <div>
          <div className="flex items-center justify-between">
            <label className="text-xs text-muted-foreground">Platforms</label>
            <span className="text-[10px] text-muted-foreground">
              Click ⚙ to set a per-platform variant
            </span>
          </div>
          <div className="mt-1 flex flex-wrap gap-2">
            {SOCIAL_PLATFORM_LIST.map((p) => {
              const active = form.platforms.includes(p.id);
              const hasVariant = !!form.variants?.[p.id];
              return (
                <div key={p.id} className="inline-flex">
                  <button
                    type="button"
                    onClick={() => togglePlatform(p.id)}
                    className={`text-xs px-3 py-1.5 rounded-l-full border transition-colors inline-flex items-center gap-1 ${
                      active
                        ? "bg-foreground text-background border-foreground"
                        : "border-input text-muted-foreground hover:bg-accent"
                    }`}
                  >
                    <span>{p.icon}</span>
                    {p.label}
                  </button>
                  <Tooltip content="Per-platform caption">
                    <button
                      type="button"
                      onClick={() => toggleVariantPanel(p.id)}
                      disabled={!active}
                      className={`text-xs px-2 py-1.5 rounded-r-full border-y border-r transition-colors ${
                        active
                          ? hasVariant
                            ? "bg-blue-500/10 border-blue-500/30 text-blue-700 dark:text-blue-300"
                            : "border-input text-muted-foreground hover:bg-accent"
                          : "border-input text-muted-foreground/40"
                      }`}
                      aria-label="Per-platform caption"
                    >
                      ⚙
                    </button>
                  </Tooltip>
                </div>
              );
            })}
          </div>
        </div>

        <div>
          <div className="flex items-center justify-between mb-1 flex-wrap gap-2">
            <label className="text-xs text-muted-foreground">
              AI brief (one sentence, used by ✨ buttons)
            </label>
            <div className="flex gap-1">
              <Button
                type="button"
                variant="ghost"
                size="sm"
                disabled={drafting}
                onClick={generateCaption}
              >
                {drafting ? "Drafting…" : "✨ Caption draft"}
              </Button>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                disabled={hashtagging || !form.content.trim()}
                onClick={generateHashtags}
              >
                {hashtagging ? "Generating…" : "# Hashtags"}
              </Button>
            </div>
          </div>
          <Input
            value={brief}
            onChange={(e) => setBrief(e.target.value)}
            placeholder="e.g. ‘Saturday axe-throwing league finals, $25 entry, free first beer’"
          />
          {agentDraft && (
            <pre className="mt-2 whitespace-pre-wrap text-xs bg-muted p-3 rounded-md max-h-48 overflow-y-auto">
              {agentDraft}
            </pre>
          )}
          {agentError && (
            <p className="mt-2 text-xs text-destructive">{agentError}</p>
          )}
        </div>

        <div>
          <label className="text-xs text-muted-foreground">Shared caption</label>
          <textarea
            value={form.content}
            onChange={(e) => setForm({ ...form, content: e.target.value })}
            className="mt-1 w-full rounded-md border border-input bg-background p-3 text-sm"
            rows={5}
            placeholder="Write or paste your caption. Each platform can override below."
            required
          />
        </div>

        {form.hashtags && form.hashtags.length > 0 && (
          <div>
            <label className="text-xs text-muted-foreground">Hashtags</label>
            <div className="mt-1 flex flex-wrap gap-1">
              {form.hashtags.map((t) => (
                <button
                  key={t}
                  type="button"
                  onClick={() =>
                    setForm({ ...form, hashtags: form.hashtags?.filter((x) => x !== t) })
                  }
                  className="text-[11px] px-2 py-0.5 rounded-full border border-input bg-muted hover:bg-destructive/10 inline-flex items-center gap-1"
                  title="Click to remove"
                >
                  #{t.replace(/^#/, "")}
                  <span className="text-muted-foreground">×</span>
                </button>
              ))}
            </div>
          </div>
        )}

        {form.platforms.length > 0 &&
          form.platforms.some((p) => variantPanelOpen.has(p)) && (
            <div className="rounded-md border bg-muted/30 p-4 space-y-3">
              <div className="text-xs font-semibold text-muted-foreground">
                Per-platform overrides
              </div>
              {form.platforms
                .filter((p) => variantPanelOpen.has(p))
                .map((p) => {
                  const plat = SOCIAL_PLATFORMS[p];
                  const v = form.variants?.[p] ?? "";
                  return (
                    <div key={p}>
                      <div className="flex items-center justify-between mb-1">
                        <label className="text-xs font-medium flex items-center gap-1">
                          {plat.icon} {plat.label}{" "}
                          <span className="text-[10px] text-muted-foreground">
                            ({plat.charLimit} chars)
                          </span>
                        </label>
                        <Button
                          type="button"
                          variant="ghost"
                          size="sm"
                          disabled={varianting !== null || !form.content.trim()}
                          onClick={() => generateVariant(p)}
                        >
                          {varianting === p ? "Adapting…" : "✨ Adapt"}
                        </Button>
                      </div>
                      <textarea
                        value={v}
                        onChange={(e) => setVariant(p, e.target.value)}
                        className="w-full rounded-md border border-input bg-background p-2 text-sm"
                        rows={3}
                        placeholder={`Leave empty to use the shared caption on ${plat.label}.`}
                      />
                    </div>
                  );
                })}
            </div>
          )}

        <div>
          <div className="flex items-center justify-between mb-2 flex-wrap gap-2">
            <label className="text-xs text-muted-foreground">Media</label>
            <div className="flex gap-1">
              <Button
                type="button"
                variant="outline"
                size="sm"
                onClick={() => fileInputRef.current?.click()}
              >
                📎 Upload
              </Button>
              <Button type="button" variant="outline" size="sm" onClick={() => setShowCanva(true)}>
                📐 Design with Canva
              </Button>
            </div>
          </div>
          <input
            ref={fileInputRef}
            type="file"
            multiple
            accept="image/png,image/jpeg,image/webp,image/gif,video/mp4,video/quicktime,application/pdf"
            className="hidden"
            onChange={(e) => {
              if (e.target.files && e.target.files.length > 0) {
                void uploadFiles(e.target.files);
                e.target.value = "";
              }
            }}
          />
          <div
            className="rounded-md border border-dashed bg-background p-4"
            onDragOver={(e) => {
              e.preventDefault();
              e.dataTransfer.dropEffect = "copy";
            }}
            onDrop={(e) => {
              e.preventDefault();
              if (e.dataTransfer.files.length > 0) void uploadFiles(e.dataTransfer.files);
            }}
          >
            {form.media.length === 0 ? (
              <p className="text-xs text-muted-foreground text-center">
                Drag-and-drop images, video, or PDF here, or click Upload above. Max 50 MB per file.
              </p>
            ) : (
              <div className="flex flex-wrap gap-2">
                {form.media.map((m) => (
                  <div key={m.id} className="relative group">
                    {m.mime.startsWith("image/") ? (
                      // eslint-disable-next-line @next/next/no-img-element
                      <img
                        src={`/api/social/media/${m.id}`}
                        alt=""
                        className="w-24 h-24 rounded-md border object-cover"
                      />
                    ) : m.mime.startsWith("video/") ? (
                      <div className="w-24 h-24 rounded-md border bg-muted flex items-center justify-center text-3xl">
                        🎬
                      </div>
                    ) : (
                      <div className="w-24 h-24 rounded-md border bg-muted flex items-center justify-center text-3xl">
                        📄
                      </div>
                    )}
                    <Tooltip content="Remove">
                      <button
                        type="button"
                        onClick={() => removeMedia(m.id)}
                        className="absolute -top-1 -right-1 w-5 h-5 rounded-full bg-destructive text-destructive-foreground text-xs leading-none"
                        aria-label="Remove"
                      >
                        ×
                      </button>
                    </Tooltip>
                    {m.source === "canva" && (
                      <Badge variant="info" className="absolute bottom-1 left-1 text-[9px]">
                        Canva
                      </Badge>
                    )}
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>

        {form.platforms.length > 0 && (
          <div>
            <label className="text-xs text-muted-foreground">Preview per platform</label>
            <div className="mt-1 grid gap-3 md:grid-cols-2 lg:grid-cols-3">
              {form.platforms.map((p) => {
                const firstMedia = form.media[0];
                return (
                  <SocialPlatformPreview
                    key={p}
                    platform={p}
                    caption={captionFor(
                      {
                        ...form,
                        id: initial?.id ?? "preview",
                        createdAt: initial?.createdAt ?? new Date().toISOString(),
                      },
                      p
                    )}
                    hashtags={form.hashtags}
                    mediaSrc={firstMedia ? `/api/social/media/${firstMedia.id}` : undefined}
                    mediaMime={firstMedia?.mime}
                  />
                );
              })}
            </div>
          </div>
        )}

        <div className="grid gap-3 md:grid-cols-2">
          <Field label="Status">
            <select
              value={form.status}
              onChange={(e) =>
                setForm({
                  ...form,
                  status: e.target.value as PostStatus,
                  approvedAt:
                    e.target.value === "Scheduled" ? new Date().toISOString() : form.approvedAt,
                  approvedBy: e.target.value === "Scheduled" ? "Glenn" : form.approvedBy,
                  reviewRequestedAt:
                    e.target.value === "Pending Review"
                      ? new Date().toISOString()
                      : form.reviewRequestedAt,
                })
              }
              className="w-full h-10 rounded-md border border-input bg-background px-3 text-sm"
            >
              {STATUSES.map((s) => (
                <option key={s} value={s}>
                  {s}
                </option>
              ))}
            </select>
          </Field>
          <Field label="Internal notes (optional)">
            <Input
              value={form.notes ?? ""}
              onChange={(e) => setForm({ ...form, notes: e.target.value })}
              placeholder="Reviewer, context, links…"
            />
          </Field>
        </div>

        <div className="flex items-center justify-end gap-2">
          <Button variant="ghost" size="sm" type="button" onClick={onCancel}>
            Cancel
          </Button>
          <Button variant="brand" size="sm" onClick={submit}>
            {initial ? "Save changes" : "Save post"}
          </Button>
        </div>
      </CardContent>

      {showCanva && (
        <CanvaPicker
          onClose={() => setShowCanva(false)}
          onPicked={(file) =>
            setForm((f) => ({
              ...f,
              media: [
                ...f.media,
                {
                  id: file.id,
                  mime: file.mime,
                  source: "canva",
                  canvaDesignId: file.canvaDesignId,
                },
              ],
            }))
          }
        />
      )}
    </Card>
  );
}

function Field({ label, children, className }: { label: string; children: React.ReactNode; className?: string }) {
  return (
    <div className={className}>
      <label className="text-xs text-muted-foreground">{label}</label>
      <div className="mt-1">{children}</div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Legacy schema (pre-v2). Kept here so we can migrate cleanly on first run.
// ──────────────────────────────────────────────────────────────────────────

interface LegacyPost {
  id: string;
  organizationSlug: string;
  content: string;
  platforms: string[];
  scheduledAt: string;
  mediaUrls?: string[];
  status: string;
  notes?: string;
  createdAt: string;
}
