"use client";
/* eslint-disable @next/next/no-img-element */

import { ChangeEvent, useEffect, useRef, useState } from "react";
import { Pencil, X } from "lucide-react";
import { SbisCatalogPanel } from "./sbis-catalog-panel";

type Category = { id: number; slug: string; name: string; yandexCategoryId: number; sortOrder: number; isActive: boolean; archivedAt: Date | string | null; sbisCategoryId: string | null; sbisCategoryNameSnapshot: string | null; categorySyncState: string };
type Item = { id: number; slug: string; categoryId: number; name: string; description: string | null; shortDescription: string | null; ingredients: string | null; weightText: string | null; imageUrl: string | null; isAvailable: boolean; isAlcohol: boolean; showOnWebsite: boolean; showDetails: boolean; publishToYandex: boolean; allowOnlineOrder: boolean; allowDelivery: boolean; archivedAt: Date | string | null };
type Variant = { id: number; itemId: number; label: string; priceKopecks: number; yandexOfferId: string; isAvailable: boolean };
type Link = { id: number; menuItemId: number; sbisId: string; unlinkedAt: Date | string | null; unlinkReason: string | null };
type SyncState = { lastAttemptAt: string | null; lastSuccessAt: string | null; lastDurationMs: number | null; lastError: string | null; lastSnapshotId: string | null; sourceVersion: string | null; itemsCount: number; categoriesCount: number } | null;
type AuditEvent = { id: number; actor: string; action: string; entityType: string | null; entityId: string | null; createdAt: string };
export type Data = { categories: Category[]; items: Item[]; variants: Variant[]; links?: Link[]; syncState?: SyncState; auditEvents?: AuditEvent[]; categorySbis?: Record<string, { id: string | null; name: string }[]> };
type ItemDraft = Pick<Item, "name" | "description" | "shortDescription" | "weightText" | "imageUrl" | "isAvailable" | "isAlcohol" | "showOnWebsite" | "publishToYandex" | "allowOnlineOrder" | "allowDelivery"> & { priceRubles: string };

async function mutate(method: string, body: unknown) {
  const csrf = document.cookie.split("; ").find((part) => part.startsWith("kiln-admin-csrf="))?.split("=")[1];
  const response = await fetch("/api/admin/menu", { method, headers: { "content-type": "application/json", ...(csrf ? { "x-csrf-token": decodeURIComponent(csrf) } : {}) }, body: JSON.stringify(body) });
  if (!response.ok) throw new Error((await response.json()).error || "Ошибка сохранения");
}

function csrfHeaders() {
  const csrf = document.cookie.split("; ").find((part) => part.startsWith("kiln-admin-csrf="))?.split("=")[1];
  return csrf ? { "x-csrf-token": decodeURIComponent(csrf) } : {} as Record<string, string>;
}

function ImageUploader({ item, onUploaded, onRemoved }: { item: Item; onUploaded: (url: string) => Promise<void>; onRemoved: () => Promise<void> }) {
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState("");

  async function upload(event: ChangeEvent<HTMLInputElement>) {
    const file = event.target.files?.[0];
    event.target.value = "";
    if (!file) return;
    setError("");
    setUploading(true);
    try {
      const form = new FormData();
      form.append("file", file);
      form.append("slug", item.slug);
      form.append("name", item.name);
      const response = await fetch("/api/admin/menu/image", { method: "POST", headers: csrfHeaders(), body: form });
      const result = await response.json();
      if (!response.ok) throw new Error(result.error || "Не удалось загрузить фото");
      await onUploaded(result.url);
    } catch (uploadError) {
      setError(uploadError instanceof Error ? uploadError.message : "Не удалось загрузить фото");
    } finally {
      setUploading(false);
    }
  }

  return <div className="mt-3 rounded border border-white/10 bg-black/15 p-3">
    <div className="flex flex-wrap items-center gap-3">
      {item.imageUrl ? <><span className="sr-only">Текущее фото</span>{/* eslint-disable-next-line @next/next/no-img-element */}<img src={item.imageUrl} alt="" className="h-20 w-20 rounded object-cover" /></> : <div className="flex h-20 w-20 items-center justify-center rounded bg-white/5 text-center text-xs text-kiln-milk/45">Нет фото</div>}
      <div className="flex min-w-48 flex-1 flex-wrap gap-2">
        <input ref={inputRef} className="sr-only" type="file" accept="image/jpeg,image/png,image/webp,image/avif" onChange={upload} />
        <button type="button" className="button button-primary" disabled={uploading} onClick={() => inputRef.current?.click()}>{uploading ? "Загрузка…" : item.imageUrl ? "Заменить фото" : "Загрузить фото"}</button>
        {item.imageUrl ? <button type="button" className="button button-secondary" disabled={uploading} onClick={async () => { setError(""); setUploading(true); try { await onRemoved(); } catch (removeError) { setError(removeError instanceof Error ? removeError.message : "Ошибка удаления"); } finally { setUploading(false); } }}>Удалить</button> : null}
        <p className="basis-full text-xs text-kiln-milk/50">JPG, PNG, WebP или AVIF · до 8 МБ. Фото автоматически станет WebP.</p>
      </div>
    </div>
    {error ? <p className="mt-2 text-sm text-kiln-flame">{error}</p> : null}
  </div>;
}

export function AdminMenuPanel({ loggedIn, stats, initialData = null, initialError = "" }: { loggedIn: boolean; stats: { items: number; lastFeed: string } | null; initialData?: Data | null; initialError?: string }) {
  const [login, setLogin] = useState("");
  const [password, setPassword] = useState("");
  const [data, setData] = useState<Data | null>(initialData);
  const [message, setMessage] = useState(initialError);
  const [photoItemId, setPhotoItemId] = useState<number | null>(null);
  const [editItem, setEditItem] = useState<Item | null>(null);
  const [editDraft, setEditDraft] = useState<ItemDraft | null>(null);
  const [savingEdit, setSavingEdit] = useState(false);
  const [category, setCategory] = useState({ name: "", slug: "", yandexCategoryId: "" });
  const [item, setItem] = useState({ name: "", slug: "", categorySlug: "", description: "", weightText: "", priceRubles: "", isAlcohol: false });

  useEffect(() => { if (loggedIn) fetch("/api/admin/menu").then(async (response) => { const result = await response.json(); if (!response.ok) throw new Error(result.error || "Не удалось загрузить меню"); return result; }).then(setData).catch((error) => setMessage(error instanceof Error ? error.message : "Не удалось загрузить меню")); }, [loggedIn]);

  if (!loggedIn) return <main className="section"><div className="site-container max-w-lg"><h1 className="display-title text-5xl">Управление меню</h1><p className="mt-3 muted">Раздел доступен только администратору.</p><form className="mt-6 grid gap-3" onSubmit={async (event) => { event.preventDefault(); const response = await fetch("/api/admin/menu/login", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ login, password }) }); if (response.ok) location.reload(); else setMessage("Неверные данные для входа"); }}><input className="input" type="text" autoComplete="username" value={login} onChange={(event) => setLogin(event.target.value)} placeholder="Логин" /><input className="input" type="password" autoComplete="current-password" value={password} onChange={(event) => setPassword(event.target.value)} placeholder="Пароль" /><button className="button button-primary">Войти</button>{message ? <p className="text-kiln-flame">{message}</p> : null}</form></div></main>;

  const refresh = () => fetch("/api/admin/menu").then((response) => response.json()).then(setData);
  const logout = async () => { await fetch("/api/admin/menu/logout", { method: "POST" }); location.reload(); };
  const save = async (request: Promise<unknown>) => { try { await request; setMessage("Сохранено"); await refresh(); } catch (error) { setMessage(error instanceof Error ? error.message : "Ошибка"); } };
  const updateImage = (current: Item, imageUrl: string | null) => save(mutate("PATCH", { type: "item", id: current.id, name: current.name, description: current.description, shortDescription: current.shortDescription, weightText: current.weightText, imageUrl, isAvailable: current.isAvailable, showOnWebsite: current.showOnWebsite, showDetails: current.showDetails, isAlcohol: current.isAlcohol, allowOnlineOrder: current.allowOnlineOrder, allowDelivery: current.allowDelivery, publishToYandex: current.publishToYandex }));
  const openEditor = (current: Item) => {
    const variant = data?.variants.find((candidate) => candidate.itemId === current.id);
    setEditItem(current);
    setEditDraft({ ...current, priceRubles: variant ? String(variant.priceKopecks / 100) : "" });
  };
  const closeEditor = () => { if (!savingEdit) { setEditItem(null); setEditDraft(null); } };
  const saveEdit = async (event: React.FormEvent) => {
    event.preventDefault();
    if (!editItem || !editDraft) return;
    setSavingEdit(true);
    try {
      await mutate("PATCH", { type: "item", id: editItem.id, ...editDraft });
      const variant = data?.variants.find((candidate) => candidate.itemId === editItem.id);
      if (variant && editDraft.priceRubles) await mutate("PATCH", { type: "variant", id: variant.id, label: variant.label, priceRubles: editDraft.priceRubles, isAvailable: variant.isAvailable });
      if (!variant && editDraft.priceRubles) await mutate("POST", { type: "variant", itemId: editItem.id, label: editDraft.weightText || "1 порция", priceRubles: editDraft.priceRubles, yandexOfferId: `${editItem.slug}-main` });
      setMessage("Позиция сохранена");
      setEditItem(null);
      setEditDraft(null);
      await refresh();
    } catch (error) {
      setMessage(error instanceof Error ? error.message : "Ошибка сохранения");
    } finally {
      setSavingEdit(false);
    }
  };

  return <main className="section"><div className="site-container"><div className="flex flex-wrap items-start justify-between gap-4"><div><p className="eyebrow">Администрирование</p><h1 className="display-title mt-2 text-5xl">Меню</h1></div><button type="button" className="button button-secondary" onClick={logout}>Выйти</button></div><div className="mt-6 grid gap-4 md:grid-cols-3"><div className="card p-5"><span className="muted">Позиций</span><strong className="mt-2 block text-3xl">{stats?.items ?? data?.items.length ?? 0}</strong></div><div className="card p-5"><span className="muted">Последний запрос YML</span><strong className="mt-2 block text-sm">{stats?.lastFeed || "не запрашивался"}</strong></div><a href="/yandex-menu" target="_blank" className="card p-5 text-kiln-flame">Предпросмотр YML →</a></div><SbisCatalogPanel localItems={data?.items || []} links={data?.links || []} syncState={data?.syncState || null} auditEvents={data?.auditEvents || []} />
    <div className="mt-8 grid gap-6 lg:grid-cols-2"><section className="card grid gap-3 p-5"><h2 className="text-2xl">Новая категория</h2><input className="input" placeholder="Название" value={category.name} onChange={(e) => setCategory({ ...category, name: e.target.value })} /><input className="input" placeholder="slug" value={category.slug} onChange={(e) => setCategory({ ...category, slug: e.target.value })} /><input className="input" placeholder="Yandex category ID" type="number" value={category.yandexCategoryId} onChange={(e) => setCategory({ ...category, yandexCategoryId: e.target.value })} /><button className="button button-primary" onClick={() => save(mutate("POST", { type: "category", ...category }))}>Создать категорию</button></section><section className="card grid gap-3 p-5"><h2 className="text-2xl">Новая позиция</h2><input className="input" placeholder="Название" value={item.name} onChange={(e) => setItem({ ...item, name: e.target.value })} /><input className="input" placeholder="slug" value={item.slug} onChange={(e) => setItem({ ...item, slug: e.target.value })} /><select className="input" value={item.categorySlug} onChange={(e) => setItem({ ...item, categorySlug: e.target.value })}><option value="">Категория</option>{data?.categories.filter((c) => c.isActive).map((c) => <option key={c.id} value={c.slug}>{c.name}</option>)}</select><textarea className="input" placeholder="Описание" value={item.description} onChange={(e) => setItem({ ...item, description: e.target.value })} /><input className="input" placeholder="Вес/объём" value={item.weightText} onChange={(e) => setItem({ ...item, weightText: e.target.value })} /><input className="input" placeholder="Цена, ₽" type="number" value={item.priceRubles} onChange={(e) => setItem({ ...item, priceRubles: e.target.value })} /><label className="flex gap-2"><input type="checkbox" checked={item.isAlcohol} onChange={(e) => setItem({ ...item, isAlcohol: e.target.checked })} /> Алкоголь (заказ и доставка будут запрещены)</label><button className="button button-primary" onClick={() => save(mutate("POST", { type: "item", ...item }))}>Создать позицию</button></section></div>
    <section className="mt-8 card p-5"><h2 className="text-2xl">Категории и позиции</h2><p className="mt-2 text-sm text-kiln-milk/60">Карандаш открывает полное редактирование позиции, включая фото и цену.</p><div className="mt-4 grid gap-3">{data?.categories.map((c) => <div key={c.id} className="border-b border-white/10 pb-3"><div className="flex flex-wrap items-center justify-between gap-3"><strong>{c.name}</strong><button className="button button-secondary" onClick={() => save(mutate("PATCH", { type: "category", id: c.id, name: c.name, slug: c.slug, yandexCategoryId: c.yandexCategoryId, isActive: !c.isActive }))}>{c.isActive ? "Выключить" : "Включить"}</button></div>{(() => { const itemCats = data.categorySbis?.[String(c.id)] || []; const mismatch = c.sbisCategoryId !== null && (itemCats.length === 0 || itemCats.some((entry) => entry.id !== c.sbisCategoryId)); return <div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-kiln-milk/60"><span>СБИС: {c.sbisCategoryNameSnapshot || (c.sbisCategoryId ? `id ${c.sbisCategoryId} нет в прайсе` : "не привязана")}</span>{itemCats.length > 1 ? <span className="text-kiln-flame">позиции из нескольких категорий СБИС: {itemCats.map((entry) => entry.name).join(", ")}</span> : null}{mismatch && itemCats.length === 1 ? <span className="text-kiln-flame">расхождение с категорией позиций</span> : null}<input className="input max-w-48 text-xs" placeholder="sbis_category_id" defaultValue={c.sbisCategoryId || ""} onBlur={(event) => { const next = event.target.value.trim(); if (next !== (c.sbisCategoryId || "")) save(mutate("PATCH", { type: "category", id: c.id, name: c.name, slug: c.slug, yandexCategoryId: c.yandexCategoryId, isActive: c.isActive, sbisCategoryId: next || null })); }} /></div>; })()}{data.items.filter((i) => i.categoryId === c.id).map((i) => <div key={i.id} className="mt-2 rounded border border-transparent p-2 pl-4 text-sm transition hover:border-white/10"><div className="flex flex-wrap items-center justify-between gap-2"><div className="flex min-w-0 items-center gap-3">{i.imageUrl ? <>{/* eslint-disable-next-line @next/next/no-img-element */}<img src={i.imageUrl} alt="" className="h-10 w-10 shrink-0 rounded object-cover" /></> : <div className="h-10 w-10 shrink-0 rounded bg-white/5" />}<span>{i.name} · {(data.variants.filter((v) => v.itemId === i.id)[0]?.priceKopecks || 0) / 100} ₽ {i.isAlcohol ? "· 18+" : ""}</span></div><div className="flex flex-wrap gap-2"><button type="button" className="button button-secondary inline-flex items-center gap-2" onClick={() => openEditor(i)}><Pencil size={15} aria-hidden="true" />Редактировать</button><button type="button" className="button button-secondary" onClick={() => save(mutate("PATCH", { type: "item", id: i.id, name: i.name, description: i.description, weightText: i.weightText, isAvailable: !i.isAvailable, showOnWebsite: i.showOnWebsite, showDetails: i.showDetails, isAlcohol: i.isAlcohol, allowOnlineOrder: i.allowOnlineOrder, allowDelivery: i.allowDelivery, publishToYandex: i.publishToYandex, imageUrl: i.imageUrl }))}>{i.isAvailable ? "Снять наличие" : "Включить"}</button><button type="button" className="button button-secondary" onClick={() => save(mutate("DELETE", { type: "item", id: i.id }))}>Архив</button></div></div>{photoItemId === i.id ? <ImageUploader item={i} onUploaded={(url) => updateImage(i, url)} onRemoved={() => updateImage(i, null)} /> : null}</div>)}</div>)}</div></section>{message ? <p className="mt-4 text-kiln-flame">{message}</p> : null}</div>{editItem && editDraft ? <div className="dish-modal" role="presentation" onMouseDown={(event) => event.target === event.currentTarget && closeEditor()}><section className="dish-modal-panel !block max-w-2xl" role="dialog" aria-modal="true" aria-labelledby="admin-edit-title"><div className="dish-modal-content max-h-[92dvh]"><div className="mb-5 flex items-start justify-between gap-4"><div><p className="eyebrow">Позиция меню</p><h2 id="admin-edit-title" className="mt-1 text-2xl">Редактировать блюдо</h2></div><button type="button" className="icon-button" onClick={closeEditor} aria-label="Закрыть"><X size={18} /></button></div><form className="grid gap-3" onSubmit={saveEdit}><input className="input" required placeholder="Название" value={editDraft.name} onChange={(event) => setEditDraft({ ...editDraft, name: event.target.value })} /><textarea className="input min-h-28" placeholder="Описание" value={editDraft.description || ""} onChange={(event) => setEditDraft({ ...editDraft, description: event.target.value })} /><input className="input" placeholder="Короткое описание" value={editDraft.shortDescription || ""} onChange={(event) => setEditDraft({ ...editDraft, shortDescription: event.target.value })} /><div className="grid gap-3 sm:grid-cols-2"><input className="input" placeholder="Вес/объём" value={editDraft.weightText || ""} onChange={(event) => setEditDraft({ ...editDraft, weightText: event.target.value })} /><input className="input" required min="0" step="0.01" type="number" placeholder="Цена, ₽" value={editDraft.priceRubles} onChange={(event) => setEditDraft({ ...editDraft, priceRubles: event.target.value })} /></div><div className="grid gap-2 rounded border border-white/10 p-3"><label className="flex gap-2"><input type="checkbox" checked={editDraft.isAvailable} onChange={(event) => setEditDraft({ ...editDraft, isAvailable: event.target.checked })} /> В наличии</label><label className="flex gap-2"><input type="checkbox" checked={editDraft.showOnWebsite} onChange={(event) => setEditDraft({ ...editDraft, showOnWebsite: event.target.checked })} /> Показывать на сайте</label><label className="flex gap-2"><input type="checkbox" checked={editDraft.publishToYandex} onChange={(event) => setEditDraft({ ...editDraft, publishToYandex: event.target.checked })} /> Публиковать в Яндекс</label><label className="flex gap-2"><input type="checkbox" checked={editDraft.allowOnlineOrder} onChange={(event) => setEditDraft({ ...editDraft, allowOnlineOrder: event.target.checked })} /> Разрешить онлайн-заказ</label><label className="flex gap-2"><input type="checkbox" checked={editDraft.allowDelivery} onChange={(event) => setEditDraft({ ...editDraft, allowDelivery: event.target.checked })} /> Разрешить доставку</label><label className="flex gap-2"><input type="checkbox" checked={editDraft.isAlcohol} onChange={(event) => setEditDraft({ ...editDraft, isAlcohol: event.target.checked })} /> Алкоголь (заказ и доставка будут запрещены)</label></div><ImageUploader item={{ ...editItem, imageUrl: editDraft.imageUrl }} onUploaded={async (url) => setEditDraft({ ...editDraft, imageUrl: url })} onRemoved={async () => setEditDraft({ ...editDraft, imageUrl: null })} /><div className="mt-2 flex justify-end gap-3"><button type="button" className="button button-secondary" onClick={closeEditor} disabled={savingEdit}>Отмена</button><button type="submit" className="button button-primary" disabled={savingEdit}>{savingEdit ? "Сохранение…" : "Сохранить изменения"}</button></div></form></div></section></div> : null}</main>;
}
