import { Box, Button, Flex, Heading, Spinner, Text, useBreakpointValue, IconButton, Drawer, DrawerBody, DrawerHeader, DrawerOverlay, DrawerContent, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, VStack } from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon, SettingsIcon, DownloadIcon } from "@chakra-ui/icons";
import React, { useState, useRef, useEffect, useCallback } from "react";
import { useNavigate, useLocation, Routes, Route } from "react-router-dom";
import { PaginatedSongList } from "./components/PaginatedSongList";
import { PlaylistManager } from "./components/PlaylistManager";
import { SongDetails } from "./components/SongDetails";
import { Configuration } from "./pages/Configuration";
import { PersistentMusicPlayer } from "./components/PersistentMusicPlayer";
import { BackgroundJobProgress } from "./components/BackgroundJobProgress";
import { MusicPlayerProvider, useMusicPlayer } from "./contexts/MusicPlayerContext";
import { useXmlParser } from "./hooks/useXmlParser";
import { usePaginatedSongs } from "./hooks/usePaginatedSongs";
import { formatTotalDuration } from "./utils/formatters";

import { api } from "./services/api";
import type { Song, PlaylistNode } from "./types/interfaces";
import { v4 as uuidv4 } from "uuid";
import "./App.css";



const ResizeHandle = ({ onMouseDown }: { onMouseDown: (e: React.MouseEvent) => void }) => (
  <Box
    position="absolute"
    right="-4px"
    top={0}
    bottom={0}
    width="8px"
    cursor="col-resize"
    zIndex={1}
    _hover={{
      '&::after': {
        bg: 'blue.500',
      }
    }}
    onMouseDown={onMouseDown}
  >
    <Box
      position="absolute"
      left="3px"
      top={0}
      bottom={0}
      width="2px"
      bg="gray.600"
      transition="background-color 0.2s"
      _hover={{ bg: 'blue.500' }}
    />
  </Box>
);

const findPlaylistByName = (playlists: PlaylistNode[], name: string): PlaylistNode | null => {
  for (const playlist of playlists) {
    if (playlist.name === name) return playlist;
    if (playlist.type === 'folder' && playlist.children) {
      const found = findPlaylistByName(playlist.children, name);
      if (found) return found;
    }
  }
  return null;
};

  const getAllPlaylistTracks = (node: PlaylistNode): string[] => {
    if (!node.type || node.type === 'playlist') {  // Handle both old and new playlist formats
      return node.tracks || [];
    }
    if (node.type === 'folder' && node.children) {
      return node.children.flatMap(child => getAllPlaylistTracks(child));
    }
    return [];
  };

const RekordboxReader: React.FC = () => {
  const { playlists, setPlaylists, loading: xmlLoading } = useXmlParser();
  const [selectedSong, setSelectedSong] = useState<Song | null>(null);
  const [isDatabaseInitialized, setIsDatabaseInitialized] = useState(false);
  const [isSwitchingPlaylist, setIsSwitchingPlaylist] = useState(false);
  const { currentSong, playSong, closePlayer } = useMusicPlayer();
  
  // Memoized song selection handler to prevent unnecessary re-renders
  const handleSongSelect = useCallback((song: Song) => {
    setSelectedSong(song);
  }, []);

  // Handle playing a song from the main view
  const handlePlaySong = useCallback((song: Song) => {
    // Check if song has S3 file
    if (song.s3File?.hasS3File) {
      playSong(song);
    }
  }, [playSong]);

  // Handle closing the music player
  const handleCloseMusicPlayer = useCallback(() => {
    closePlayer();
  }, [closePlayer]);
  
  // Format total duration for display
  const getFormattedTotalDuration = useCallback((durationSeconds?: number): string => {
    if (!durationSeconds) return "";
    return formatTotalDuration(durationSeconds);
  }, []);


  
  const navigate = useNavigate();
  const location = useLocation();
  const initialLoadDone = useRef(false);

  const { isOpen, onOpen, onClose } = useDisclosure();
  const { isOpen: isWelcomeOpen, onOpen: onWelcomeOpen, onClose: onWelcomeClose } = useDisclosure({ defaultIsOpen: false });
  
  const isMobile = useBreakpointValue({ base: true, md: false });
  const [sidebarWidth, setSidebarWidth] = useState(400);
  const [isResizing, setIsResizing] = useState(false);
  const resizeRef = useRef<{ startX: number; startWidth: number } | null>(null);

  // Get the current playlist from URL or default to "All Songs"
  const currentPlaylist = location.pathname.startsWith("/playlists/")
    ? decodeURIComponent(location.pathname.slice("/playlists/".length))
    : "All Songs";

  const {
    songs,
    loading: songsLoading,
    hasMore,
    totalSongs,
    totalDuration,
    loadNextPage,
    searchSongs,
    searchQuery
  } = usePaginatedSongs({ pageSize: 100, playlistName: currentPlaylist });

  // Export library to XML
  const handleExportLibrary = useCallback(async () => {
    try {
      const response = await fetch('/api/songs/export');
      if (!response.ok) {
        throw new Error('Failed to export library');
      }
      
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `rekordbox-library-${new Date().toISOString().split('T')[0]}.xml`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (error) {
      console.error('Failed to export library:', error);
    }
  }, []);

  // Check if database is initialized (has songs or playlists) - moved after useDisclosure
  useEffect(() => {
    const checkDatabaseInitialized = async () => {
      try {
        // Check if there are any songs in the database
        const songCount = await api.getSongCount();
        const hasPlaylists = playlists.length > 0;
        const isInitialized = songCount > 0 || hasPlaylists;
        setIsDatabaseInitialized(isInitialized);
        
        // Only show welcome modal if database is truly empty
        if (!isInitialized) {
          onWelcomeOpen();
        }
      } catch (error) {
        // If we can't get the song count, assume database is not initialized
        setIsDatabaseInitialized(false);
        onWelcomeOpen();
      }
    };

    if (!xmlLoading) {
      checkDatabaseInitialized();
    }
  }, [xmlLoading, playlists.length, onWelcomeOpen]);

  useEffect(() => {
    // Only run this check after the initial data load
    if (!xmlLoading && playlists.length > 0) {
      initialLoadDone.current = true;
    }

    // If we've loaded the data and the playlist doesn't exist
    if (initialLoadDone.current && 
        currentPlaylist !== "All Songs" && 
        !findPlaylistByName(playlists, currentPlaylist)) {
      navigate("/", { replace: true });
    }
  }, [currentPlaylist, playlists, navigate, xmlLoading]);

  // Reset switching state when loading starts (immediate transition)
  useEffect(() => {
    if (songsLoading && isSwitchingPlaylist) {
      setIsSwitchingPlaylist(false);
    }
  }, [songsLoading, isSwitchingPlaylist]);

  const handlePlaylistSelect = (name: string) => {
    // Set switching state immediately for visual feedback
    setIsSwitchingPlaylist(true);
    
    // Clear selected song immediately to prevent stale state
    setSelectedSong(null);
    
    // Navigate immediately without any delays
    if (name === "All Songs") {
      navigate("/", { replace: true });
    } else {
      const encodedName = encodeURIComponent(name);
      navigate(`/playlists/${encodedName}`, { replace: true });
    }
  };

  const handleCreatePlaylist = async (name: string) => {
    const newPlaylist: PlaylistNode = {
      id: uuidv4(),
      name,
      type: 'playlist',
      tracks: [],
      children: undefined
    };
    const updatedPlaylists = [...playlists, newPlaylist];
    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
    handlePlaylistSelect(name); // Navigate to the new playlist
  };

  const handleAddSongsToPlaylist = async (songIds: string[], playlistName: string) => {
    const updatedPlaylists = playlists.map(node => {
      if (node.name === playlistName && node.type === 'playlist') {
        return {
          ...node,
          tracks: [...new Set([...(node.tracks || []), ...songIds])]
        };
      }
      if (node.type === 'folder' && node.children) {
        return {
          ...node,
          children: node.children.map(child => {
            if (child.name === playlistName && child.type === 'playlist') {
              return {
                ...child,
                tracks: [...new Set([...(child.tracks || []), ...songIds])]
              };
            }
            return child;
          })
        };
      }
      return node;
    });
    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
  };

  const handleRemoveFromPlaylist = async (songIds: string[]) => {
    if (currentPlaylist === "All Songs") return;

    const updatedPlaylists = playlists.map(node => {
      if (node.name === currentPlaylist && node.type === 'playlist') {
        return {
          ...node,
          tracks: (node.tracks || []).filter(id => !songIds.includes(id))
        };
      }
      if (node.type === 'folder' && node.children) {
        return {
          ...node,
          children: node.children.map(child => {
            if (child.name === currentPlaylist && child.type === 'playlist') {
              return {
                ...child,
                tracks: (child.tracks || []).filter(id => !songIds.includes(id))
              };
            }
            return child;
          })
        };
      }
      return node;
    });
    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
  };



  const handlePlaylistDelete = async (name: string) => {
    const updatedPlaylists = playlists.filter(p => p.name !== name);
    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
    if (currentPlaylist === name) {
      navigate("/"); // Navigate back to All Songs if the current playlist is deleted
    }
  };

  const handleCreateFolder = async (name: string) => {
    const newFolder: PlaylistNode = {
      id: uuidv4(),
      name,
      type: 'folder',
      children: [],
    };
    const updatedPlaylists = [...playlists, newFolder];
    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
  };

  const handleMovePlaylist = async (playlistName: string, targetFolderName: string | null) => {
    let updatedPlaylists = [...playlists];
    let playlistToMove: PlaylistNode | null = null;

    // Helper function to remove playlist from its current location
    const removePlaylist = (nodes: PlaylistNode[]): PlaylistNode[] => {
      return nodes.reduce((acc: PlaylistNode[], node) => {
        if (node.name === playlistName) {
          playlistToMove = node;
          return acc;
        }
        if (node.type === 'folder' && node.children) {
          return [...acc, {
            ...node,
            children: removePlaylist(node.children)
          }];
        }
        return [...acc, node];
      }, []);
    };

    // First, remove the playlist from its current location
    updatedPlaylists = removePlaylist(updatedPlaylists);

    if (!playlistToMove) return; // Playlist not found

    if (targetFolderName === null) {
      // Move to root level
      updatedPlaylists.push(playlistToMove);
    } else {
      // Move to target folder
      const addToFolder = (nodes: PlaylistNode[]): PlaylistNode[] => {
        return nodes.map(node => {
          if (node.name === targetFolderName && node.type === 'folder') {
            return {
              ...node,
              children: [...(node.children || []), playlistToMove!]
            };
          }
          if (node.type === 'folder' && node.children) {
            return {
              ...node,
              children: addToFolder(node.children)
            };
          }
          return node;
        });
      };

      updatedPlaylists = addToFolder(updatedPlaylists);
    }

    const savedPlaylists = await api.savePlaylists(updatedPlaylists);
    setPlaylists(savedPlaylists);
  };

  // Note: For now, we're showing all songs with pagination
  // TODO: Implement playlist filtering with pagination

  const handleResizeStart = (e: React.MouseEvent) => {
    e.preventDefault();
    setIsResizing(true);
    resizeRef.current = {
      startX: e.pageX,
      startWidth: sidebarWidth,
    };
  };

  const handleResizeMove = (e: MouseEvent) => {
    if (!isResizing || !resizeRef.current) return;

    const delta = e.pageX - resizeRef.current.startX;
    const newWidth = Math.max(300, Math.min(800, resizeRef.current.startWidth + delta));
    setSidebarWidth(newWidth);
  };

  const handleResizeEnd = () => {
    setIsResizing(false);
    resizeRef.current = null;
  };

  useEffect(() => {
    if (isResizing) {
      window.addEventListener('mousemove', handleResizeMove);
      window.addEventListener('mouseup', handleResizeEnd);
    }
    return () => {
      window.removeEventListener('mousemove', handleResizeMove);
      window.removeEventListener('mouseup', handleResizeEnd);
    };
  }, [isResizing]);

  if (xmlLoading) {
    return (
      <Flex height="100vh" align="center" justify="center" direction="column" gap={4}>
        <Spinner size="xl" />
        <Text>Loading your library...</Text>
      </Flex>
    );
  }

  const playlistManager = (
    <PlaylistManager
      playlists={playlists}
      selectedItem={currentPlaylist}
      onPlaylistCreate={handleCreatePlaylist}
      onPlaylistSelect={(name) => {
        handlePlaylistSelect(name || "All Songs");
        if (isMobile) onClose();
      }}
      onPlaylistDelete={handlePlaylistDelete}
      onFolderCreate={handleCreateFolder}
      onPlaylistMove={handleMovePlaylist}
    />
  );

  return (
    <Box 
      position="fixed"
      top={0}
      left={0}
      right={0}
      bottom={0}
      overflow="hidden"
      margin={0}
      padding={0}
      userSelect={isResizing ? 'none' : 'auto'}
    >
      {/* Welcome Modal */}
      {!xmlLoading && !isDatabaseInitialized && (
        <Modal isOpen={isWelcomeOpen} onClose={onWelcomeClose} isCentered>
          <ModalOverlay />
          <ModalContent bg="gray.800" maxW="md">
            <ModalHeader color="white">Welcome to Rekordbox Reader</ModalHeader>
            <ModalBody>
              <VStack spacing={4} align="stretch">
                <Text color="gray.300">
                  It looks like your library is empty. To get started, you'll need to import your Rekordbox XML file.
                </Text>
                <Text color="gray.400">
                  Head over to the configuration page to learn how to export your library from Rekordbox and import it here.
                </Text>
              </VStack>
            </ModalBody>
            <ModalFooter>
              <Button 
                colorScheme="blue" 
                onClick={() => {
                  onWelcomeClose();
                  navigate('/config');
                }}
              >
                Go to Configuration
              </Button>
            </ModalFooter>
          </ModalContent>
        </Modal>
      )}

      <Flex direction="column" h="100%" w="100%">
        {/* Header */}
        <Flex 
          px={isMobile ? 2 : 4} 
          py={2}
          bg="gray.800" 
          borderBottom="1px" 
          borderColor="gray.700" 
          align="center" 
          gap={2}
          w="full"
        >
          {isMobile && (
            <IconButton
              aria-label="Open menu"
              icon={<ChevronRightIcon />}
              onClick={onOpen}
              variant="solid"
              colorScheme="blue"
              size="md"
              fontSize="20px"
            />
          )}
          <Heading 
            size={isMobile ? "sm" : "md"}
            cursor="pointer"
            onClick={() => navigate('/')}
            _hover={{ color: 'blue.300' }}
            transition="color 0.2s"
          >
            Rekordbox Reader
          </Heading>

          {/* Configuration Button */}
          <IconButton
            icon={<SettingsIcon />}
            aria-label="Configuration"
            variant="ghost"
            color="gray.300"
            _hover={{ color: "white", bg: "whiteAlpha.200" }}
            onClick={() => navigate('/config')}
            ml="auto"
            mr={2}
          />

          {/* Export Library Button */}
          <IconButton
            icon={<DownloadIcon />}
            aria-label="Export Library"
            variant="ghost"
            mr={2}
            color="gray.300"
            _hover={{ color: "white", bg: "whiteAlpha.200" }}
            onClick={handleExportLibrary}
            isDisabled={songs.length === 0}
          />
        </Flex>

        {/* Main Content */}
        <Box flex={1} overflow="hidden">
          <Routes>
            <Route path="/config" element={<Configuration />} />
            <Route
              path="*"
              element={
                <Flex flex={1} h="100%" overflow="hidden" w="full">
                  {/* Sidebar - Desktop */}
                  {!isMobile && (
                    <Box
                      position="relative"
                      w={`${sidebarWidth}px`}
                      minW={`${sidebarWidth}px`}
                      p={4}
                      borderRight="1px"
                      borderColor="gray.700"
                      overflowY="auto"
                      bg="gray.900"
                    >
                      {playlistManager}
                      <ResizeHandle onMouseDown={handleResizeStart} />
                    </Box>
                  )}

                  {/* Sidebar - Mobile */}
                  <Drawer 
                    isOpen={isOpen} 
                    placement="left" 
                    onClose={onClose}
                    size="full"
                  >
                    <DrawerOverlay />
                    <DrawerContent bg="gray.900" p={0}>
                      <DrawerHeader 
                        borderBottomWidth="1px" 
                        bg="gray.800" 
                        display="flex" 
                        alignItems="center"
                        px={2}
                        py={2}
                      >
                        <Text>Playlists</Text>
                        <IconButton
                          aria-label="Close menu"
                          icon={<ChevronLeftIcon />}
                          onClick={onClose}
                          variant="ghost"
                          ml="auto"
                          color="blue.400"
                          _hover={{ color: "blue.300", bg: "whiteAlpha.200" }}
                        />
                      </DrawerHeader>
                      <DrawerBody p={2}>
                        {playlistManager}
                      </DrawerBody>
                    </DrawerContent>
                  </Drawer>

                  {/* Main Content Area */}
                  <Flex 
                    flex={1} 
                    gap={4} 
                    p={isMobile ? 2 : 4} 
                    h="100%"
                    overflow="hidden" 
                  >
                    {/* Song List */}
                    <Box flex={1} overflowY="auto" minH={0}>
                      <PaginatedSongList
                        songs={songs}
                        onAddToPlaylist={handleAddSongsToPlaylist}
                        onRemoveFromPlaylist={handleRemoveFromPlaylist}
                        playlists={playlists}
                        onSongSelect={handleSongSelect}
                        selectedSongId={selectedSong?.id || null}
                        currentPlaylist={currentPlaylist}
                        loading={songsLoading}
                        hasMore={hasMore}
                        totalSongs={totalSongs}
                        totalPlaylistDuration={getFormattedTotalDuration(totalDuration)}
                        onLoadMore={loadNextPage}
                        onSearch={searchSongs}
                        searchQuery={searchQuery}
                        isSwitchingPlaylist={isSwitchingPlaylist}
                        onPlaySong={handlePlaySong}
                      />
                    </Box>

                    {/* Details Panel */}
                    {!isMobile && (
                      <Box
                        w="350px"
                        minW="350px"
                        pl={4}
                        pr={4}
                        pb={4}
                        borderLeft="1px"
                        borderColor="gray.700"
                        overflowY="auto"
                        bg="gray.900"
                        minH={0}
                        sx={{
                          '&::-webkit-scrollbar': {
                            width: '8px',
                            borderRadius: '8px',
                            backgroundColor: 'gray.900',
                          },
                          '&::-webkit-scrollbar-thumb': {
                            backgroundColor: 'gray.700',
                            borderRadius: '8px',
                          },
                        }}
                      >
                        <SongDetails song={selectedSong} />
                      </Box>
                    )}
                  </Flex>
                </Flex>
              }
            />
          </Routes>
        </Box>
      </Flex>

      {/* Persistent Music Player */}
      <PersistentMusicPlayer
        currentSong={currentSong}
        onClose={handleCloseMusicPlayer}
      />

      {/* Background Job Progress */}
      <BackgroundJobProgress />
    </Box>
  );
};

const RekordboxReaderApp: React.FC = () => {
  return (
    <MusicPlayerProvider>
      <RekordboxReader />
    </MusicPlayerProvider>
  );
};

export default RekordboxReaderApp;
