import { type FormEvent, useCallback, useEffect, useMemo, useState } from 'react';

import { catalogApi, type Product, type Warehouse } from '../api/catalogApi';
import { getApiErrorMessage } from '../api/errors';
import type { PageResponse } from '../api/types';
import { type ManualStockAdjustmentPayload, type StockBalance, warehouseApi } from '../api/warehouseApi';
import { useAuth } from '../auth/AuthContext';
import { DataTable, type TableColumn } from '../components/DataTable';
import { Layout } from '../components/Layout';
import { StockAdjustmentForm } from '../components/StockAdjustmentForm';
import { Button } from '../components/ui/Button';
import { ErrorState } from '../components/ui/ErrorState';
import { Input } from '../components/ui/Input';
import { LoadingState } from '../components/ui/LoadingState';
import { PageHeader } from '../components/ui/PageHeader';
import { Pagination } from '../components/ui/Pagination';
import { Select } from '../components/ui/Select';
import { formatDateTime, formatQuantity } from '../utils/formatters';

const PAGE_SIZE = 20;

export function StockBalancesPage() {
  const { user } = useAuth();
  const canAdjust = user?.role === 'ADMIN' || user?.role === 'WAREHOUSE';
  const [pageData, setPageData] = useState<PageResponse<StockBalance> | null>(null);
  const [warehouses, setWarehouses] = useState<Warehouse[]>([]);
  const [products, setProducts] = useState<Product[]>([]);
  const [page, setPage] = useState(0);
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch] = useState('');
  const [warehouseId, setWarehouseId] = useState('');
  const [productId, setProductId] = useState('');
  const [showAdjustmentForm, setShowAdjustmentForm] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState('');

  useEffect(() => {
    let isMounted = true;

    async function loadFilters() {
      try {
        const [warehousePage, productPage] = await Promise.all([
          catalogApi.listWarehouses({ page: 0, size: 100, active: true }),
          catalogApi.listProducts({ page: 0, size: 100, active: true }),
        ]);

        if (!isMounted) {
          return;
        }

        setWarehouses(warehousePage.items);
        setProducts(productPage.items);
      } catch (caughtError) {
        if (isMounted) {
          setError(getApiErrorMessage(caughtError, 'Не удалось загрузить фильтры'));
        }
      }
    }

    void loadFilters();

    return () => {
      isMounted = false;
    };
  }, []);

  const loadData = useCallback(async () => {
    setIsLoading(true);
    setError('');

    try {
      const data = await warehouseApi.listStockBalances({
        page,
        size: PAGE_SIZE,
        search,
        warehouseId,
        productId,
      });
      setPageData(data);
    } catch (caughtError) {
      setError(getApiErrorMessage(caughtError, 'Не удалось загрузить остатки'));
    } finally {
      setIsLoading(false);
    }
  }, [page, productId, search, warehouseId]);

  useEffect(() => {
    void loadData();
  }, [loadData]);

  const columns = useMemo<TableColumn<StockBalance>[]>(
    () => [
      { key: 'warehouse', label: 'Склад', render: (item) => `${item.warehouse.code} / ${item.warehouse.name}` },
      { key: 'sku', label: 'SKU товара', render: (item) => item.product.sku },
      { key: 'product', label: 'Товар', render: (item) => item.product.name },
      { key: 'unit', label: 'Ед. изм.', render: (item) => item.product.unit },
      { key: 'quantityOnHand', label: 'Остаток', render: (item) => formatQuantity(item.quantityOnHand) },
      { key: 'updatedAt', label: 'Обновлено', render: (item) => formatDateTime(item.updatedAt) },
    ],
    [],
  );

  const handleSearchSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setPage(0);
    setSearch(searchInput.trim());
  };

  const handleAdjustment = async (payload: ManualStockAdjustmentPayload) => {
    await warehouseApi.manualStockAdjustment(payload);
    setShowAdjustmentForm(false);
    await loadData();
  };

  return (
    <Layout title="Остатки">
      <div className="space-y-6">
        <PageHeader
          title="Остатки"
          description="Текущее количество товара по складам."
          actions={
            canAdjust ? (
              <Button type="button" onClick={() => setShowAdjustmentForm((current) => !current)}>
              Ручная корректировка
              </Button>
            ) : null
          }
        />

        <form onSubmit={handleSearchSubmit} className="grid gap-3 rounded-md border border-slate-200 bg-white p-4 shadow-sm lg:grid-cols-[1fr_220px_260px_auto]">
          <Input
            type="search"
            value={searchInput}
            onChange={(event) => setSearchInput(event.target.value)}
            placeholder="Поиск товара или склада"
            className="min-w-0"
          />
          <Select
            value={warehouseId}
            onChange={(event) => {
              setPage(0);
              setWarehouseId(event.target.value);
            }}
          >
            <option value="">Все склады</option>
            {warehouses.map((warehouse) => (
              <option key={warehouse.id} value={warehouse.id}>
                {warehouse.code} / {warehouse.name}
              </option>
            ))}
          </Select>
          <Select
            value={productId}
            onChange={(event) => {
              setPage(0);
              setProductId(event.target.value);
            }}
          >
            <option value="">Все товары</option>
            {products.map((product) => (
              <option key={product.id} value={product.id}>
                {product.sku} / {product.name}
              </option>
            ))}
          </Select>
          <Button type="submit" variant="secondary">
            Найти
          </Button>
        </form>

        {showAdjustmentForm && canAdjust && (
          <StockAdjustmentForm onSubmit={handleAdjustment} onCancel={() => setShowAdjustmentForm(false)} />
        )}

        {error && <ErrorState message={error} />}

        {isLoading ? (
          <LoadingState />
        ) : (
          <DataTable items={pageData?.items ?? []} columns={columns} getRowKey={(item) => item.id} emptyTitle="Остатки не найдены" />
        )}

        {pageData && (
          <Pagination
            page={pageData.page}
            totalPages={pageData.totalPages}
            totalElements={pageData.totalElements}
            hasPrevious={pageData.hasPrevious}
            hasNext={pageData.hasNext}
            onPrevious={() => setPage((current) => Math.max(current - 1, 0))}
            onNext={() => setPage((current) => current + 1)}
          />
        )}
      </div>
    </Layout>
  );
}
