'use client';

import { useState, useEffect, useCallback } from 'react';
import Link from 'next/link';
import { useApi } from '@/lib/useApi';
import { SetPageHeader } from '@/components/layout/SetPageHeader';
import {
  listPurchases,
  createPurchase,
  receivePurchase,
  deletePurchase,
} from '@/services/purchases';
import { listStores } from '@/services/stores';
import { listMedicines, listMedicineProducts } from '@/services/medicines';
import type { z } from 'zod/v4';
import type { PurchaseResponseSchema } from '@meshitrack/shared';

type PurchaseResponse = z.infer<typeof PurchaseResponseSchema>;

type StoreOption = { _id: string; name: string };
type MedicineOption = { _id: string; name: string; strength: number; strengthUnit: string };
type ProductOption = { _id: string; brand?: string; packageSize: number; packageUnit: string };

function formatDate(dateStr: string): string {
  return new Date(dateStr).toLocaleDateString();
}

// --- Create purchase form ---

function CreatePurchaseForm({
  householdId,
  stores,
  onCreated,
  onCancel,
}: {
  householdId: string;
  stores: StoreOption[];
  onCreated: () => void;
  onCancel: () => void;
}) {
  const [storeId, setStoreId] = useState('');
  const [isOnline, setIsOnline] = useState(false);
  const [notes, setNotes] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState('');

  // Line items
  const [medicines, setMedicines] = useState<MedicineOption[]>([]);
  const [items, setItems] = useState<
    Array<{
      medicineId: string;
      medicineProductId: string;
      products: ProductOption[];
      productsLoading: boolean;
      name: string;
      quantity: string;
      unit: string;
      actualPrice: string;
      currency: string;
    }>
  >([
    {
      medicineId: '',
      medicineProductId: '',
      products: [],
      productsLoading: false,
      name: '',
      quantity: '',
      unit: 'tablet',
      actualPrice: '',
      currency: 'USD',
    },
  ]);

  useEffect(() => {
    listMedicines(householdId, { limit: 100 })
      .then((r) => setMedicines(r.data))
      .catch(() => {});
  }, [householdId]);

  async function handleMedicineChange(idx: number, medicineId: string) {
    const updated = items.map((item, i) =>
      i === idx
        ? {
            ...item,
            medicineId,
            medicineProductId: '',
            products: [],
            productsLoading: !!medicineId,
          }
        : item,
    );
    setItems(updated);
    if (!medicineId) return;
    try {
      const result = await listMedicineProducts(householdId, medicineId, { limit: 50 });
      setItems((prev) =>
        prev.map((item, i) =>
          i === idx
            ? { ...item, products: result.data as ProductOption[], productsLoading: false }
            : item,
        ),
      );
    } catch {
      setItems((prev) =>
        prev.map((item, i) => (i === idx ? { ...item, productsLoading: false } : item)),
      );
    }
  }

  function handleProductChange(idx: number, productId: string) {
    setItems((prev) =>
      prev.map((item, i) => {
        if (i !== idx) return item;
        const product = item.products.find((p) => p._id === productId);
        return {
          ...item,
          medicineProductId: productId,
          ...(product
            ? {
                quantity: String(product.packageSize),
                unit: product.packageUnit,
                name: product.brand ?? item.name,
              }
            : {}),
        };
      }),
    );
  }

  function addItem() {
    setItems((prev) => [
      ...prev,
      {
        medicineId: '',
        medicineProductId: '',
        products: [],
        productsLoading: false,
        name: '',
        quantity: '',
        unit: 'tablet',
        actualPrice: '',
        currency: 'USD',
      },
    ]);
  }

  function removeItem(idx: number) {
    setItems((prev) => prev.filter((_, i) => i !== idx));
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!storeId) {
      setError('Please select a store.');
      return;
    }
    const validItems = items.filter((item) => item.name.trim() && item.quantity);
    if (validItems.length === 0) {
      setError('Add at least one item with a name and quantity.');
      return;
    }
    setError('');
    setSubmitting(true);
    try {
      await createPurchase(householdId, {
        storeId,
        status: isOnline ? 'ordered' : 'in_cabinet',
        notes: notes.trim() || undefined,
        items: validItems.map((item) => ({
          medicineProductId: item.medicineProductId || undefined,
          name: item.name.trim(),
          quantity: Number(item.quantity),
          unit: item.unit,
          actualPrice: item.actualPrice ? Number(item.actualPrice) : undefined,
          currency: item.currency.trim() || undefined,
        })),
      });
      onCreated();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create purchase');
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="mt-card mb-6">
      <h2 className="text-lg font-semibold mb-4">Record Purchase</h2>
      {error && <div className="mt-alert mt-alert--danger mb-4">{error}</div>}
      <form onSubmit={handleSubmit} className="space-y-5">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div>
            <label className="mt-field-label">Store</label>
            <select
              value={storeId}
              onChange={(e) => setStoreId(e.target.value)}
              required
              className="mt-field"
            >
              <option value="">Select store</option>
              {stores.map((s) => (
                <option key={s._id} value={s._id}>
                  {s.name}
                </option>
              ))}
            </select>
            {stores.length === 0 && (
              <p className="text-xs text-gray-400 mt-1">
                No stores yet.{' '}
                <Link href="/stores" className="mt-link">
                  Add a store first
                </Link>
              </p>
            )}
          </div>

          <div className="flex items-center gap-3 pt-5">
            <input
              type="checkbox"
              id="isOnline"
              checked={isOnline}
              onChange={(e) => setIsOnline(e.target.checked)}
              className="h-4 w-4 rounded border-gray-300"
            />
            <label htmlFor="isOnline" className="text-sm font-medium text-gray-700">
              Online order (pending arrival)
            </label>
          </div>
        </div>

        <div>
          <label className="mt-field-label">Notes (optional)</label>
          <input
            type="text"
            maxLength={1000}
            value={notes}
            onChange={(e) => setNotes(e.target.value)}
            className="mt-field"
          />
        </div>

        <div>
          <div className="flex items-center justify-between mb-2">
            <h3 className="text-sm font-semibold text-gray-700">Items</h3>
            <button type="button" onClick={addItem} className="mt-btn mt-btn--ghost">
              Add item
            </button>
          </div>

          <div className="space-y-4">
            {items.map((item, idx) => (
              <div key={idx} className="rounded-lg border p-4 space-y-3">
                <div className="flex items-center justify-between">
                  <span className="text-xs font-medium text-gray-500">Item {idx + 1}</span>
                  {items.length > 1 && (
                    <button
                      type="button"
                      onClick={() => removeItem(idx)}
                      className="mt-link text-xs"
                    >
                      Remove
                    </button>
                  )}
                </div>

                <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
                  <div>
                    <label className="mt-field-label">Medicine (optional)</label>
                    <select
                      value={item.medicineId}
                      onChange={(e) => handleMedicineChange(idx, e.target.value)}
                      className="mt-field"
                    >
                      <option value="">Select medicine</option>
                      {medicines.map((m) => (
                        <option key={m._id} value={m._id}>
                          {m.name} ({m.strength} {m.strengthUnit})
                        </option>
                      ))}
                    </select>
                  </div>

                  <div>
                    <label className="mt-field-label">Product (optional)</label>
                    {item.productsLoading ? (
                      <div className="animate-pulse h-10 rounded-lg bg-gray-200" />
                    ) : (
                      <select
                        value={item.medicineProductId}
                        onChange={(e) => handleProductChange(idx, e.target.value)}
                        disabled={!item.medicineId}
                        className="mt-field"
                      >
                        <option value="">
                          {item.medicineId ? 'Select product' : 'Select medicine first'}
                        </option>
                        {item.products.map((p) => (
                          <option key={p._id} value={p._id}>
                            {p.brand ?? 'Generic'} — {p.packageSize} {p.packageUnit}
                          </option>
                        ))}
                      </select>
                    )}
                  </div>
                </div>

                <div className="grid grid-cols-1 gap-3 md:grid-cols-4">
                  <div className="md:col-span-2">
                    <label className="mt-field-label">Name</label>
                    <input
                      type="text"
                      required
                      maxLength={200}
                      value={item.name}
                      onChange={(e) =>
                        setItems((prev) =>
                          prev.map((it, i) => (i === idx ? { ...it, name: e.target.value } : it)),
                        )
                      }
                      placeholder="Brand / product name"
                      className="mt-field"
                    />
                  </div>

                  <div>
                    <label className="mt-field-label">Package size</label>
                    <input
                      type="number"
                      required
                      min={0.01}
                      step="any"
                      value={item.quantity}
                      onChange={(e) =>
                        setItems((prev) =>
                          prev.map((it, i) =>
                            i === idx ? { ...it, quantity: e.target.value } : it,
                          ),
                        )
                      }
                      placeholder="90"
                      className="mt-field"
                    />
                  </div>

                  <div>
                    <label className="mt-field-label">Unit</label>
                    <input
                      type="text"
                      required
                      value={item.unit}
                      onChange={(e) =>
                        setItems((prev) =>
                          prev.map((it, i) => (i === idx ? { ...it, unit: e.target.value } : it)),
                        )
                      }
                      placeholder="tablet"
                      className="mt-field"
                    />
                  </div>
                </div>

                <div className="grid grid-cols-2 gap-3">
                  <div>
                    <label className="mt-field-label">Price (optional)</label>
                    <input
                      type="number"
                      min={0.01}
                      step="any"
                      value={item.actualPrice}
                      onChange={(e) =>
                        setItems((prev) =>
                          prev.map((it, i) =>
                            i === idx ? { ...it, actualPrice: e.target.value } : it,
                          ),
                        )
                      }
                      placeholder="9.99"
                      className="mt-field"
                    />
                  </div>
                  <div>
                    <label className="mt-field-label">Currency</label>
                    <input
                      type="text"
                      maxLength={10}
                      value={item.currency}
                      onChange={(e) =>
                        setItems((prev) =>
                          prev.map((it, i) =>
                            i === idx ? { ...it, currency: e.target.value } : it,
                          ),
                        )
                      }
                      placeholder="USD"
                      className="mt-field"
                    />
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="flex gap-3 pt-2">
          <button type="submit" disabled={submitting} className="mt-btn mt-btn--primary">
            {submitting ? 'Saving...' : 'Save Purchase'}
          </button>
          <button type="button" onClick={onCancel} className="mt-btn mt-btn--ghost">
            Cancel
          </button>
        </div>
      </form>
    </div>
  );
}

// --- Purchase card ---

function PurchaseCard({
  purchase,
  onReceive,
  onDelete,
}: {
  purchase: PurchaseResponse;
  onReceive?: (id: string) => void;
  onDelete?: (id: string) => void;
}) {
  const isOrdered = purchase.status === 'ordered';

  return (
    <div className={`mt-card ${!isOrdered ? '' : ''}`}>
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="font-semibold text-gray-900">{purchase.storeName}</p>
          <p className="text-xs text-gray-400 mt-0.5">{formatDate(purchase.purchasedAt)}</p>
        </div>
        <span className={`mt-pill ${isOrdered ? 'mt-pill--warn' : 'mt-pill--ok'}`}>
          {isOrdered ? 'Pending' : 'Received'}
        </span>
      </div>

      <div className="mt-3 space-y-1">
        {purchase.items.map((item, i) => (
          <div key={i} className="flex items-center justify-between text-sm">
            <span className="text-gray-700">{item.name}</span>
            <span className="text-gray-500">
              {item.quantity} {item.unit}
              {item.actualPrice != null &&
                ` — ${item.actualPrice.toFixed(2)} ${item.currency ?? ''}`}
            </span>
          </div>
        ))}
      </div>

      {purchase.notes && <p className="mt-2 text-xs text-gray-400 italic">{purchase.notes}</p>}

      {(isOrdered || onDelete) && (
        <div className="mt-4 flex gap-2">
          {isOrdered && onReceive && (
            <button onClick={() => onReceive(purchase._id)} className="mt-btn mt-btn--primary">
              Mark as received
            </button>
          )}
          {isOrdered && onDelete && (
            <button onClick={() => onDelete(purchase._id)} className="mt-btn mt-btn--ghost">
              Cancel order
            </button>
          )}
        </div>
      )}
    </div>
  );
}

// --- Main content ---

function PurchasesContent({ householdId }: { householdId: string }) {
  const [stores, setStores] = useState<StoreOption[]>([]);
  const [showForm, setShowForm] = useState(false);
  const [purchases, setPurchases] = useState<PurchaseResponse[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [cursor, setCursor] = useState<string | null>(null);
  const [hasMore, setHasMore] = useState(false);

  useEffect(() => {
    listStores(householdId, { limit: 100 })
      .then((r) => setStores(r.data))
      .catch(() => {});
  }, [householdId]);

  const fetchPurchases = useCallback(
    async (append = false) => {
      if (!append) setLoading(true);
      setError('');
      try {
        const result = await listPurchases(householdId, {
          cursor: append ? (cursor ?? undefined) : undefined,
          limit: 20,
        });
        setPurchases((prev) => (append ? [...prev, ...result.data] : result.data));
        setCursor(result.pagination.cursor);
        setHasMore(result.pagination.hasMore);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load purchases');
      } finally {
        setLoading(false);
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [householdId],
  );

  useEffect(() => {
    setCursor(null);
    fetchPurchases(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [householdId]);

  async function handleReceive(id: string) {
    try {
      await receivePurchase(householdId, id);
      setPurchases((prev) =>
        prev.map((p) => (p._id === id ? { ...p, status: 'in_cabinet' as const } : p)),
      );
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to receive purchase');
    }
  }

  async function handleDelete(id: string) {
    try {
      await deletePurchase(householdId, id);
      setPurchases((prev) => prev.filter((p) => p._id !== id));
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to delete purchase');
    }
  }

  const ordered = purchases.filter((p) => p.status === 'ordered');
  const received = purchases.filter((p) => p.status === 'in_cabinet');

  return (
    <div>
      <div className="flex items-center justify-between mb-6">
        <h1 className="text-2xl font-bold">Purchases</h1>
        <button onClick={() => setShowForm(!showForm)} className="mt-btn mt-btn--primary">
          {showForm ? 'Cancel' : 'Record Purchase'}
        </button>
      </div>

      {showForm && (
        <CreatePurchaseForm
          householdId={householdId}
          stores={stores}
          onCreated={() => {
            setShowForm(false);
            setCursor(null);
            fetchPurchases(false);
          }}
          onCancel={() => setShowForm(false)}
        />
      )}

      {error && (
        <div className="mt-alert mt-alert--danger mb-4">
          {error}
          <button onClick={() => setError('')} className="ml-2 underline">
            Dismiss
          </button>
        </div>
      )}

      {loading ? (
        <div className="animate-pulse space-y-3">
          {Array.from({ length: 3 }).map((_, i) => (
            <div key={i} className="h-28 rounded-xl bg-gray-200" />
          ))}
        </div>
      ) : (
        <div className="space-y-8">
          {ordered.length > 0 && (
            <div>
              <h2 className="text-base font-semibold text-gray-700 mb-3">Pending arrival</h2>
              <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
                {ordered.map((p) => (
                  <PurchaseCard
                    key={p._id}
                    purchase={p}
                    onReceive={handleReceive}
                    onDelete={handleDelete}
                  />
                ))}
              </div>
            </div>
          )}

          {received.length > 0 && (
            <div>
              <h2 className="text-base font-semibold text-gray-700 mb-3">Received</h2>
              <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
                {received.map((p) => (
                  <PurchaseCard key={p._id} purchase={p} />
                ))}
              </div>
            </div>
          )}

          {purchases.length === 0 && (
            <div className="mt-card text-center">
              <p className="text-sm text-gray-500">
                No purchases recorded yet. Record your first purchase to get started.
              </p>
            </div>
          )}

          {hasMore && (
            <div className="text-center">
              <button
                onClick={() => fetchPurchases(true)}
                className="rounded-lg border px-4 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
              >
                Load more
              </button>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

export default function PurchasesPage() {
  const { householdId, isLoading: sessionLoading } = useApi();

  if (sessionLoading) {
    return (
      <>
        <SetPageHeader title="Purchases" subtitle="Order history and pending arrivals" />
        <div style={{ padding: '28px 32px' }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {[1, 2, 3].map((i) => (
              <div
                key={i}
                style={{ height: 64, borderRadius: 'var(--r-md)', background: 'var(--bg-inset)' }}
              />
            ))}
          </div>
        </div>
      </>
    );
  }

  if (!householdId) {
    return (
      <>
        <SetPageHeader title="Purchases" subtitle="Order history and pending arrivals" />
        <div style={{ padding: '28px 32px' }}>
          <div
            style={{
              background: 'var(--bg-elev)',
              border: '1px solid var(--border)',
              borderRadius: 'var(--r-md)',
              padding: 24,
            }}
          >
            <p style={{ color: 'var(--ink-muted)', fontSize: 14 }}>
              You need to{' '}
              <Link href="/settings" style={{ color: 'var(--brand)', textDecoration: 'underline' }}>
                create or join a household
              </Link>{' '}
              before recording purchases.
            </p>
          </div>
        </div>
      </>
    );
  }

  return (
    <>
      <SetPageHeader title="Purchases" subtitle="Order history and pending arrivals" />
      <div className="mt-page">
        <PurchasesContent householdId={householdId} />
      </div>
    </>
  );
}
