'use client';

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
import { api } from '@/lib/api';
import { useAuthStore } from '@/stores/auth';
import { isCommandCurrent, requireSelectedStore } from '@/lib/stores/store-context';
import { CategoryAutocomplete } from '@/components/seller/category-autocomplete';
import { ImageUploader } from '@/components/seller/image-uploader';
import { ItemStatusBadge } from '@/components/seller/item-status-badge';

type Condition = 'NWT' | 'NWOT' | 'EUC' | 'GUC' | 'Fair' | 'Poor';
const CONDITIONS: Condition[] = ['NWT', 'NWOT', 'EUC', 'GUC', 'Fair', 'Poor'];

interface ItemImage { id: number; url: string; thumb_url: string; order_column: number }
interface ItemDetail {
  id: string;
  title: string;
  description: string | null;
  category: { id: number; name: string } | null;
  brand: string | null;
  size: string | null;
  condition: Condition;
  colors: string[] | null;
  price: number;
  status: string;
  images: ItemImage[];
}

interface FormState {
  title: string;
  description: string;
  category_id: number | null;
  brand: string;
  size: string;
  condition: Condition;
  colors: string[];
  price_dollars: string;
}

function emptyForm(): FormState {
  return { title: '', description: '', category_id: null, brand: '', size: '', condition: 'GUC', colors: [], price_dollars: '' };
}

function formFromItem(it: ItemDetail): FormState {
  return {
    title: it.title ?? '',
    description: it.description ?? '',
    category_id: it.category?.id ?? null,
    brand: it.brand ?? '',
    size: it.size ?? '',
    condition: it.condition,
    colors: it.colors ?? [],
    price_dollars: it.price ? (it.price / 100).toFixed(2) : '',
  };
}

function toPayload(f: FormState) {
  // Save draft is disabled until category_id is set, so this assertion is safe.
  if (f.category_id === null) {
    throw new Error('Category is required before saving a draft.');
  }
  const price = f.price_dollars.trim()
    ? Math.round(parseFloat(f.price_dollars) * 100)
    : null;
  return {
    title: f.title,
    description: f.description || null,
    category_id: f.category_id,
    brand: f.brand || null,
    size: f.size || null,
    condition: f.condition,
    colors: f.colors,
    price,
  };
}

function canPublish(f: FormState, images: ItemImage[]): string | null {
  if (!f.title.trim()) return 'Title is required';
  if (!f.category_id) return 'Category is required';
  if (!f.condition) return 'Condition is required';
  if (images.length === 0) return 'At least one image is required';
  const price = Math.round(parseFloat(f.price_dollars || '0') * 100);
  if (price <= 0) return 'Price must be greater than $0';
  return null;
}

export function ItemForm({ storeId, itemId }: { storeId: string; itemId?: string }) {
  const generation = useAuthStore(state => state.commandGeneration);
  const router = useRouter();
  const qc = useQueryClient();
  const [form, setForm] = useState<FormState>(emptyForm());
  const [images, setImages] = useState<ItemImage[]>([]);
  const [status, setStatus] = useState<string>('draft');
  const [savedAt, setSavedAt] = useState<Date | null>(null);
  const [error, setError] = useState<string | null>(null);

  const itemQ = useQuery({
    queryKey: ['seller-item', storeId, itemId],
    enabled: !!itemId,
    queryFn: () => api.items.get(storeId, itemId!),
  });

  const syncedItemIdRef = useRef<string | null>(null);
  useEffect(() => {
    const detail = itemQ.data?.data as ItemDetail | undefined;
    if (!detail) return;
    if (syncedItemIdRef.current === detail.id) return;
    syncedItemIdRef.current = detail.id;
    // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing loaded item data to local form state
    setForm(formFromItem(detail));
    setImages(detail.images ?? []);
    setStatus(detail.status);
  }, [itemQ.data]);

  const mounted = useRef(false);
  useEffect(() => {
    mounted.current = true;
    return () => { mounted.current = false; };
  }, []);
  type ItemCommand = { generation: number; storeId: string; itemId?: string; form: FormState };
  const command = (): ItemCommand => ({ generation, storeId, itemId, form });
  const isVisible = (origin: ItemCommand) => mounted.current && isCommandCurrent(origin.generation)
    && origin.storeId === storeId && origin.itemId === itemId;
  const createMut = useMutation({
    mutationFn: ({ generation, storeId, form }: ItemCommand) => api.items.create(requireSelectedStore(storeId, 'store.admin', generation), toPayload(form)),
    onSuccess: (res, origin) => {
      if (!isVisible(origin)) return;
      const detail = res.data as unknown as ItemDetail;
      router.replace(`/seller/listings/${detail.id}`);
    },
    onError: (_error, origin) => { if (isVisible(origin)) setError('Failed to create item.'); },
  });

  const updateMut = useMutation({
    mutationFn: ({ generation, storeId, itemId, form }: ItemCommand) => api.items.update(requireSelectedStore(storeId, 'store.admin', generation), itemId!, toPayload(form)),
    onSuccess: (_data, origin) => {
      if (isVisible(origin)) setSavedAt(new Date());
      qc.invalidateQueries({ queryKey: ['seller-item', origin.storeId, origin.itemId], refetchType: isVisible(origin) ? 'active' : 'none' });
    },
    onError: (_error, origin) => { if (isVisible(origin)) setError('Failed to save changes.'); },
  });

  const publishMut = useMutation({
    mutationFn: ({ generation, storeId, itemId }: ItemCommand) => api.items.publish(requireSelectedStore(storeId, 'store.admin', generation), itemId!),
    onSuccess: (_data, origin) => {
      if (isVisible(origin)) setStatus('active');
      const refetchType = isVisible(origin) ? 'active' : 'none';
      qc.invalidateQueries({ queryKey: ['seller-item', origin.storeId, origin.itemId], refetchType });
      qc.invalidateQueries({ queryKey: ['seller-items', origin.storeId], refetchType });
    },
    onError: (_error, origin) => { if (isVisible(origin)) setError('Failed to publish.'); },
  });

  const removeMut = useMutation({
    mutationFn: ({ generation, storeId, itemId }: ItemCommand) => api.items.remove(requireSelectedStore(storeId, 'store.admin', generation), itemId!),
    onSuccess: (_data, origin) => {
      if (isVisible(origin)) setStatus('removed');
      qc.invalidateQueries({ queryKey: ['seller-items', origin.storeId], refetchType: isVisible(origin) ? 'active' : 'none' });
    },
  });

  const relistMut = useMutation({
    mutationFn: ({ generation, storeId, itemId }: ItemCommand) => api.items.relist(requireSelectedStore(storeId, 'store.admin', generation), itemId!),
    onSuccess: (_data, origin) => {
      if (isVisible(origin)) setStatus('active');
      qc.invalidateQueries({ queryKey: ['seller-items', origin.storeId], refetchType: isVisible(origin) ? 'active' : 'none' });
    },
  });

  const autosaveRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  useEffect(() => () => {
    if (autosaveRef.current !== null) clearTimeout(autosaveRef.current);
  }, [storeId, itemId, generation]);
  const scheduleAutosave = (nextForm: FormState = form) => {
    if (!itemId) return;
    if (autosaveRef.current) clearTimeout(autosaveRef.current);
    const origin = { ...command(), form: nextForm };
    autosaveRef.current = setTimeout(() => {
      autosaveRef.current = null;
      if (isCommandCurrent(origin.generation)) updateMut.mutate(origin);
    }, 1000);
  };

  const savedText = savedAt ? `Saved at ${savedAt.toLocaleTimeString()}` : '';
  const publishBlocker = canPublish(form, images);

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <button onClick={() => router.push('/seller/listings')} className="text-sm text-ink/60 hover:text-ink">
            &larr; Listings
          </button>
          <h1 className="mt-1 text-2xl font-bold text-ink">
            {itemId ? 'Edit item' : 'New item'}
          </h1>
          <div className="mt-2 flex items-center gap-2 text-sm text-ink/70">
            <ItemStatusBadge status={status} />
            {savedText && <span className="text-xs text-ink/50">{savedText}</span>}
          </div>
        </div>
        <div className="flex gap-2">
          {!itemId && (
            <button
              onClick={() => createMut.mutate(command())}
              disabled={createMut.isPending || !form.title.trim() || !form.category_id}
              title={!form.title.trim() ? 'Title required' : !form.category_id ? 'Category required' : undefined}
              className="rounded border border-forest/20 px-3 py-1.5 text-sm hover:bg-bone disabled:opacity-50"
            >
              {createMut.isPending ? 'Saving…' : 'Save draft'}
            </button>
          )}
          {itemId && status === 'draft' && (
            <button
              onClick={() => publishMut.mutate(command())}
              disabled={publishBlocker !== null || publishMut.isPending}
              title={publishBlocker ?? undefined}
              className="rounded bg-forest px-3 py-1.5 text-sm font-semibold text-white hover:bg-forest/90 disabled:opacity-50"
            >
              {publishMut.isPending ? 'Publishing…' : 'Publish'}
            </button>
          )}
          {itemId && status === 'active' && (
            <button onClick={() => removeMut.mutate(command())} className="rounded border border-terracotta/30 px-3 py-1.5 text-sm text-terracotta hover:bg-terracotta/5">
              Remove
            </button>
          )}
          {itemId && status === 'removed' && (
            <button onClick={() => relistMut.mutate(command())} className="rounded bg-forest px-3 py-1.5 text-sm font-semibold text-white hover:bg-forest/90">
              Relist
            </button>
          )}
        </div>
      </div>

      {error && <div className="rounded bg-red-50 p-3 text-sm text-red-700">{error}</div>}
      {publishBlocker && itemId && status === 'draft' && (
        <div className="rounded bg-amber-50 p-3 text-sm text-amber-800">Before publishing: {publishBlocker}.</div>
      )}

      <Section title="Images">
        {itemId ? (
          <ImageUploader storeId={storeId} itemId={itemId} images={images} onChange={setImages} />
        ) : (
          <p className="text-sm text-ink/60">Save a draft first to upload images.</p>
        )}
      </Section>

      <Section title="Basics">
        <Field label="Title">
          <input
            value={form.title}
            onChange={(e) => setForm({ ...form, title: e.target.value })}
            onBlur={() => scheduleAutosave()}
            className="w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
        <Field label="Category">
          <CategoryAutocomplete
            value={form.category_id}
            onChange={(id) => {
              const nextForm = { ...form, category_id: id };
              setForm(nextForm);
              scheduleAutosave(nextForm);
            }}
          />
        </Field>
        <Field label="Condition">
          <select
            value={form.condition}
            onChange={(e) => {
              const nextForm = { ...form, condition: e.target.value as Condition };
              setForm(nextForm);
              scheduleAutosave(nextForm);
            }}
            className="rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          >
            {CONDITIONS.map((c) => <option key={c} value={c}>{c}</option>)}
          </select>
        </Field>
        <Field label="Description">
          <textarea
            rows={4}
            value={form.description}
            onChange={(e) => setForm({ ...form, description: e.target.value })}
            onBlur={() => scheduleAutosave()}
            className="w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
      </Section>

      <Section title="Details">
        <Field label="Brand">
          <input
            value={form.brand}
            onChange={(e) => setForm({ ...form, brand: e.target.value })}
            onBlur={() => scheduleAutosave()}
            className="w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
        <Field label="Size">
          <input
            value={form.size}
            onChange={(e) => setForm({ ...form, size: e.target.value })}
            onBlur={() => scheduleAutosave()}
            className="w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
        <Field label="Colors (comma-separated, max 5)">
          <input
            value={form.colors.join(', ')}
            onChange={(e) =>
              setForm({
                ...form,
                colors: e.target.value
                  .split(',')
                  .map((c) => c.trim())
                  .filter(Boolean)
                  .slice(0, 5),
              })
            }
            onBlur={() => scheduleAutosave()}
            className="w-full rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
      </Section>

      <Section title="Price">
        <Field label="Listed price (USD)">
          <input
            inputMode="decimal"
            value={form.price_dollars}
            onChange={(e) => setForm({ ...form, price_dollars: e.target.value.replace(/[^0-9.]/g, '') })}
            onBlur={() => scheduleAutosave()}
            className="w-40 rounded border border-forest/20 bg-white px-2 py-1.5 text-sm"
          />
        </Field>
      </Section>
    </div>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="rounded-md border border-forest/20 bg-white p-5">
      <h2 className="text-sm font-semibold uppercase tracking-wide text-ink/60">{title}</h2>
      <div className="mt-4 space-y-4">{children}</div>
    </section>
  );
}

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <label className="flex flex-col gap-1 text-sm">
      <span className="text-xs uppercase tracking-wide text-ink/60">{label}</span>
      {children}
    </label>
  );
}
