import { AppLayout } from '@/components/AppLayout'
import { AppPagination } from '@/components/AppPagination'
import { CreatePlaylistDialog } from '@/components/playlists/CreatePlaylistDialog'
import { PlaylistsHeader } from '@/components/playlists/PlaylistsHeader'
import {
  PlaylistsEmpty,
  PlaylistsError,
  PlaylistsLoading,
} from '@/components/playlists/PlaylistsLoadingStates'
import { PlaylistTable } from '@/components/playlists/PlaylistTable'
import {
  type Playlist,
  type PlaylistSortField,
  type SortOrder,
  playlistsService,
} from '@/lib/api/services/playlists'
import { favoritesService } from '@/lib/api/services/favorites'
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router'
import { toast } from 'sonner'

export function PlaylistsPage() {
  const navigate = useNavigate()
  const [playlists, setPlaylists] = useState<Playlist[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  // Search and sorting state
  const [searchQuery, setSearchQuery] = useState('')
  const [sortBy, setSortBy] = useState<PlaylistSortField>('name')
  const [sortOrder, setSortOrder] = useState<SortOrder>('asc')
  const [showFavoritesOnly, setShowFavoritesOnly] = useState(false)

  // Pagination state
  const [currentPage, setCurrentPage] = useState(1)
  const [totalPages, setTotalPages] = useState(1)
  const [totalCount, setTotalCount] = useState(0)
  const [pageSize, setPageSize] = useState(10)

  // Create playlist dialog state
  const [showCreateDialog, setShowCreateDialog] = useState(false)
  const [createLoading, setCreateLoading] = useState(false)
  const [newPlaylist, setNewPlaylist] = useState({
    name: '',
    description: '',
    genre: '',
  })

  // Debounce search query
  const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery)

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedSearchQuery(searchQuery)
    }, 300)

    return () => clearTimeout(handler)
  }, [searchQuery])

  const fetchPlaylists = async () => {
    try {
      setLoading(true)
      setError(null)
      const response = await playlistsService.getPlaylists({
        search: debouncedSearchQuery.trim() || undefined,
        sort_by: sortBy,
        sort_order: sortOrder,
        favorites_only: showFavoritesOnly,
        page: currentPage,
        limit: pageSize,
      })
      setPlaylists(response.playlists)
      setTotalPages(response.total_pages)
      setTotalCount(response.total)
    } catch (err) {
      const errorMessage =
        err instanceof Error ? err.message : 'Failed to fetch playlists'
      setError(errorMessage)
      toast.error(errorMessage)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    fetchPlaylists()
  }, [debouncedSearchQuery, sortBy, sortOrder, showFavoritesOnly, currentPage, pageSize])

  // Reset to page 1 when filters change
  useEffect(() => {
    if (currentPage !== 1) {
      setCurrentPage(1)
    }
  }, [debouncedSearchQuery, sortBy, sortOrder, showFavoritesOnly, pageSize])

  const handlePageChange = (page: number) => {
    setCurrentPage(page)
  }

  const handlePageSizeChange = (size: number) => {
    setPageSize(size)
    setCurrentPage(1) // Reset to first page when changing page size
  }

  const handleCreatePlaylist = async () => {
    if (!newPlaylist.name.trim()) {
      toast.error('Playlist name is required')
      return
    }

    try {
      setCreateLoading(true)
      await playlistsService.createPlaylist({
        name: newPlaylist.name.trim(),
        description: newPlaylist.description.trim() || undefined,
        genre: newPlaylist.genre.trim() || undefined,
      })

      toast.success(`Playlist "${newPlaylist.name}" created successfully`)

      // Reset form and close dialog
      setNewPlaylist({ name: '', description: '', genre: '' })
      setShowCreateDialog(false)

      // Refresh the playlists list
      fetchPlaylists()
    } catch (err) {
      const errorMessage =
        err instanceof Error ? err.message : 'Failed to create playlist'
      toast.error(errorMessage)
    } finally {
      setCreateLoading(false)
    }
  }

  const handleCancelCreate = () => {
    setNewPlaylist({ name: '', description: '', genre: '' })
    setShowCreateDialog(false)
  }

  const handleSetCurrent = async (playlist: Playlist) => {
    try {
      await playlistsService.setCurrentPlaylist(playlist.id)
      toast.success(`"${playlist.name}" is now the current playlist`)

      // Refresh the playlists list to update the current status
      fetchPlaylists()
    } catch (err) {
      const errorMessage =
        err instanceof Error ? err.message : 'Failed to set current playlist'
      toast.error(errorMessage)
    }
  }

  const handleEditPlaylist = (playlist: Playlist) => {
    navigate(`/playlists/${playlist.id}/edit`)
  }

  const handleFavoriteToggle = async (playlistId: number, shouldFavorite: boolean) => {
    try {
      if (shouldFavorite) {
        await favoritesService.addPlaylistFavorite(playlistId)
        toast.success('Added to favorites')
      } else {
        await favoritesService.removePlaylistFavorite(playlistId)
        toast.success('Removed from favorites')
      }
      
      // Update the playlist in the local state
      setPlaylists(prevPlaylists =>
        prevPlaylists.map(playlist =>
          playlist.id === playlistId
            ? {
                ...playlist,
                is_favorited: shouldFavorite,
                favorite_count: shouldFavorite 
                  ? playlist.favorite_count + 1 
                  : Math.max(0, playlist.favorite_count - 1),
              }
            : playlist,
        ),
      )
    } catch (error) {
      toast.error(
        `Failed to ${shouldFavorite ? 'add to' : 'remove from'} favorites: ${
          error instanceof Error ? error.message : 'Unknown error'
        }`,
      )
    }
  }

  const renderContent = () => {
    if (loading) {
      return <PlaylistsLoading />
    }

    if (error) {
      return <PlaylistsError error={error} onRetry={fetchPlaylists} />
    }

    if (playlists.length === 0) {
      return <PlaylistsEmpty searchQuery={searchQuery} showFavoritesOnly={showFavoritesOnly} />
    }

    return (
      <div className="space-y-4">
        <PlaylistTable
          playlists={playlists}
          onEdit={handleEditPlaylist}
          onSetCurrent={handleSetCurrent}
          onFavoriteToggle={handleFavoriteToggle}
        />
        <AppPagination
          currentPage={currentPage}
          totalPages={totalPages}
          totalCount={totalCount}
          pageSize={pageSize}
          onPageChange={handlePageChange}
          onPageSizeChange={handlePageSizeChange}
          itemName="playlists"
        />
      </div>
    )
  }

  return (
    <AppLayout
      breadcrumb={{
        items: [{ label: 'Dashboard', href: '/' }, { label: 'Playlists' }],
      }}
    >
      <div className="flex-1 rounded-xl bg-muted/50 p-4">
        <PlaylistsHeader
          searchQuery={searchQuery}
          onSearchChange={setSearchQuery}
          sortBy={sortBy}
          onSortByChange={setSortBy}
          sortOrder={sortOrder}
          onSortOrderChange={setSortOrder}
          onRefresh={fetchPlaylists}
          onCreateClick={() => setShowCreateDialog(true)}
          loading={loading}
          error={error}
          playlistCount={totalCount}
          showFavoritesOnly={showFavoritesOnly}
          onFavoritesToggle={setShowFavoritesOnly}
        />

        <CreatePlaylistDialog
          open={showCreateDialog}
          onOpenChange={setShowCreateDialog}
          loading={createLoading}
          name={newPlaylist.name}
          description={newPlaylist.description}
          genre={newPlaylist.genre}
          onNameChange={name => setNewPlaylist(prev => ({ ...prev, name }))}
          onDescriptionChange={description => setNewPlaylist(prev => ({ ...prev, description }))}
          onGenreChange={genre => setNewPlaylist(prev => ({ ...prev, genre }))}
          onSubmit={handleCreatePlaylist}
          onCancel={handleCancelCreate}
        />

        {renderContent()}
      </div>
    </AppLayout>
  )
}
