import { useEffect, useState } from 'react'
import ItemCard from '../../components/ItemCard/ItemCard.jsx'
import {
  inventoryApi,
  locationsApi,
  searchApi,
} from '../../api/client.js'
import { useAuth } from '../../context/AuthContext.jsx'
import {
  filterInventoryItems,
  formatAmount,
  formatDate,
  getExpiryStatus,
} from '../../utils/searchUtils.js'
import { getPaginatedResults } from '../../utils/paginationUtils.js'
import './SearchPage.css'

function ExpiryBadge({ expiryDate }) {
  const status = getExpiryStatus(expiryDate)
  const badgeClass = status.status === 'Expired'
    ? 'expiry-expired'
    : (status.status === 'Soon' || status.status === 'Today')
      ? 'expiry-soon'
      : 'expiry-fresh'

  return (
    <div className={`item-expiry-badge ${badgeClass}`}>
      {formatDate(expiryDate) || 'No expiry date'}
    </div>
  )
}

function SearchPage() {
  const { isAuthenticated } = useAuth()
  const [searchName, setSearchName] = useState('')
  const [locationId, setLocationId] = useState('')
  const [minAmount, setMinAmount] = useState('0')
  const [maxAmount, setMaxAmount] = useState('999')
  const [minExpiryDate, setMinExpiryDate] = useState('')
  const [maxExpiryDate, setMaxExpiryDate] = useState('')
  const [currentPage, setCurrentPage] = useState(1)
  const [pageSize, setPageSize] = useState(15)
  const [locations, setLocations] = useState([])
  const [matchingLocations, setMatchingLocations] = useState([])
  const [results, setResults] = useState([])
  const [loading, setLoading] = useState(false)
  const [errorMessage, setErrorMessage] = useState('')

  useEffect(() => {
    let cancelled = false

    async function loadInitialData() {
      if (!isAuthenticated) {
        setLocations([])
        setMatchingLocations([])
        setResults([])
        setErrorMessage('')
        return
      }

      setLoading(true)
      setErrorMessage('')

      try {
        const [nextLocations, nextItems] = await Promise.all([
          locationsApi.getLocations(),
          inventoryApi.getInventoryItems(),
        ])

        if (!cancelled) {
          setLocations(nextLocations)
          setMatchingLocations([])
          setResults(nextItems)
        }
      } catch (error) {
        if (!cancelled) {
          setErrorMessage(error.message)
        }
      } finally {
        if (!cancelled) {
          setLoading(false)
        }
      }
    }

    loadInitialData()

    return () => {
      cancelled = true
    }
  }, [isAuthenticated])

  async function performSearch() {
    const parsedMinAmount = minAmount === '' ? 0 : Number(minAmount)
    const parsedMaxAmount = maxAmount === '' ? Infinity : Number(maxAmount)
    const safeMinAmount = Number.isFinite(parsedMinAmount) ? parsedMinAmount : 0
    const safeMaxAmount = maxAmount === '' || !Number.isFinite(parsedMaxAmount) ? Infinity : parsedMaxAmount

    if (minExpiryDate && maxExpiryDate && minExpiryDate > maxExpiryDate) {
      alert('Start date cannot be after end date')
      return
    }

    if (safeMinAmount > safeMaxAmount) {
      alert('Minimum amount cannot be greater than maximum amount')
      return
    }

    setLoading(true)
    setErrorMessage('')

    try {
      const trimmedQuery = searchName.trim()
      const [nextItems, nextMatchingLocations] = trimmedQuery
        ? await Promise.all([
          searchApi.searchItems(trimmedQuery),
          searchApi.searchLocations(trimmedQuery),
        ])
        : await Promise.all([
          inventoryApi.getInventoryItems(),
          Promise.resolve([]),
        ])

      const filteredItems = filterInventoryItems(nextItems, {
        locationId,
        minAmount: safeMinAmount,
        maxAmount: safeMaxAmount,
        minExpiryDate,
        maxExpiryDate,
      })

      setCurrentPage(1)
      setResults(filteredItems)
      setMatchingLocations(nextMatchingLocations)
    } catch (error) {
      setErrorMessage(error.message)
    } finally {
      setLoading(false)
    }
  }

  async function resetForm() {
    setSearchName('')
    setLocationId('')
    setMinAmount('0')
    setMaxAmount('999')
    setMinExpiryDate('')
    setMaxExpiryDate('')
    setCurrentPage(1)
    setPageSize(15)
    setMatchingLocations([])
    setErrorMessage('')

    if (!isAuthenticated) {
      setResults([])
      return
    }

    setLoading(true)

    try {
      const [nextLocations, nextItems] = await Promise.all([
        locationsApi.getLocations(),
        inventoryApi.getInventoryItems(),
      ])

      setLocations(nextLocations)
      setResults(nextItems)
    } catch (error) {
      setErrorMessage(error.message)
    } finally {
      setLoading(false)
    }
  }

  const paginationData = getPaginatedResults(results, currentPage, pageSize)

  return (
    <>
      <h2>Search Inventory</h2>
      <hr />

      {!isAuthenticated ? (
        <div className="auth-required">
          Sign in on the dashboard before using the protected item and location search endpoints.
        </div>
      ) : (
        <>
          {errorMessage && <div className="status-banner status-banner--error">{errorMessage}</div>}
          {loading && <div className="status-banner status-banner--info">Searching the API...</div>}

          <div className="search-container panel">
            <div className="search-form">
              <div className="form-group">
                <label htmlFor="search-name">Item / Location / Barcode Search</label>
                <input
                  type="text"
                  id="search-name"
                  placeholder="milk, fridge, 01234567890..."
                  autoComplete="off"
                  value={searchName}
                  onChange={event => setSearchName(event.target.value)}
                  onKeyDown={event => {
                    if (event.key === 'Enter') {
                      event.preventDefault()
                      performSearch()
                    }
                  }}
                />
              </div>

              <div className="form-group">
                <label htmlFor="search-location">Storage location</label>
                <select id="search-location" value={locationId} onChange={event => setLocationId(event.target.value)}>
                  <option value="">All locations</option>
                  {locations.map(location => (
                    <option key={location.id} value={location.id}>{location.name}</option>
                  ))}
                </select>
              </div>

              <div className="form-group">
                <label>Amount range</label>
                <div className="quantity-range">
                  <div className="form-group">
                    <label htmlFor="min-amount" style={{ fontSize: '12px' }}>Min</label>
                    <input
                      type="number"
                      id="min-amount"
                      min="0"
                      step="0.1"
                      value={minAmount}
                      onChange={event => setMinAmount(event.target.value)}
                    />
                  </div>
                  <div className="form-group">
                    <label htmlFor="max-amount" style={{ fontSize: '12px' }}>Max</label>
                    <input
                      type="number"
                      id="max-amount"
                      min="0"
                      step="0.1"
                      value={maxAmount}
                      onChange={event => setMaxAmount(event.target.value)}
                    />
                  </div>
                </div>
              </div>

              <div className="form-group">
                <label>Expiry date range</label>
                <div className="date-range">
                  <div className="form-group">
                    <label htmlFor="min-expiry-date" style={{ fontSize: '12px' }}>Start date</label>
                    <input
                      type="date"
                      id="min-expiry-date"
                      value={minExpiryDate}
                      onChange={event => setMinExpiryDate(event.target.value)}
                    />
                  </div>
                  <div className="form-group">
                    <label htmlFor="max-expiry-date" style={{ fontSize: '12px' }}>End date</label>
                    <input
                      type="date"
                      id="max-expiry-date"
                      value={maxExpiryDate}
                      onChange={event => setMaxExpiryDate(event.target.value)}
                    />
                  </div>
                </div>
              </div>

              <div className="search-buttons">
                <button type="button" className="btn btn-primary" onClick={performSearch}>Search</button>
                <button type="button" className="btn btn-secondary" onClick={resetForm}>Reset</button>
              </div>
            </div>
          </div>

          {searchName.trim() && (
            <div className="location-results panel">
              <h3>Matching Locations</h3>
              {matchingLocations.length === 0 ? (
                <div className="empty-state">No locations matched that query.</div>
              ) : (
                <div className="location-results-grid">
                  {matchingLocations.map(location => (
                    <div className="location-result-card" key={location.id}>
                      <strong>{location.name}</strong>
                      <div>{location.description || 'No description provided.'}</div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          )}

          <div className="results-container panel">
            <div className="results-info">
              {results.length === 0
                ? 'No results'
                : `Found ${results.length} item${results.length !== 1 ? 's' : ''} (showing ${paginationData.startIndex}-${paginationData.endIndex})`
              }
            </div>

            <div className="pagination-controls">
              <div className="pagination-size">
                <label htmlFor="page-size-select">Items per page:</label>
                <select
                  id="page-size-select"
                  value={pageSize}
                  onChange={event => {
                    setPageSize(parseInt(event.target.value, 10))
                    setCurrentPage(1)
                  }}
                >
                  <option value="15">15</option>
                  <option value="30">30</option>
                  <option value="60">60</option>
                </select>
              </div>
              <div className="pagination-nav">
                <button
                  type="button"
                  className="btn"
                  disabled={paginationData.currentPage === 1}
                  onClick={() => setCurrentPage(page => Math.max(1, page - 1))}
                >
                  Previous
                </button>
                <div className="pagination-info">
                  Page {paginationData.currentPage} of {paginationData.totalPages}
                </div>
                <button
                  type="button"
                  className="btn"
                  disabled={paginationData.currentPage === paginationData.totalPages}
                  onClick={() => setCurrentPage(page => page + 1)}
                >
                  Next
                </button>
              </div>
            </div>

            {results.length === 0 ? (
              <div className="no-results">No items found matching your search criteria.</div>
            ) : (
              <div className="item-component-grid">
                {paginationData.items.map(item => (
                  <ItemCard
                    key={item.id}
                    imgAlt={item.name}
                    text1={item.name}
                    text2={`${item.location?.name || 'No location'} | ${formatAmount(item.amount, item.amountType)}`}
                    text3={`Barcode: ${item.barcode || 'Not set'} | Expires: ${formatDate(item.expiryDate) || 'Not set'}`}
                    editable={false}
                  >
                    <ExpiryBadge expiryDate={item.expiryDate} />
                  </ItemCard>
                ))}
              </div>
            )}
          </div>
        </>
      )}
    </>
  )
}

export default SearchPage
