import { useEffect, useMemo, useState } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { api, formatCredits } from '../api';
import { useAuth } from '../AuthContext';
import ItemTile from '../components/ItemTile';
import { onInventoryChanged } from '../inventoryEvents';
import { loadInventorySort, saveInventorySort } from '../userPrefs';

const PAGE_SIZE = 50;

export default function Dashboard() {
  const { user, loading, patchUser } = useAuth();
  const [inventory, setInventory] = useState([]);
  const [error, setError] = useState('');
  const [sort, setSort] = useState('value');
  const [page, setPage] = useState(1);
  const [selected, setSelected] = useState([]);
  const [busy, setBusy] = useState(false);
  const [maxValue, setMaxValue] = useState('10');
  const [autoSellEnabled, setAutoSellEnabled] = useState(false);
  const [settingsBusy, setSettingsBusy] = useState(false);

  useEffect(() => {
    if (!user?.id) return;
    const saved = loadInventorySort(user.id);
    if (saved) setSort(saved);
  }, [user?.id]);

  useEffect(() => {
    if (!user) return;
    setAutoSellEnabled(Boolean(user.autoSellEnabled));
    if (user.autoSellThresholdCents != null) {
      setMaxValue((user.autoSellThresholdCents / 100).toFixed(2).replace(/\.?0+$/, '') || '0');
    }
  }, [user?.id, user?.autoSellEnabled, user?.autoSellThresholdCents]);

  const load = async () => {
    const inv = await api.inventory();
    setInventory(inv.inventory);
  };

  useEffect(() => {
    if (!user || user.role === 'admin') return;
    let cancelled = false;
    (async () => {
      try {
        await load();
      } catch (err) {
        if (!cancelled) setError(err.message);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [user]);

  useEffect(() => {
    if (!user || user.role === 'admin') return undefined;
    return onInventoryChanged(() => {
      load().catch(() => {});
    });
  }, [user]);

  const sorted = useMemo(() => {
    const list = [...inventory];
    if (sort === 'value') {
      list.sort(
        (a, b) =>
          (b.valueCents ?? b.item?.valueCents ?? b.item?.marketValue) -
          (a.valueCents ?? a.item?.valueCents ?? a.item?.marketValue)
      );
    } else {
      list.sort((a, b) => new Date(b.obtainedAt) - new Date(a.obtainedAt));
    }
    return list;
  }, [inventory, sort]);

  const totalPages = Math.max(1, Math.ceil(sorted.length / PAGE_SIZE));
  const currentPage = Math.min(page, totalPages);
  const pageItems = useMemo(() => {
    const start = (currentPage - 1) * PAGE_SIZE;
    return sorted.slice(start, start + PAGE_SIZE);
  }, [sorted, currentPage]);

  useEffect(() => {
    setPage(1);
  }, [sort]);

  useEffect(() => {
    if (page > totalPages) setPage(totalPages);
  }, [page, totalPages]);

  const selectedValue = useMemo(
    () =>
      inventory
        .filter((inv) => selected.includes(inv.id))
        .reduce((sum, inv) => sum + (inv.valueCents ?? inv.item?.valueCents ?? 0), 0),
    [inventory, selected]
  );

  const thresholdCents = useMemo(() => {
    const credits = Number(maxValue);
    if (!Number.isFinite(credits) || credits < 0) return null;
    return Math.round(credits * 100);
  }, [maxValue]);

  const belowThreshold = useMemo(() => {
    if (thresholdCents == null) return [];
    return inventory.filter(
      (inv) =>
        !inv.favorite &&
        (inv.valueCents ?? inv.item?.valueCents ?? 0) < thresholdCents
    );
  }, [inventory, thresholdCents]);

  const selectedItems = useMemo(
    () => inventory.filter((inv) => selected.includes(inv.id)),
    [inventory, selected]
  );

  const selectedHasFavorite = selectedItems.some((inv) => inv.favorite);
  const selectedAllFavorite =
    selectedItems.length > 0 && selectedItems.every((inv) => inv.favorite);
  const selectedCanSell = selectedItems.some((inv) => !inv.favorite);

  const belowValue = useMemo(
    () =>
      belowThreshold.reduce(
        (sum, inv) => sum + (inv.valueCents ?? inv.item?.valueCents ?? 0),
        0
      ),
    [belowThreshold]
  );

  const toggle = (id) => {
    setSelected((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]
    );
  };

  const sellIds = async (ids) => {
    if (!ids.length) return;
    setBusy(true);
    setError('');
    try {
      const data = await api.sellInventory(ids);
      patchUser({ balance: data.user.balance });
      setSelected((prev) => prev.filter((id) => !ids.includes(id)));
      await load();
    } catch (err) {
      setError(err.message);
    } finally {
      setBusy(false);
    }
  };

  const sell = async () => {
    const ids = selectedItems.filter((inv) => !inv.favorite).map((inv) => inv.id);
    if (!ids.length) return;
    await sellIds(ids);
  };

  const setFavorite = async (favorite) => {
    if (!selected.length) return;
    setBusy(true);
    setError('');
    try {
      await api.setInventoryFavorite(selected, favorite);
      await load();
    } catch (err) {
      setError(err.message);
    } finally {
      setBusy(false);
    }
  };

  const sellBelow = async () => {
    const ids = belowThreshold.map((inv) => inv.id);
    if (!ids.length || thresholdCents == null) return;
    const favSkipped = inventory.filter(
      (inv) =>
        inv.favorite && (inv.valueCents ?? inv.item?.valueCents ?? 0) < thresholdCents
    ).length;
    const ok = window.confirm(
      `Sell ${ids.length} item${ids.length === 1 ? '' : 's'} below ${formatCredits(thresholdCents)} cr for ${formatCredits(belowValue)} cr?` +
        (favSkipped ? ` (${favSkipped} favorite item${favSkipped === 1 ? '' : 's'} excluded)` : '')
    );
    if (!ok) return;
    await sellIds(ids);
  };

  const saveAutoSell = async (enabled, thresholdCredits) => {
    setSettingsBusy(true);
    setError('');
    try {
      const data = await api.updateAutoSell({ enabled, thresholdCredits });
      patchUser(data.user);
    } catch (err) {
      setError(err.message);
    } finally {
      setSettingsBusy(false);
    }
  };

  const onAutoSellToggle = async (enabled) => {
    setAutoSellEnabled(enabled);
    const credits = Number(maxValue);
    if (!Number.isFinite(credits) || credits < 0) return;
    await saveAutoSell(enabled, credits);
  };

  const onThresholdBlur = async () => {
    const credits = Number(maxValue);
    if (!Number.isFinite(credits) || credits < 0) return;
    const savedCents = user?.autoSellThresholdCents ?? 1000;
    if (Math.round(credits * 100) === savedCents && autoSellEnabled === Boolean(user?.autoSellEnabled)) {
      return;
    }
    await saveAutoSell(autoSellEnabled, credits);
  };

  if (loading) return <p className="muted">Loading…</p>;
  if (!user) return <Navigate to="/login" replace />;
  if (user.role === 'admin') return <Navigate to="/admin" replace />;

  return (
    <div>
      <section className="section">
        <div className="section-head">
          <div>
            <h1>Inventory</h1>
            <p className="muted">Select items to sell at market value.</p>
          </div>
        </div>

        <div className="inv-toolbar">
          <div className="inv-toolbar-left">
            <div className="sort-toggle" role="group" aria-label="Sort inventory">
              <button
                type="button"
                className={sort === 'value' ? 'active' : ''}
                onClick={() => {
                  setSort('value');
                  saveInventorySort(user.id, 'value');
                }}
              >
                Highest value
              </button>
              <button
                type="button"
                className={sort === 'recent' ? 'active' : ''}
                onClick={() => {
                  setSort('recent');
                  saveInventorySort(user.id, 'recent');
                }}
              >
                Most recent
              </button>
            </div>
            {inventory.length > 0 && (
              <span className="muted inv-count">
                {inventory.length} item{inventory.length === 1 ? '' : 's'}
              </span>
            )}
          </div>
          <div className="row-actions">
            {selected.length > 0 && (
              <>
                <span className="muted">
                  {selected.length} selected · {formatCredits(selectedValue)} cr
                  {selectedHasFavorite ? ' · includes favorites' : ''}
                </span>
                <button
                  type="button"
                  className="btn ghost"
                  onClick={() => setSelected([])}
                  disabled={busy}
                >
                  Clear
                </button>
                {!selectedAllFavorite && (
                  <button
                    type="button"
                    className="btn secondary"
                    onClick={() => setFavorite(true)}
                    disabled={busy}
                  >
                    Favorite
                  </button>
                )}
                {selectedItems.some((inv) => inv.favorite) && (
                  <button
                    type="button"
                    className="btn ghost"
                    onClick={() => setFavorite(false)}
                    disabled={busy}
                  >
                    Unfavorite
                  </button>
                )}
                <button
                  type="button"
                  className="btn"
                  onClick={sell}
                  disabled={busy || !selectedCanSell}
                  title={selectedHasFavorite ? 'Favorites cannot be sold' : undefined}
                >
                  Sell
                </button>
              </>
            )}
          </div>
        </div>

        <div className="inv-bulk-sell">
          {inventory.length > 0 && (
            <>
              <button
                type="button"
                className="btn"
                disabled={busy || belowThreshold.length === 0}
                onClick={sellBelow}
              >
                Sell below
              </button>
              <label className="inv-bulk-label">
                <input
                  type="number"
                  min="0"
                  step="0.01"
                  value={maxValue}
                  disabled={busy || settingsBusy}
                  onChange={(e) => setMaxValue(e.target.value)}
                  onBlur={onThresholdBlur}
                  aria-label="Maximum market value in credits"
                />
                <span className="muted">cr</span>
              </label>
              <span className="muted inv-bulk-preview">
                {belowThreshold.length} item{belowThreshold.length === 1 ? '' : 's'} ·{' '}
                {formatCredits(belowValue)} cr
              </span>
            </>
          )}
          {inventory.length === 0 && (
            <label className="inv-bulk-label">
              Threshold
              <input
                type="number"
                min="0"
                step="0.01"
                value={maxValue}
                disabled={busy || settingsBusy}
                onChange={(e) => setMaxValue(e.target.value)}
                onBlur={onThresholdBlur}
                aria-label="Auto-sell threshold in credits"
              />
              <span className="muted">cr</span>
            </label>
          )}
          <div className="inv-auto-sell-box">
            <label className="inv-auto-sell-toggle">
              <input
                type="checkbox"
                checked={autoSellEnabled}
                disabled={busy || settingsBusy}
                onChange={(e) => onAutoSellToggle(e.target.checked)}
              />
              <span>Auto-sell</span>
            </label>
            <span className="inv-auto-sell-at muted">
              at{' '}
              {formatCredits(
                Number.isFinite(Number(maxValue)) && Number(maxValue) >= 0
                  ? Math.round(Number(maxValue) * 100)
                  : 0
              )}{' '}
              cr
            </span>
          </div>
        </div>

        {error && <div className="error">{error}</div>}
        {inventory.length === 0 ? (
          <div className="empty">
            Empty for now —{' '}
            <Link to="/cases" style={{ color: 'var(--accent)' }}>
              open a case
            </Link>
            .
          </div>
        ) : (
          <>
            <div className="grid">
              {pageItems.map((inv) => (
                <ItemTile
                  key={inv.id}
                  item={inv.item}
                  favorite={inv.favorite}
                  selected={selected.includes(inv.id)}
                  onClick={() => toggle(inv.id)}
                />
              ))}
            </div>
            {totalPages > 1 && (
              <div className="inv-pager">
                <button
                  type="button"
                  className="btn ghost"
                  disabled={currentPage <= 1}
                  onClick={() => setPage((p) => Math.max(1, p - 1))}
                >
                  Previous
                </button>
                <span className="muted">
                  Page {currentPage} / {totalPages}
                </span>
                <button
                  type="button"
                  className="btn ghost"
                  disabled={currentPage >= totalPages}
                  onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                >
                  Next
                </button>
              </div>
            )}
          </>
        )}
      </section>
    </div>
  );
}
