import { useAppDispatch, useAppSelector } from '@/app/hooks'
import { selectCalendars } from '@/app/selectors/selectCalendars'
import { searchEventsAsync } from '@/features/Search/SearchSlice'
import { setView } from '@/features/Settings/SettingsSlice'
import { userAttendee } from '@/features/User/models/attendee'
import { createAttendee } from '@/features/User/models/attendee.mapper'
import { extractEventBaseUuid } from '@/utils/extractEventBaseUuid'
import {
  Box,
  Button,
  Card,
  CardActions,
  CardContent,
  Divider,
  IconButton,
  InputAdornment,
  InputLabel,
  MenuItem,
  Popover,
  Select,
  Stack,
  TextField,
  Typography,
  type AutocompleteRenderInputParams
} from '@linagora/twake-mui'
import HighlightOffIcon from '@mui/icons-material/HighlightOff'
import SearchIcon from '@mui/icons-material/Search'
import TuneIcon from '@mui/icons-material/Tune'
import { useEffect, useRef, useState } from 'react'
import { useI18n } from 'twake-i18n'
import UserSearch from '../Attendees/AttendeeSearch'
import { PeopleSearch } from '../Attendees/PeopleSearch'
import { User } from '../Attendees/types'
import { CalendarItemList } from '../Calendar/CalendarItemList'

const SEARCH_OBJECT_TYPES = ['user', 'contact']

export default function SearchBar() {
  const { t } = useI18n()
  const dispatch = useAppDispatch()
  const calendars = useAppSelector(selectCalendars)
  const userId = useAppSelector(state => state.user.userData?.openpaasId)
  const personnalCalendars = userId
    ? calendars.filter(c => extractEventBaseUuid(c.id) === userId)
    : []

  const [search, setSearch] = useState('')
  const [selectedContacts, setSelectedContacts] = useState<User[]>([])
  const [extended, setExtended] = useState(false)

  const [filters, setFilters] = useState({
    searchIn: 'my-calendars',
    keywords: '',
    organizers: [] as userAttendee[],
    attendees: [] as userAttendee[]
  })

  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
  const filterOpen = Boolean(anchorEl)
  const [filterError, setFilterError] = useState(false)
  const searchWidth = {
    xs: '10vw',
    sm: '20vw',
    md: '35vw',
    xl: '35vw',
    '@media (min-width: 2000px)': {
      width: '55vw'
    }
  }

  const inputRef = useRef<HTMLInputElement | null>(null)
  const containerRef = useRef<HTMLDivElement | null>(null)
  const shouldCollapseRef = useRef(false)

  type FilterField = 'searchIn' | 'keywords' | 'organizers' | 'attendees'
  const handleFilterChange = (
    field: FilterField,
    value: string | userAttendee[]
  ) => {
    setFilters(prev => ({ ...prev, [field]: value }))
    if (field === 'organizers') {
      setSelectedContacts(
        (value as userAttendee[]).map((a: userAttendee) => ({
          displayName: a.cn ?? a.cal_address,
          email: a.cal_address || ''
        }))
      )
    }
  }

  function buildQuery(
    searchQuery: string,
    filters: {
      searchIn: string
      keywords: string
      organizers: userAttendee[]
      attendees: userAttendee[]
    }
  ) {
    const trimmedSearch = searchQuery.trim()
    const trimmedKeywords = filters.keywords.trim()

    // Block search if all search criteria are empty
    const hasSearchCriteria =
      trimmedSearch ||
      trimmedKeywords ||
      filters.organizers.length > 0 ||
      filters.attendees.length > 0

    if (!hasSearchCriteria) {
      return
    }

    let searchInCalendars: string[]

    if (filters.searchIn === '' || !filters.searchIn) {
      searchInCalendars = calendars.map(c => c.id)
    } else if (filters.searchIn === 'my-calendars') {
      searchInCalendars = personnalCalendars.map(c => c.id)
    } else {
      searchInCalendars = [filters.searchIn]
    }

    const cleanedFilters = {
      keywords: trimmedKeywords,
      organizers: filters.organizers.map(u => u.cal_address),
      attendees: filters.attendees.map(u => u.cal_address),
      searchIn: searchInCalendars
    }
    return {
      search: trimmedSearch,
      filters: cleanedFilters
    }
  }

  const handleClearFilters = () => {
    setFilters({
      searchIn: 'my-calendars',
      keywords: '',
      organizers: [] as userAttendee[],
      attendees: [] as userAttendee[]
    })
    setAnchorEl(null)
    setFilterError(false)
  }

  const handleContactSelect = (contacts: User[]) => {
    setSelectedContacts(contacts)
    setSearch('')
    if (contacts.length > 0) {
      handleSearch('', {
        ...filters,
        organizers: contacts.map(contact =>
          createAttendee({
            cal_address: contact.email,
            cn: contact.displayName
          })
        )
      })
    }
  }

  const handleSearch = async (
    searchQuery: string,
    filters: {
      searchIn: string
      keywords: string
      organizers: userAttendee[]
      attendees: userAttendee[]
    }
  ) => {
    const cleanedQuery = buildQuery(searchQuery, filters)
    if (cleanedQuery) {
      await dispatch(searchEventsAsync(cleanedQuery))
      dispatch(setView('search'))
      setAnchorEl(null)
    } else {
      if (filterOpen) {
        setFilterError(true)
      }
    }
  }

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      const target = event.target as Node

      if (filterOpen) {
        return
      }

      if (
        containerRef.current?.contains(target) ||
        inputRef.current?.contains(target) ||
        (target as HTMLElement).closest('.MuiAutocomplete-popper')
      ) {
        return
      }

      if (!search.trim() && selectedContacts.length === 0) {
        setExtended(false)
      }
    }

    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [filterOpen, search, selectedContacts])

  return (
    <>
      <Box
        ref={containerRef}
        sx={{
          margin: '0 auto',
          position: 'relative',
          width: extended ? searchWidth : 'auto',
          transition: 'width 0.25s ease-out'
        }}
      >
        {!extended && (
          <IconButton sx={{ mr: 1 }} onClick={() => setExtended(true)}>
            <SearchIcon />
          </IconButton>
        )}

        {extended && (
          <PeopleSearch
            selectedUsers={selectedContacts}
            onChange={(_event, users) => {
              handleContactSelect(users)
            }}
            objectTypes={SEARCH_OBJECT_TYPES}
            onToggleEventPreview={() => {}}
            customSlotProps={{
              popper: {
                anchorEl: containerRef.current,
                placement: 'bottom-start',
                sx: {
                  minWidth: searchWidth,
                  '& .MuiPaper-root': {
                    width: '100%'
                  }
                },
                modifiers: [
                  {
                    name: 'offset',
                    options: {
                      offset: [0, 8]
                    }
                  }
                ]
              }
            }}
            customRenderInput={(
              params: AutocompleteRenderInputParams,
              query: string,
              setQuery: (value: string) => void
            ) => (
              <TextField
                {...params}
                fullWidth
                autoFocus
                placeholder={t('common.search')}
                value={query}
                inputRef={el => {
                  inputRef.current = el
                  const ref = params.InputProps.ref
                  if (typeof ref === 'function') {
                    ref(el)
                  } else if (ref && 'current' in ref) {
                    ;(
                      ref as React.MutableRefObject<HTMLInputElement | null>
                    ).current = el
                  }
                }}
                onKeyDown={e => {
                  if (e.key === 'Enter') {
                    handleSearch(query, filters)
                  }
                }}
                onChange={e => {
                  const value = e.target.value
                  setQuery(value)
                  setSearch(value)
                }}
                variant="outlined"
                sx={{
                  borderRadius: '999px',
                  '& .MuiInputBase-input': { padding: '12px 10px' },
                  animation: 'scaleIn 0.25s ease-out',
                  '@keyframes scaleIn': {
                    from: { transform: 'scaleX(0)', opacity: 0 },
                    to: { transform: 'scaleX(1)', opacity: 1 }
                  },
                  transformOrigin: 'right',
                  '& .MuiOutlinedInput-root': {
                    borderRadius: '999px',
                    height: 40,
                    padding: '0 10px'
                  }
                }}
                InputProps={{
                  ...params.InputProps,
                  startAdornment: (
                    <>
                      <InputAdornment position="start">
                        <SearchIcon sx={{ color: '#605D62' }} />
                      </InputAdornment>
                      {params.InputProps.startAdornment}
                    </>
                  ),
                  endAdornment: (
                    <InputAdornment position="end">
                      {(query || selectedContacts.length > 0) && (
                        <IconButton
                          aria-label={t('common.clear')}
                          onClick={() => {
                            setQuery('')
                            setSearch('')
                            handleFilterChange('keywords', '')
                            setSelectedContacts([])
                          }}
                        >
                          <HighlightOffIcon />
                        </IconButton>
                      )}
                      <IconButton
                        aria-label={t('search.filter.filters')}
                        onMouseDown={e => e.preventDefault()}
                        onClick={() => {
                          setAnchorEl(containerRef.current)
                          handleFilterChange('keywords', query)
                          handleFilterChange(
                            'organizers',
                            selectedContacts.map((attendee: User) =>
                              createAttendee({
                                cal_address: attendee.email,
                                cn: attendee.displayName
                              })
                            )
                          )
                        }}
                      >
                        <TuneIcon />
                      </IconButton>
                    </InputAdornment>
                  )
                }}
              />
            )}
          />
        )}
      </Box>

      <Popover
        open={filterOpen}
        anchorEl={anchorEl}
        onClose={handleClearFilters}
        anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
        transformOrigin={{ vertical: 'top', horizontal: 'right' }}
        slotProps={{
          paper: {
            sx: { mt: 1.2, width: extended ? searchWidth : 'auto' }
          },
          transition: {
            onExited: () => {
              if (
                !search.trim() &&
                selectedContacts.length === 0 &&
                shouldCollapseRef.current
              ) {
                setExtended(false)
              }
              shouldCollapseRef.current = false
            }
          }
        }}
      >
        <Card sx={{ p: 2, pb: 1 }}>
          <CardContent>
            <Stack spacing={2}>
              <Box
                sx={{
                  display: 'grid',
                  gridTemplateColumns: '140px 1fr',
                  gap: 2,
                  alignItems: 'center'
                }}
              >
                <InputLabel id="search-in" sx={{ m: 0 }}>
                  {t('search.searchIn')}
                </InputLabel>
                <Select
                  displayEmpty
                  value={filters.searchIn}
                  onChange={e => handleFilterChange('searchIn', e.target.value)}
                  MenuProps={{
                    PaperProps: {
                      style: {
                        maxHeight: 300,
                        color: '#8C9CAF'
                      }
                    }
                  }}
                  sx={{ height: '40px' }}
                >
                  <MenuItem value="">
                    <Typography
                      sx={{
                        color: '#243B55',
                        font: 'Roboto',
                        fontSize: '16px',
                        weight: 400,
                        pointerEvents: 'auto'
                      }}
                    >
                      {t('search.filter.allCalendar')}
                    </Typography>
                  </MenuItem>
                  <Divider />
                  <MenuItem
                    value="my-calendars"
                    sx={{
                      color: '#243B55',
                      font: 'Roboto',
                      fontSize: '12px',
                      weight: 400,
                      pointerEvents: 'auto'
                    }}
                  >
                    {t('search.filter.myCalendar')}
                  </MenuItem>
                  {CalendarItemList(personnalCalendars)}
                </Select>
              </Box>

              <Box
                sx={{
                  display: 'grid',
                  gridTemplateColumns: '140px 1fr',
                  gap: 2,
                  alignItems: 'center'
                }}
              >
                <InputLabel id="keywords" sx={{ m: 0 }}>
                  {t('search.keywords')}
                </InputLabel>
                <TextField
                  fullWidth
                  error={filterError}
                  helperText={filterError ? t('search.error.emptySearch') : ''}
                  placeholder={t('search.keywordsPlaceholder')}
                  value={filters.keywords}
                  onChange={e => {
                    handleFilterChange('keywords', e.target.value)
                    if (e.target.value.trim()) {
                      setFilterError(false)
                    }
                  }}
                  size="small"
                />
              </Box>

              <Box
                sx={{
                  display: 'grid',
                  gridTemplateColumns: '140px 1fr',
                  gap: 2,
                  alignItems: 'center'
                }}
              >
                <InputLabel id="from" sx={{ m: 0 }}>
                  {t('search.organizers')}
                </InputLabel>
                <UserSearch
                  attendees={filters.organizers}
                  setAttendees={(users: userAttendee[]) => {
                    handleFilterChange('organizers', users)
                    if (users.length > 0) {
                      setFilterError(false)
                    }
                  }}
                />
              </Box>

              <Box
                sx={{
                  display: 'grid',
                  gridTemplateColumns: '140px 1fr',
                  gap: 2,
                  alignItems: 'center'
                }}
              >
                <InputLabel id="participant" sx={{ m: 0 }}>
                  {t('search.participants')}
                </InputLabel>
                <UserSearch
                  attendees={filters.attendees}
                  setAttendees={(users: userAttendee[]) => {
                    handleFilterChange('attendees', users)
                    if (users.length > 0) {
                      setFilterError(false)
                    }
                  }}
                />
              </Box>
            </Stack>
          </CardContent>

          <CardActions sx={{ justifyContent: 'flex-end', p: 2, gap: 2 }}>
            <Button
              variant="text"
              onClick={() => {
                handleClearFilters()
                setSelectedContacts([])
                setSearch('')
                shouldCollapseRef.current = true
              }}
            >
              {t('common.cancel')}
            </Button>
            <Button
              variant="contained"
              onClick={() => handleSearch(filters.keywords, filters)}
            >
              {t('common.search')}
            </Button>
          </CardActions>
        </Card>
      </Popover>
    </>
  )
}
