"use client";

import * as React from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useSession } from "next-auth/react";
import {
  Plus,
  Pencil,
  Trash2,
  Send,
  Check,
  X,
  Share2,
  CalendarCheck,
  ExternalLink,
} from "lucide-react";
import { apiGet, apiSend } from "@/lib/api";
import type { PostDTO, PlatformDTO } from "@/lib/types";
import { can } from "@/lib/rbac";
import { POST_STATUS_LABEL, POST_STATUS_BADGE, POST_STATUS_ORDER } from "@/lib/labels";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Dialog, DialogHeader, DialogBody, DialogFooter } from "@/components/ui/dialog";
import { PageHeader, Spinner, EmptyState } from "@/components/common";

export function PostsView() {
  const { data: session } = useSession();
  const me = session?.user;
  const canAuthor = can(me?.role, "posts:author");
  const canApprove = can(me?.role, "posts:approve");
  const canManagePlatforms = can(me?.role, "platforms:write");
  const qc = useQueryClient();

  const postsQuery = useQuery({ queryKey: ["posts"], queryFn: () => apiGet<PostDTO[]>("/api/posts") });
  const platformsQuery = useQuery({
    queryKey: ["platforms"],
    queryFn: () => apiGet<PlatformDTO[]>("/api/platforms"),
  });

  const [formOpen, setFormOpen] = React.useState(false);
  const [editing, setEditing] = React.useState<PostDTO | null>(null);
  const [platformsOpen, setPlatformsOpen] = React.useState(false);

  const refresh = () => qc.invalidateQueries({ queryKey: ["posts"] });

  const posts = postsQuery.data ?? [];
  const platforms = platformsQuery.data ?? [];
  const activePlatforms = platforms.filter((p) => p.active);

  // Group posts into the workflow columns.
  const byStatus = POST_STATUS_ORDER.map((s) => ({
    status: s,
    posts: posts.filter((p) => p.status === s),
  })).filter((g) => g.posts.length > 0);

  return (
    <div>
      <PageHeader
        title="Content Calendar"
        subtitle="Draft posts, get manager approval, then publish & record the date"
      >
        {canManagePlatforms && (
          <Button variant="secondary" onClick={() => setPlatformsOpen(true)}>
            <Share2 className="size-4" /> Platforms
          </Button>
        )}
        {canAuthor && (
          <Button
            onClick={() => {
              setEditing(null);
              setFormOpen(true);
            }}
          >
            <Plus className="size-4" /> New Post
          </Button>
        )}
      </PageHeader>

      {postsQuery.isLoading ? (
        <Spinner />
      ) : posts.length === 0 ? (
        <EmptyState
          title="No posts yet"
          description={
            canAuthor
              ? "Create your first post — add the caption, a link to the graphic/video, and pick the platforms."
              : "Posts will appear here once the marketing team starts drafting."
          }
        />
      ) : (
        <div className="space-y-6">
          {byStatus.map((group) => (
            <div key={group.status}>
              <div className="mb-2 flex items-center gap-2">
                <Badge variant={POST_STATUS_BADGE[group.status]}>
                  {POST_STATUS_LABEL[group.status]}
                </Badge>
                <span className="text-xs text-muted-foreground">{group.posts.length}</span>
              </div>
              <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
                {group.posts.map((p) => (
                  <PostCard
                    key={p.id}
                    post={p}
                    meId={me?.id}
                    canApprove={canApprove}
                    onChanged={refresh}
                    onEdit={() => {
                      setEditing(p);
                      setFormOpen(true);
                    }}
                  />
                ))}
              </div>
            </div>
          ))}
        </div>
      )}

      {canAuthor && (
        <PostFormDialog
          open={formOpen}
          onClose={() => setFormOpen(false)}
          onSaved={refresh}
          post={editing}
          platforms={activePlatforms}
        />
      )}
      {canManagePlatforms && (
        <PlatformsDialog
          open={platformsOpen}
          onClose={() => setPlatformsOpen(false)}
          platforms={platforms}
        />
      )}
    </div>
  );
}

function fmtDate(iso: string | null): string {
  if (!iso) return "—";
  return new Date(iso).toLocaleDateString(undefined, {
    year: "numeric",
    month: "short",
    day: "numeric",
  });
}

function PostCard({
  post,
  meId,
  canApprove,
  onChanged,
  onEdit,
}: {
  post: PostDTO;
  meId?: string;
  canApprove: boolean;
  onChanged: () => void;
  onEdit: () => void;
}) {
  const isAuthor = post.authorId === meId;
  const [rejectOpen, setRejectOpen] = React.useState(false);
  const [postOpen, setPostOpen] = React.useState(false);

  const act = useMutation({
    mutationFn: (body: Record<string, unknown>) => apiSend(`/api/posts/${post.id}`, "PATCH", body),
    onSuccess: onChanged,
  });
  const del = useMutation({
    mutationFn: () => apiSend(`/api/posts/${post.id}`, "DELETE"),
    onSuccess: onChanged,
  });

  const editable = post.status === "DRAFT" || post.status === "REJECTED";

  return (
    <div className="flex flex-col rounded-md border border-border bg-card p-3">
      <div className="mb-1 flex items-start justify-between gap-2">
        <div className="text-sm font-semibold">{post.title}</div>
        {(isAuthor || canApprove) && (
          <div className="flex shrink-0 gap-1">
            {isAuthor && editable && (
              <Button variant="ghost" size="icon" onClick={onEdit} title="Edit">
                <Pencil className="size-3.5" />
              </Button>
            )}
            {(isAuthor || canApprove) && (
              <Button variant="ghost" size="icon" onClick={() => del.mutate()} title="Delete">
                <Trash2 className="size-3.5" />
              </Button>
            )}
          </div>
        )}
      </div>

      <p className="mb-2 whitespace-pre-wrap text-xs text-muted-foreground line-clamp-4">
        {post.content}
      </p>

      <div className="mb-2 flex flex-wrap gap-1.5">
        {post.platforms.map((pl) => (
          <Badge key={pl.id} variant="outline">
            {pl.name}
          </Badge>
        ))}
      </div>

      {post.mediaUrl && (
        <a
          href={post.mediaUrl}
          target="_blank"
          rel="noopener noreferrer"
          className="mb-2 inline-flex items-center gap-1 text-xs text-accent-foreground underline"
        >
          <ExternalLink className="size-3" /> Graphic / video
        </a>
      )}

      <div className="mb-2 space-y-0.5 text-[11px] text-muted-foreground">
        <div>By {post.author.name}</div>
        {post.scheduledDate && <div>Scheduled: {fmtDate(post.scheduledDate)}</div>}
        {post.status === "POSTED" && <div>Posted: {fmtDate(post.postedDate)}</div>}
      </div>

      {post.status === "REJECTED" && post.reviewNote && (
        <div className="mb-2 rounded-md border border-destructive/30 bg-destructive/10 px-2 py-1.5 text-[11px] text-destructive">
          <span className="font-semibold">Manager: </span>
          {post.reviewNote}
        </div>
      )}

      {/* ── Workflow actions ─────────────────────────────────────────────── */}
      <div className="mt-auto flex flex-wrap gap-1.5 pt-1">
        {isAuthor && editable && (
          <Button size="sm" onClick={() => act.mutate({ action: "submit" })} disabled={act.isPending}>
            <Send className="size-3.5" /> Submit for approval
          </Button>
        )}

        {canApprove && post.status === "PENDING_APPROVAL" && (
          <>
            <Button
              size="sm"
              variant="success"
              onClick={() => act.mutate({ action: "approve" })}
              disabled={act.isPending}
            >
              <Check className="size-3.5" /> Approve
            </Button>
            <Button size="sm" variant="destructive" onClick={() => setRejectOpen(true)}>
              <X className="size-3.5" /> Reject
            </Button>
          </>
        )}

        {isAuthor && post.status === "APPROVED" && (
          <Button size="sm" variant="success" onClick={() => setPostOpen(true)} disabled={act.isPending}>
            <CalendarCheck className="size-3.5" /> Mark as posted
          </Button>
        )}
      </div>

      <RejectDialog
        open={rejectOpen}
        onClose={() => setRejectOpen(false)}
        onConfirm={(note) => {
          act.mutate({ action: "reject", reviewNote: note });
          setRejectOpen(false);
        }}
      />
      <MarkPostedDialog
        open={postOpen}
        onClose={() => setPostOpen(false)}
        onConfirm={(date) => {
          act.mutate({ action: "post", postedDate: date });
          setPostOpen(false);
        }}
      />
    </div>
  );
}

function RejectDialog({
  open,
  onClose,
  onConfirm,
}: {
  open: boolean;
  onClose: () => void;
  onConfirm: (note: string) => void;
}) {
  const [note, setNote] = React.useState("");
  React.useEffect(() => {
    if (open) setNote("");
  }, [open]);
  return (
    <Dialog open={open} onClose={onClose} className="max-w-md">
      <DialogHeader title="Reject post" onClose={onClose} />
      <DialogBody>
        <div className="space-y-1.5">
          <Label>Reason / changes needed</Label>
          <Textarea
            value={note}
            onChange={(e) => setNote(e.target.value)}
            placeholder="Tell the author what to fix…"
            autoFocus
          />
        </div>
      </DialogBody>
      <DialogFooter>
        <Button type="button" variant="secondary" onClick={onClose}>
          Cancel
        </Button>
        <Button type="button" variant="destructive" disabled={!note.trim()} onClick={() => onConfirm(note.trim())}>
          Reject &amp; send back
        </Button>
      </DialogFooter>
    </Dialog>
  );
}

function MarkPostedDialog({
  open,
  onClose,
  onConfirm,
}: {
  open: boolean;
  onClose: () => void;
  onConfirm: (isoDate: string) => void;
}) {
  const [date, setDate] = React.useState("");
  React.useEffect(() => {
    if (open) setDate(todayInputValue());
  }, [open]);
  return (
    <Dialog open={open} onClose={onClose} className="max-w-sm">
      <DialogHeader title="Record posting date" onClose={onClose} />
      <DialogBody>
        <div className="space-y-1.5">
          <Label>Date posted to the platform(s)</Label>
          <Input type="date" value={date} onChange={(e) => setDate(e.target.value)} />
        </div>
      </DialogBody>
      <DialogFooter>
        <Button type="button" variant="secondary" onClick={onClose}>
          Cancel
        </Button>
        <Button
          type="button"
          variant="success"
          disabled={!date}
          onClick={() => onConfirm(new Date(date).toISOString())}
        >
          Mark as posted
        </Button>
      </DialogFooter>
    </Dialog>
  );
}

function PostFormDialog({
  open,
  onClose,
  onSaved,
  post,
  platforms,
}: {
  open: boolean;
  onClose: () => void;
  onSaved: () => void;
  post: PostDTO | null;
  platforms: PlatformDTO[];
}) {
  const [form, setForm] = React.useState(() => initPostForm(post));
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    setForm(initPostForm(post));
    setError("");
  }, [post, open]);

  function togglePlatform(id: string) {
    setForm((f) => ({
      ...f,
      platformIds: f.platformIds.includes(id)
        ? f.platformIds.filter((x) => x !== id)
        : [...f.platformIds, id],
    }));
  }

  const save = useMutation({
    mutationFn: async (submit: boolean) => {
      const payload = {
        title: form.title,
        content: form.content,
        mediaUrl: form.mediaUrl || null,
        mediaNotes: form.mediaNotes || null,
        scheduledDate: form.scheduledDate ? new Date(form.scheduledDate).toISOString() : null,
        platformIds: form.platformIds,
      };
      if (post) {
        // Edit existing draft, then optionally submit it.
        await apiSend(`/api/posts/${post.id}`, "PATCH", payload);
        if (submit) await apiSend(`/api/posts/${post.id}`, "PATCH", { action: "submit" });
      } else {
        await apiSend("/api/posts", "POST", { ...payload, submit });
      }
    },
    onSuccess: () => {
      onSaved();
      onClose();
    },
    onError: (e) => setError(e instanceof Error ? e.message : "Failed to save"),
  });

  function validate(): boolean {
    if (!form.title.trim()) {
      setError("Title is required");
      return false;
    }
    if (!form.content.trim()) {
      setError("Content writing is required");
      return false;
    }
    if (form.platformIds.length === 0) {
      setError("Select at least one platform");
      return false;
    }
    setError("");
    return true;
  }

  return (
    <Dialog open={open} onClose={onClose}>
      <DialogHeader title={post ? "Edit Post" : "New Post"} onClose={onClose} />
      <DialogBody>
        <div className="space-y-1.5">
          <Label>Title</Label>
          <Input
            value={form.title}
            onChange={(e) => setForm({ ...form, title: e.target.value })}
            placeholder="e.g. June water-safety tip"
            autoFocus
          />
        </div>
        <div className="space-y-1.5">
          <Label>Content writing (caption)</Label>
          <Textarea
            value={form.content}
            onChange={(e) => setForm({ ...form, content: e.target.value })}
            className="min-h-[120px]"
            placeholder="Write the post copy here…"
          />
        </div>
        <div className="space-y-1.5">
          <Label>Graphic / video link</Label>
          <Input
            value={form.mediaUrl}
            onChange={(e) => setForm({ ...form, mediaUrl: e.target.value })}
            placeholder="https://drive.google.com/… or Canva / YouTube link"
          />
        </div>
        <div className="space-y-1.5">
          <Label>Media notes (optional)</Label>
          <Input
            value={form.mediaNotes}
            onChange={(e) => setForm({ ...form, mediaNotes: e.target.value })}
            placeholder="e.g. 3 carousel images, 15s reel"
          />
        </div>
        <div className="space-y-1.5">
          <Label>Scheduled date (optional)</Label>
          <Input
            type="date"
            value={form.scheduledDate}
            onChange={(e) => setForm({ ...form, scheduledDate: e.target.value })}
          />
        </div>
        <div className="space-y-1.5">
          <Label>Platforms</Label>
          {platforms.length === 0 ? (
            <p className="text-xs text-muted-foreground">
              No platforms set up yet. A manager can add them with the “Platforms” button.
            </p>
          ) : (
            <div className="flex flex-wrap gap-2">
              {platforms.map((pl) => {
                const on = form.platformIds.includes(pl.id);
                return (
                  <button
                    key={pl.id}
                    type="button"
                    onClick={() => togglePlatform(pl.id)}
                    className={
                      "rounded-full border px-3 py-1 text-xs font-medium transition-colors " +
                      (on
                        ? "border-primary bg-primary text-primary-foreground"
                        : "border-border bg-card text-muted-foreground hover:bg-secondary")
                    }
                  >
                    {on ? "✓ " : ""}
                    {pl.name}
                  </button>
                );
              })}
            </div>
          )}
          <p className="text-[11px] text-muted-foreground">
            A post can go to multiple platforms — tap each one to include it.
          </p>
        </div>
        {error && <p className="text-sm text-destructive">{error}</p>}
      </DialogBody>
      <DialogFooter>
        <Button type="button" variant="secondary" onClick={onClose}>
          Cancel
        </Button>
        <Button
          type="button"
          variant="outline"
          disabled={save.isPending}
          onClick={() => validate() && save.mutate(false)}
        >
          Save draft
        </Button>
        <Button type="button" disabled={save.isPending} onClick={() => validate() && save.mutate(true)}>
          <Send className="size-4" /> Save &amp; submit
        </Button>
      </DialogFooter>
    </Dialog>
  );
}

// Inline manager for social-media platforms (FR-3) — editable by Admin/Manager.
function PlatformsDialog({
  open,
  onClose,
  platforms,
}: {
  open: boolean;
  onClose: () => void;
  platforms: PlatformDTO[];
}) {
  const qc = useQueryClient();
  const [name, setName] = React.useState("");
  const [error, setError] = React.useState("");
  // Inline rename state.
  const [editingId, setEditingId] = React.useState<string | null>(null);
  const [editName, setEditName] = React.useState("");
  const refresh = () => qc.invalidateQueries({ queryKey: ["platforms"] });

  const create = useMutation({
    mutationFn: () => apiSend("/api/platforms", "POST", { name }),
    onSuccess: () => {
      setName("");
      setError("");
      refresh();
    },
    onError: (e) => setError(e instanceof Error ? e.message : "Failed to add"),
  });
  const rename = useMutation({
    mutationFn: (vars: { id: string; name: string }) =>
      apiSend(`/api/platforms/${vars.id}`, "PATCH", { name: vars.name }),
    onSuccess: () => {
      setEditingId(null);
      setError("");
      refresh();
    },
    onError: (e) => setError(e instanceof Error ? e.message : "Failed to rename"),
  });
  const toggle = useMutation({
    mutationFn: (p: PlatformDTO) => apiSend(`/api/platforms/${p.id}`, "PATCH", { active: !p.active }),
    onSuccess: refresh,
  });
  const remove = useMutation({
    mutationFn: (id: string) => apiSend(`/api/platforms/${id}`, "DELETE"),
    onSuccess: refresh,
  });

  function startEdit(p: PlatformDTO) {
    setEditingId(p.id);
    setEditName(p.name);
    setError("");
  }

  return (
    <Dialog open={open} onClose={onClose}>
      <DialogHeader title="Social-media platforms" onClose={onClose} />
      <DialogBody>
        <p className="text-xs text-muted-foreground">
          The platforms staff can choose when scheduling a post.
        </p>
        <div className="flex gap-2">
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="e.g. Facebook, Instagram, TikTok"
            onKeyDown={(e) => {
              if (e.key === "Enter" && name.trim()) {
                e.preventDefault();
                create.mutate();
              }
            }}
          />
          <Button type="button" onClick={() => name.trim() && create.mutate()} disabled={create.isPending}>
            <Plus className="size-4" /> Add
          </Button>
        </div>
        {error && <p className="text-sm text-destructive">{error}</p>}
        <div className="space-y-1.5">
          {platforms.length === 0 ? (
            <EmptyState title="No platforms yet" />
          ) : (
            platforms.map((p) =>
              editingId === p.id ? (
                <div
                  key={p.id}
                  className="flex items-center gap-2 rounded-md border border-primary px-3 py-2"
                >
                  <Input
                    value={editName}
                    onChange={(e) => setEditName(e.target.value)}
                    autoFocus
                    onKeyDown={(e) => {
                      if (e.key === "Enter" && editName.trim())
                        rename.mutate({ id: p.id, name: editName.trim() });
                      if (e.key === "Escape") setEditingId(null);
                    }}
                  />
                  <Button
                    type="button"
                    size="sm"
                    disabled={!editName.trim() || rename.isPending}
                    onClick={() => rename.mutate({ id: p.id, name: editName.trim() })}
                  >
                    Save
                  </Button>
                  <Button type="button" variant="ghost" size="sm" onClick={() => setEditingId(null)}>
                    Cancel
                  </Button>
                </div>
              ) : (
                <div
                  key={p.id}
                  className="flex items-center justify-between rounded-md border border-border px-3 py-2"
                >
                  <div className="flex items-center gap-2">
                    <span className="text-sm font-medium">{p.name}</span>
                    {!p.active && <Badge variant="outline">Inactive</Badge>}
                  </div>
                  <div className="flex gap-1">
                    <Button variant="ghost" size="icon" onClick={() => startEdit(p)} title="Rename">
                      <Pencil className="size-3.5" />
                    </Button>
                    <Button variant="ghost" size="sm" onClick={() => toggle.mutate(p)}>
                      {p.active ? "Deactivate" : "Activate"}
                    </Button>
                    <Button variant="ghost" size="icon" onClick={() => remove.mutate(p.id)} title="Delete">
                      <Trash2 className="size-3.5" />
                    </Button>
                  </div>
                </div>
              )
            )
          )}
        </div>
      </DialogBody>
      <DialogFooter>
        <Button type="button" variant="secondary" onClick={onClose}>
          Done
        </Button>
      </DialogFooter>
    </Dialog>
  );
}

function todayInputValue(): string {
  const d = new Date();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${d.getFullYear()}-${m}-${day}`;
}

function isoToInput(iso: string | null): string {
  if (!iso) return "";
  const d = new Date(iso);
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${d.getFullYear()}-${m}-${day}`;
}

function initPostForm(post: PostDTO | null) {
  return {
    title: post?.title ?? "",
    content: post?.content ?? "",
    mediaUrl: post?.mediaUrl ?? "",
    mediaNotes: post?.mediaNotes ?? "",
    scheduledDate: isoToInput(post?.scheduledDate ?? null),
    platformIds: post?.platforms.map((p) => p.id) ?? [],
  };
}
