'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 { recordPrice, getPriceHistory, compareStores } from '@/services/medicine-prices';
import { listMedicines, listMedicineProducts } from '@/services/medicines';
import { listStores } from '@/services/stores';
import { DosageUnit } from '@meshitrack/shared';
import type { z } from 'zod/v4';
import type {
  MedicinePriceRecordResponseSchema,
  StoreComparisonItemSchema,
} from '@meshitrack/shared';

type PriceRecord = z.infer<typeof MedicinePriceRecordResponseSchema>;
type StoreComparisonItem = z.infer<typeof StoreComparisonItemSchema>;

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

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

function formatCurrency(amount: number, currency?: string): string {
  return currency ? `${currency} ${amount.toFixed(2)}` : amount.toFixed(2);
}

// --- Record price form ---

function RecordPriceForm({
  householdId,
  medicines,
  stores,
  onRecorded,
  onCancel,
}: {
  householdId: string;
  medicines: MedicineOption[];
  stores: StoreOption[];
  onRecorded: () => void;
  onCancel: () => void;
}) {
  const [medicineId, setMedicineId] = useState('');
  const [medicineSearch, setMedicineSearch] = useState('');
  const [products, setProducts] = useState<ProductOption[]>([]);
  const [productsLoading, setProductsLoading] = useState(false);
  const [medicineProductId, setMedicineProductId] = useState('');
  const [storeId, setStoreId] = useState('');
  const [price, setPrice] = useState('');
  const [currency, setCurrency] = useState('USD');
  const [quantity, setQuantity] = useState('');
  const [unit, setUnit] = useState<DosageUnit>(DosageUnit.TABLET);
  const [isInsurancePrice, setIsInsurancePrice] = useState(false);
  const [notes, setNotes] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState('');

  const filteredMedicines = medicineSearch
    ? medicines.filter((m) => m.name.toLowerCase().includes(medicineSearch.toLowerCase()))
    : medicines;

  async function handleMedicineChange(id: string) {
    setMedicineId(id);
    setMedicineProductId('');
    setProducts([]);
    if (!id) return;
    setProductsLoading(true);
    try {
      const result = await listMedicineProducts(householdId, id, { limit: 50 });
      setProducts(result.data as ProductOption[]);
    } catch {
      /* non-fatal */
    } finally {
      setProductsLoading(false);
    }
  }

  function handleProductChange(productId: string) {
    setMedicineProductId(productId);
    const product = products.find((p) => p._id === productId);
    if (product) {
      setQuantity(String(product.packageSize));
      setUnit(product.packageUnit as DosageUnit);
    }
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!medicineId || !medicineProductId || !storeId) {
      setError('Please select a medicine, a product, and a store.');
      return;
    }
    setError('');
    setSubmitting(true);
    try {
      await recordPrice(householdId, {
        medicineId,
        medicineProductId,
        storeId,
        price: Number(price),
        currency: currency.trim(),
        quantity: Number(quantity),
        unit,
        isInsurancePrice,
        notes: notes.trim() || undefined,
      });
      onRecorded();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to record price');
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="mt-card mb-6">
      <h2 className="text-lg font-semibold mb-4">Record Price</h2>
      {error && <div className="mt-alert mt-alert--danger mb-4">{error}</div>}
      <form onSubmit={handleSubmit} className="space-y-4">
        <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>
            <label className="mt-field-label">Medicine</label>
            <input
              type="text"
              value={medicineSearch}
              onChange={(e) => setMedicineSearch(e.target.value)}
              placeholder="Search medicines..."
              className="mt-field mb-2"
            />
            <select
              value={medicineId}
              onChange={(e) => handleMedicineChange(e.target.value)}
              required
              className="mt-field"
            >
              <option value="">Select medicine</option>
              {filteredMedicines.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</label>
            {productsLoading ? (
              <div className="animate-pulse h-10 rounded-lg bg-gray-200" />
            ) : (
              <select
                value={medicineProductId}
                onChange={(e) => handleProductChange(e.target.value)}
                required
                disabled={!medicineId}
                className="mt-field"
              >
                <option value="">
                  {medicineId ? 'Select product' : 'Select a medicine first'}
                </option>
                {products.map((p) => (
                  <option key={p._id} value={p._id}>
                    {p.brand ?? 'Generic'} — {p.packageSize} {p.packageUnit}
                  </option>
                ))}
              </select>
            )}
            {medicineId && !productsLoading && products.length === 0 && (
              <p className="text-xs text-gray-400 mt-1">
                No products for this medicine.{' '}
                <Link href={`/medicines/${medicineId}`} className="mt-link">
                  Add a product first
                </Link>
              </p>
            )}
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className="mt-field-label">Price</label>
              <input
                type="number"
                required
                min={0.01}
                step="any"
                value={price}
                onChange={(e) => setPrice(e.target.value)}
                placeholder="9.99"
                className="mt-field"
              />
            </div>
            <div>
              <label className="mt-field-label">Currency</label>
              <input
                type="text"
                required
                maxLength={10}
                value={currency}
                onChange={(e) => setCurrency(e.target.value)}
                placeholder="USD"
                className="mt-field"
              />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className="mt-field-label">Package size</label>
              <input
                type="number"
                required
                min={1}
                step={1}
                value={quantity}
                onChange={(e) => setQuantity(e.target.value)}
                placeholder="90"
                className="mt-field"
              />
            </div>
            <div>
              <label className="mt-field-label">Unit</label>
              <select
                value={unit}
                onChange={(e) => setUnit(e.target.value as DosageUnit)}
                className="mt-field"
              >
                {Object.values(DosageUnit).map((u) => (
                  <option key={u} value={u}>
                    {u}
                  </option>
                ))}
              </select>
            </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 className="flex items-center gap-3 pt-5">
            <input
              type="checkbox"
              id="isInsurancePrice"
              checked={isInsurancePrice}
              onChange={(e) => setIsInsurancePrice(e.target.checked)}
              className="h-4 w-4 rounded border-gray-300"
            />
            <label htmlFor="isInsurancePrice" className="text-sm font-medium text-gray-700">
              Insurance price
            </label>
          </div>
        </div>

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

// --- Price history & store comparison ---

function PriceHistory({
  householdId,
  medicines,
  stores,
}: {
  householdId: string;
  medicines: MedicineOption[];
  stores: StoreOption[];
}) {
  const [selectedMedicineId, setSelectedMedicineId] = useState('');
  const [selectedStoreId, setSelectedStoreId] = useState('');
  const [records, setRecords] = useState<PriceRecord[]>([]);
  const [comparison, setComparison] = useState<StoreComparisonItem[]>([]);
  const [loading, setLoading] = useState(false);
  const [cursor, setCursor] = useState<string | null>(null);
  const [hasMore, setHasMore] = useState(false);
  const [error, setError] = useState('');

  const fetchHistory = useCallback(
    async (append = false) => {
      if (!selectedMedicineId) return;
      if (!append) setLoading(true);
      setError('');
      try {
        const [histResult, compResult] = await Promise.all([
          getPriceHistory(householdId, selectedMedicineId, {
            storeId: selectedStoreId || undefined,
            cursor: append ? (cursor ?? undefined) : undefined,
            limit: 20,
          }),
          !append ? compareStores(householdId, selectedMedicineId) : Promise.resolve(null),
        ]);
        setRecords((prev) => (append ? [...prev, ...histResult.data] : histResult.data));
        setCursor(histResult.pagination.cursor);
        setHasMore(histResult.pagination.hasMore);
        if (compResult) setComparison(compResult.data);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load price history');
      } finally {
        setLoading(false);
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [householdId, selectedMedicineId, selectedStoreId],
  );

  useEffect(() => {
    setCursor(null);
    setRecords([]);
    setComparison([]);
    if (selectedMedicineId) fetchHistory(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [householdId, selectedMedicineId, selectedStoreId]);

  return (
    <div className="mt-card">
      <h2 className="text-lg font-semibold mb-4">Price History</h2>

      <div className="mb-4 flex flex-wrap items-center gap-3">
        <select
          value={selectedMedicineId}
          onChange={(e) => setSelectedMedicineId(e.target.value)}
          className="mt-field"
          style={{ width: 'auto' }}
        >
          <option value="">Select a medicine</option>
          {medicines.map((m) => (
            <option key={m._id} value={m._id}>
              {m.name} ({m.strength} {m.strengthUnit})
            </option>
          ))}
        </select>
        {selectedMedicineId && (
          <select
            value={selectedStoreId}
            onChange={(e) => setSelectedStoreId(e.target.value)}
            className="mt-field"
            style={{ width: 'auto' }}
          >
            <option value="">All stores</option>
            {stores.map((s) => (
              <option key={s._id} value={s._id}>
                {s.name}
              </option>
            ))}
          </select>
        )}
      </div>

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

      {!selectedMedicineId ? (
        <p className="text-sm text-gray-500 py-4 text-center">
          Select a medicine to view price history.
        </p>
      ) : loading ? (
        <div className="space-y-2">
          {Array.from({ length: 3 }).map((_, i) => (
            <div key={i} className="animate-pulse h-12 rounded-lg bg-gray-200" />
          ))}
        </div>
      ) : (
        <>
          {comparison.length > 0 && (
            <div className="mb-5">
              <h3 className="text-sm font-semibold text-gray-700 mb-2">Store comparison</h3>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b text-left text-gray-500">
                      <th className="pb-2 font-medium">Store</th>
                      <th className="pb-2 font-medium text-right">Price</th>
                      <th className="pb-2 font-medium text-right">Per unit</th>
                      <th className="pb-2 font-medium text-right">Date</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-100">
                    {comparison.map((item, i) => (
                      <tr
                        key={item.storeId}
                        className={i === 0 ? 'text-green-700 font-medium' : ''}
                      >
                        <td className="py-2">
                          {item.storeName}
                          {i === 0 && <span className="ml-2 mt-pill mt-pill--ok">cheapest</span>}
                          {item.isInsurancePrice && (
                            <span className="ml-1 mt-pill mt-pill--info">insurance</span>
                          )}
                        </td>
                        <td className="py-2 text-right">
                          {formatCurrency(item.latestPrice, item.currency)}
                        </td>
                        <td className="py-2 text-right text-gray-500">
                          {formatCurrency(item.latestPricePerUnit, item.currency)}
                        </td>
                        <td className="py-2 text-right text-gray-400">{formatDate(item.date)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          )}

          {records.length === 0 ? (
            <p className="text-sm text-gray-500 py-4 text-center">No price records found.</p>
          ) : (
            <>
              <h3 className="text-sm font-semibold text-gray-700 mb-2">All records</h3>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b text-left text-gray-500">
                      <th className="pb-2 font-medium">Store</th>
                      <th className="pb-2 font-medium text-right">Price</th>
                      <th className="pb-2 font-medium text-right">Qty</th>
                      <th className="pb-2 font-medium text-right">Per unit</th>
                      <th className="pb-2 font-medium text-right">Date</th>
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-100">
                    {records.map((r) => (
                      <tr key={r._id}>
                        <td className="py-2">
                          {r.storeName}
                          {r.isInsurancePrice && (
                            <span className="ml-1 mt-pill mt-pill--info">ins</span>
                          )}
                          {r.notes && (
                            <span className="ml-1 text-xs text-gray-400"> — {r.notes}</span>
                          )}
                        </td>
                        <td className="py-2 text-right font-medium">
                          {formatCurrency(r.price, r.currency)}
                        </td>
                        <td className="py-2 text-right text-gray-500">
                          {r.quantity} {r.unit}
                        </td>
                        <td className="py-2 text-right text-gray-500">
                          {formatCurrency(r.pricePerUnit, r.currency)}
                        </td>
                        <td className="py-2 text-right text-gray-400">{formatDate(r.date)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              {hasMore && (
                <div className="mt-4 text-center">
                  <button
                    onClick={() => fetchHistory(true)}
                    className="rounded-lg border px-4 py-2 text-sm font-medium hover:bg-gray-50 transition-colors"
                  >
                    Load more
                  </button>
                </div>
              )}
            </>
          )}
        </>
      )}
    </div>
  );
}

// --- Main page ---

function MedicinePricesContent({ householdId }: { householdId: string }) {
  const [medicines, setMedicines] = useState<MedicineOption[]>([]);
  const [stores, setStores] = useState<StoreOption[]>([]);
  const [showForm, setShowForm] = useState(false);
  const [historyKey, setHistoryKey] = useState(0);

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

  return (
    <div>
      <div className="flex items-center justify-between mb-6">
        <button onClick={() => setShowForm(!showForm)} className="mt-btn mt-btn--primary">
          {showForm ? 'Cancel' : 'Record Price'}
        </button>
      </div>

      {showForm && (
        <RecordPriceForm
          householdId={householdId}
          medicines={medicines}
          stores={stores}
          onRecorded={() => {
            setShowForm(false);
            setHistoryKey((k) => k + 1);
          }}
          onCancel={() => setShowForm(false)}
        />
      )}

      <div className="space-y-6">
        <PriceHistory
          key={historyKey}
          householdId={householdId}
          medicines={medicines}
          stores={stores}
        />
      </div>
    </div>
  );
}

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

  if (sessionLoading) {
    return (
      <>
        <SetPageHeader title="Medicine Prices" subtitle="Track & compare across stores" />
        <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="Medicine Prices" subtitle="Track & compare across stores" />
        <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 tracking prices.
            </p>
          </div>
        </div>
      </>
    );
  }

  return (
    <>
      <SetPageHeader title="Medicine Prices" subtitle="Track & compare across stores" />
      <div className="mt-page">
        <MedicinePricesContent householdId={householdId} />
      </div>
    </>
  );
}
