import {Stack} from 'expo-router'
import {useState} from 'react'
import {ActivityIndicator, View} from 'react-native'

import {Chip} from '@/components/chip'
import {CrumbList} from '@/components/crumb-list'
import {ErrorState} from '@/components/error-state'
import {TrailList} from '@/components/trail-list'
import {Card, CardLabel} from '@/components/ui/card'
import {Carousel} from '@/components/ui/carousel'
import {Layout} from '@/components/ui/layout'
import {UserList} from '@/components/user-list'
import {
  useSearchResults,
  type SearchScope,
} from '@/hooks/use-search-results'
import {atoms as a, tokens} from '@/sprinkles'

const SCOPES: {label: string; value: SearchScope}[] = [
  {label: 'All', value: 'all'},
  {label: 'Crumbs', value: 'crumbs'},
  {label: 'Trails', value: 'trails'},
  {label: 'People', value: 'people'},
]

export default function SearchScreen() {
  const [query, setQuery] = useState('')
  const [scope, setScope] = useState<SearchScope>('all')
  const [activeTag, setActiveTag] = useState<string | null>(null)
  const results = useSearchResults(query, scope, activeTag)
  const {search, tags, hasQuery, showResults, effectiveScope, error} =
    results

  // a tag narrows to crumbs, so a non-crumb scope clears it
  const selectScope = (value: SearchScope) => {
    if (value !== 'crumbs') setActiveTag(null)
    setScope(value)
  }

  // each section renders a different list, so only the labelled-card frame
  // is shared; gated by the active scope
  const sections = [
    {
      scope: 'people' as const,
      label: 'People',
      node: (
        <UserList
          users={results.users}
          loading={results.usersLoading}
          showStatus={showResults}
          emptyMessage={
            hasQuery ? 'No matching people' : 'No friends yet'
          }
        />
      ),
    },
    {
      scope: 'crumbs' as const,
      label: 'Crumbs',
      node: (
        <CrumbList
          crumbs={results.crumbs}
          loading={results.crumbsLoading}
          emptyMessage={
            hasQuery || activeTag
              ? 'No matching crumbs'
              : 'No crumbs yet'
          }
        />
      ),
    },
    {
      scope: 'trails' as const,
      label: 'Trails',
      node: (
        <TrailList
          trails={results.trails}
          loading={results.trailsLoading}
          emptyMessage={
            hasQuery ? 'No matching trails' : 'No trails yet'
          }
        />
      ),
    },
  ]

  return (
    <>
      <Layout.LargeTitle>Search</Layout.LargeTitle>
      <Stack.Screen
        options={{
          headerSearchBarOptions: {
            placeholder: 'Search',
            onChangeText: ({nativeEvent}) => {
              setQuery(nativeEvent.text)
              search(nativeEvent.text)
            },
          },
        }}
      />
      <Layout.Content>
        <View
          style={[
            a.flex_row,
            a.justify_between,
            a.align_center,
            a.gap_md,
            {
              marginTop: -tokens.space.lg,
              paddingBottom: tokens.space._2xl,
            },
          ]}
        >
          <Layout.Description
            style={[a.flex_1, {marginTop: 0, paddingBottom: 0}]}
          >
            Discover new crumbs and trails
          </Layout.Description>
          <ActivityIndicator
            animating={results.searching}
            hidesWhenStopped={false}
            style={{opacity: results.searching ? 1 : 0}}
          />
        </View>

        <View style={[a.gap_sm, {paddingBottom: tokens.space._2xl}]}>
          <Carousel snap={false} gutter={tokens.space._2xl}>
            {SCOPES.map(({label, value}) => (
              <Chip
                key={value}
                label={label}
                selected={effectiveScope === value}
                onPress={() => selectScope(value)}
              />
            ))}
          </Carousel>
          {tags.length > 0 && (
            <Carousel snap={false} gutter={tokens.space._2xl}>
              {tags.map((tag) => (
                <Chip
                  key={tag.name}
                  label={`${tag.emoji} ${tag.name}`}
                  selected={activeTag === tag.name}
                  onPress={() =>
                    setActiveTag(
                      activeTag === tag.name ? null : tag.name,
                    )
                  }
                />
              ))}
            </Carousel>
          )}
        </View>

        {error ? (
          <ErrorState message={error} onRetry={() => search(query)} />
        ) : (
          <Layout.Column>
            {sections
              .filter(
                (s) =>
                  effectiveScope === 'all' ||
                  effectiveScope === s.scope,
              )
              .map((s) => (
                <View key={s.scope} style={a.gap_xs}>
                  <CardLabel>{s.label}</CardLabel>
                  <Card>{s.node}</Card>
                </View>
              ))}
          </Layout.Column>
        )}
      </Layout.Content>
    </>
  )
}
