"use client";

import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";

import { BulkImportPanel } from "@/components/admin/common/BulkImportPanel";
import { ConfirmDialog } from "@/components/admin/common/ConfirmDialog";
import { useToast } from "@/components/admin/common/ToastProvider";

type ArticleRow = {
  id: string;
  title: string;
  slug: string;
  category: string;
  status: "DRAFT" | "PUBLISHED" | "ARCHIVED";
  editionId?: string | null;
  editionTitle?: string | null;
  readingMinutes: number;
  publishedAtLabel: string;
  coverUrl?: string | null;
};

type EditionOption = {
  id: string;
  title: string;
};

type MagazineListManagerProps = {
  items: ArticleRow[];
  editions: EditionOption[];
};

const ARTICLE_STATUS_OPTIONS = ["DRAFT", "PUBLISHED", "ARCHIVED"] as const;
const EMPTY_EDITION_VALUE = "__NONE__";

const articleImportCsv = `title,slug,category,status,reading_minutes,edition,sections_raw
Premium vodič za top profile,premium-vodic-za-top-profile,Biznis,PUBLISHED,7,biznisportal-izvestaj-o-trzistu-2026,"## Uvod

Premium sadržaj diže konverziju.

## Praksa

Pametno spajanje sadržaja i monetizacije."`;

const articleImportJson = `[
  {
    "title": "Premium vodič za top profile",
    "slug": "premium-vodic-za-top-profile",
    "category": "Biznis",
    "status": "PUBLISHED",
    "reading_minutes": 7
  }
]`;

function createNextRows(
  rows: ArticleRow[],
  ids: string[],
  changes: Partial<Pick<ArticleRow, "status" | "category" | "editionId">>,
  editions: EditionOption[],
) {
  const touched = new Set(ids);
  const editionLookup = new Map(editions.map((edition) => [edition.id, edition.title]));

  return rows.map((row) => {
    if (!touched.has(row.id)) {
      return row;
    }

    const nextEditionId = changes.editionId !== undefined ? changes.editionId : row.editionId;

    return {
      ...row,
      ...changes,
      editionId: nextEditionId,
      editionTitle: nextEditionId ? editionLookup.get(nextEditionId) ?? row.editionTitle : null,
    };
  });
}

export function MagazineListManager({
  items: initialItems,
  editions,
}: MagazineListManagerProps) {
  const router = useRouter();
  const [items, setItems] = useState(initialItems);
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  const [bulkStatus, setBulkStatus] = useState("");
  const [bulkCategory, setBulkCategory] = useState("");
  const [bulkEditionId, setBulkEditionId] = useState("");
  const [categoryDrafts, setCategoryDrafts] = useState<Record<string, string>>(
    Object.fromEntries(initialItems.map((item) => [item.id, item.category])),
  );
  const toast = useToast();
  const [isPending, startTransition] = useTransition();
  const [confirmTarget, setConfirmTarget] = useState<
    | { kind: "one"; item: ArticleRow }
    | { kind: "bulk"; ids: string[] }
    | null
  >(null);

  const allSelected = items.length > 0 && selectedIds.length === items.length;
  const hasBulkChanges = Boolean(bulkStatus || bulkCategory.trim() || bulkEditionId);

  function toggleSelection(id: string) {
    setSelectedIds((current) =>
      current.includes(id) ? current.filter((item) => item !== id) : [...current, id],
    );
  }

  function toggleAll() {
    setSelectedIds(allSelected ? [] : items.map((item) => item.id));
  }

  async function submitUpdate(
    ids: string[],
    changes: Partial<Pick<ArticleRow, "status" | "category" | "editionId">>,
    successMessage: string,
  ) {
    const response = await fetch("/api/admin/magazine/articles/bulk", {
      method: "POST",
      headers: {
        "content-type": "application/json",
      },
      body: JSON.stringify({
        ids,
        changes,
      }),
    });

    const payload = (await response.json()) as { message?: string };
    if (!response.ok) {
      throw new Error(payload.message || "Ažuriranje magazin liste nije uspelo.");
    }

    setItems((current) => createNextRows(current, ids, changes, editions));
    if (changes.category) {
      setCategoryDrafts((current) =>
        Object.fromEntries(
          Object.entries(current).map(([key, value]) => [
            key,
            ids.includes(key) ? changes.category ?? value : value,
          ]),
        ),
      );
    }
    toast.success(successMessage);
    router.refresh();
  }

  function handleInlineUpdate(
    id: string,
    changes: Partial<Pick<ArticleRow, "status" | "category" | "editionId">>,
    successMessage: string,
  ) {
    startTransition(async () => {
      try {
        await submitUpdate([id], changes, successMessage);
      } catch (error) {
        toast.error(error instanceof Error ? error.message : "Inline izmena članka nije uspela.");
      }
    });
  }

  async function submitDelete(ids: string[]) {
    const response = await fetch("/api/admin/magazine/articles/bulk", {
      method: "DELETE",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ ids }),
    });
    const payload = (await response.json()) as { message?: string };
    if (!response.ok) {
      throw new Error(payload.message || "Brisanje članaka nije uspelo.");
    }
    setItems((current) => current.filter((row) => !ids.includes(row.id)));
    setSelectedIds((current) => current.filter((id) => !ids.includes(id)));
    router.refresh();
  }

  function handleDeleteOne(item: ArticleRow) {
    setConfirmTarget({ kind: "one", item });
  }

  function handleBulkDelete() {
    if (selectedIds.length === 0) return;
    setConfirmTarget({ kind: "bulk", ids: [...selectedIds] });
  }

  function performConfirmedDelete() {
    if (!confirmTarget) return;
    const target = confirmTarget;
    setConfirmTarget(null);
    if (target.kind === "one") {
      startTransition(async () => {
        try {
          await submitDelete([target.item.id]);
          toast.success(`Članak „${target.item.title}" je obrisan.`);
        } catch (error) {
          toast.error(error instanceof Error ? error.message : "Brisanje članka nije uspelo.");
        }
      });
    } else {
      const count = target.ids.length;
      startTransition(async () => {
        try {
          await submitDelete(target.ids);
          toast.success(`Obrisano je ${count} članaka.`);
        } catch (error) {
          toast.error(error instanceof Error ? error.message : "Masovno brisanje nije uspelo.");
        }
      });
    }
  }

  function handleBulkApply() {
    const changes: Partial<Pick<ArticleRow, "status" | "category" | "editionId">> = {};

    if (bulkStatus) {
      changes.status = bulkStatus as ArticleRow["status"];
    }

    if (bulkCategory.trim()) {
      changes.category = bulkCategory.trim();
    }

    if (bulkEditionId) {
      changes.editionId = bulkEditionId === EMPTY_EDITION_VALUE ? null : bulkEditionId;
    }

    startTransition(async () => {
      try {
        await submitUpdate(
          selectedIds,
          changes,
          `Masovna izmena je sačuvana za ${selectedIds.length} magazin članaka.`,
        );
        setSelectedIds([]);
      } catch (error) {
        toast.error(error instanceof Error ? error.message : "Masovna izmena magazina nije uspela.");
      }
    });
  }

  return (
    <div className="space-y-6">
      <BulkImportPanel
        title="Masovni import magazin članaka"
        description="Napuni magazin većim setom tekstova iz CSV/JSON fajla, pa odmah upravljaj statusom, kategorijom i izdanjem iz jedne komandne liste."
        endpoint="/api/admin/magazine/articles/import"
        sampleCsv={articleImportCsv}
        sampleJson={articleImportJson}
      />

      <div className="admin-toolbar overflow-hidden rounded-[2rem]">
        <div className="flex flex-col gap-4 border-b border-border px-5 py-4 xl:flex-row xl:items-center xl:justify-between">
          <div className="flex flex-wrap items-center gap-3">
            <span className="admin-chip">Ukupno: {items.length}</span>
            <span className="admin-chip">Označeno: {selectedIds.length}</span>
          </div>
          <div className="text-sm text-muted-foreground">
            Magazin tim sada može da vodi status, kategoriju i izdanje direktno iz kontrolne liste.
          </div>
        </div>

        <div className="border-b border-border px-5 py-4">
          <div className="grid gap-3 xl:grid-cols-[220px_minmax(0,1fr)_minmax(0,1fr)_auto]">
            <select
              value={bulkStatus}
              onChange={(event) => setBulkStatus(event.target.value)}
              aria-label="Bulk status za magazin"
              className="inline-select"
            >
              <option value="">Bulk status</option>
              {ARTICLE_STATUS_OPTIONS.map((status) => (
                <option key={status} value={status}>
                  {status}
                </option>
              ))}
            </select>
            <input
              value={bulkCategory}
              onChange={(event) => setBulkCategory(event.target.value)}
              aria-label="Bulk kategorija za magazin"
              className="inline-select"
              placeholder="Bulk kategorija"
            />
            <select
              value={bulkEditionId}
              onChange={(event) => setBulkEditionId(event.target.value)}
              aria-label="Bulk izdanje za magazin"
              className="inline-select"
            >
              <option value="">Bulk PDF izdanje</option>
              <option value={EMPTY_EDITION_VALUE}>Bez PDF izdanja</option>
              {editions.map((edition) => (
                <option key={edition.id} value={edition.id}>
                  {edition.title}
                </option>
              ))}
            </select>
            <button
              type="button"
              onClick={handleBulkApply}
              disabled={isPending || selectedIds.length === 0 || !hasBulkChanges}
              className="primary-button"
            >
              {isPending ? "Čuvanje..." : "Primeni na označene"}
            </button>
          </div>
          <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
            <span />
            {/* Status changes now surface via toast notifications. */}
            <button
              type="button"
              onClick={handleBulkDelete}
              disabled={isPending || selectedIds.length === 0}
              className="ghost-button border-red-300 text-red-600 hover:bg-red-50"
            >
              {isPending ? "Brisanje..." : `Obriši označene (${selectedIds.length})`}
            </button>
          </div>
        </div>

        <div className="overflow-x-auto">
          <table className="admin-data-table text-left">
            <thead className="bg-white/75">
              <tr>
                <th className="px-5 py-4">
                  <input
                    type="checkbox"
                    checked={allSelected}
                    onChange={toggleAll}
                    aria-label="Označi sve članke"
                  />
                </th>
                {["Članak", "Kategorija", "Status", "PDF izdanje", "Objava", "Akcija"].map(
                  (column) => (
                    <th
                      key={column}
                      className="px-5 py-4 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground"
                    >
                      {column}
                    </th>
                  ),
                )}
              </tr>
            </thead>
            <tbody className="divide-y divide-border/70">
              {items.map((item) => (
                <tr key={item.id} className="bg-white/55">
                  <td className="px-5 py-4 align-top">
                    <input
                      type="checkbox"
                      checked={selectedIds.includes(item.id)}
                      onChange={() => toggleSelection(item.id)}
                      aria-label={`Označi članak ${item.title}`}
                    />
                  </td>
                  <td className="px-5 py-4 align-top">
                    <div className="flex min-w-[280px] items-start gap-3">
                      {item.coverUrl ? (
                        <Image
                          src={item.coverUrl}
                          alt={item.title}
                          width={84}
                          height={64}
                          className="h-16 w-20 rounded-[1rem] object-cover"
                        />
                      ) : (
                        <div className="flex h-16 w-20 items-center justify-center rounded-[1rem] border border-dashed border-border bg-background/70 text-[11px] text-muted-foreground">
                          Bez cover-a
                        </div>
                      )}
                      <div>
                        <div className="font-semibold text-foreground">{item.title}</div>
                        <div className="mt-1 text-xs uppercase tracking-[0.14em] text-muted-foreground">
                          {item.slug}
                        </div>
                        <div className="mt-2 text-sm text-muted-foreground">
                          {item.readingMinutes} min čitanja
                        </div>
                      </div>
                    </div>
                  </td>
                  <td className="px-5 py-4 align-top">
                    <div className="flex min-w-[220px] gap-2">
                      <input
                        value={categoryDrafts[item.id] ?? ""}
                        onChange={(event) =>
                          setCategoryDrafts((current) => ({
                            ...current,
                            [item.id]: event.target.value,
                          }))
                        }
                        aria-label={`Kategorija za članak ${item.title}`}
                        className="inline-select"
                      />
                      <button
                        type="button"
                        onClick={() =>
                          handleInlineUpdate(
                            item.id,
                            { category: (categoryDrafts[item.id] ?? "").trim() },
                            `Kategorija članka "${item.title}" je ažurirana.`,
                          )
                        }
                        disabled={isPending || !(categoryDrafts[item.id] ?? "").trim()}
                        className="ghost-button px-4"
                      >
                        Sačuvaj
                      </button>
                    </div>
                  </td>
                  <td className="px-5 py-4 align-top">
                    <select
                      value={item.status}
                      onChange={(event) =>
                        handleInlineUpdate(
                          item.id,
                          { status: event.target.value as ArticleRow["status"] },
                          `Status članka "${item.title}" je ažuriran.`,
                        )
                      }
                      disabled={isPending}
                      aria-label={`Status za članak ${item.title}`}
                      className="inline-select"
                    >
                      {ARTICLE_STATUS_OPTIONS.map((status) => (
                        <option key={status} value={status}>
                          {status}
                        </option>
                      ))}
                    </select>
                  </td>
                  <td className="px-5 py-4 align-top">
                    <select
                      value={item.editionId ?? EMPTY_EDITION_VALUE}
                      onChange={(event) =>
                        handleInlineUpdate(
                          item.id,
                          {
                            editionId:
                              event.target.value === EMPTY_EDITION_VALUE
                                ? null
                                : event.target.value,
                          },
                          `PDF izdanje za članak "${item.title}" je ažurirano.`,
                        )
                      }
                      disabled={isPending}
                      aria-label={`PDF izdanje za članak ${item.title}`}
                      className="inline-select min-w-[260px]"
                    >
                      <option value={EMPTY_EDITION_VALUE}>Bez PDF izdanja</option>
                      {editions.map((edition) => (
                        <option key={edition.id} value={edition.id}>
                          {edition.title}
                        </option>
                      ))}
                    </select>
                    <div className="mt-2 text-xs text-muted-foreground">
                      {item.editionTitle || "Nije povezano"}
                    </div>
                  </td>
                  <td className="px-5 py-4 align-top text-sm text-muted-foreground">
                    {item.publishedAtLabel}
                  </td>
                  <td className="px-5 py-4 align-top">
                    <div className="flex flex-wrap gap-2">
                      <Link href={`/admin/magazin/${item.id}`} className="ghost-button">
                        Otvori detalj
                      </Link>
                      <button
                        type="button"
                        onClick={() => handleDeleteOne(item)}
                        disabled={isPending}
                        className="ghost-button border-red-300 text-red-600 hover:bg-red-50"
                        aria-label={`Obriši članak ${item.title}`}
                      >
                        Obriši
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <ConfirmDialog
        open={confirmTarget !== null}
        destructive
        title={
          confirmTarget?.kind === "one"
            ? `Obriši članak „${confirmTarget.item.title}"`
            : confirmTarget?.kind === "bulk"
              ? `Obriši ${confirmTarget.ids.length} članaka`
              : ""
        }
        message="Ova akcija je nepovratna. Članak će biti uklonjen iz baze i sa javnog sajta."
        confirmLabel="Obriši"
        onConfirm={performConfirmedDelete}
        onCancel={() => setConfirmTarget(null)}
        isPending={isPending}
      />
    </div>
  );
}
