package com.vibevault.service.impl;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.vibevault.dto.PlaylistDTO;
import com.vibevault.dto.SongCreateDTO;
import com.vibevault.dto.SongDTO;
import com.vibevault.exception.ResourceNotFoundException;
import com.vibevault.exception.UnauthorizedAccessException;
import com.vibevault.model.Playlist;
import com.vibevault.model.Song;
import com.vibevault.model.User;
import com.vibevault.repository.PlaylistRepository;
import com.vibevault.repository.SongRepository;
import com.vibevault.repository.UserRepository;
import com.vibevault.service.PlaylistService;

@Service
public class PlaylistServiceImpl implements PlaylistService {

    private final PlaylistRepository playlistRepository;
    private final UserRepository userRepository;
    private final SongRepository songRepository;

    @Autowired
    public PlaylistServiceImpl(PlaylistRepository playlistRepository, UserRepository userRepository, SongRepository songRepository) {
        this.playlistRepository = playlistRepository;
        this.userRepository = userRepository;
        this.songRepository = songRepository;
    }

    @Override
    public List<PlaylistDTO> getAllPlaylists() {
        return playlistRepository.findAll().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public PlaylistDTO getPlaylistById(Long id) {
        Playlist playlist = playlistRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + id));
        return convertToDTO(playlist);
    }

    @Override
    @Transactional
    public PlaylistDTO createPlaylist(String name, String ownerUsername) {
        User owner = userRepository.findByUsername(ownerUsername)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + ownerUsername));

        Playlist playlist = new Playlist();
        playlist.setName(name);
        playlist.setOwner(owner);

        Playlist savedPlaylist = playlistRepository.save(playlist);
        return convertToDTO(savedPlaylist);
    }

    @Override
    @Transactional
    public PlaylistDTO addSongToPlaylist(Long playlistId, SongCreateDTO songDTO, String username) {
        Playlist playlist = getPlaylistWithOwnershipCheck(playlistId, username);

        Song song = new Song();
        song.setTitle(songDTO.title());
        song.setArtist(songDTO.artist());
        song.setDurationInSeconds(songDTO.durationInSeconds());

        playlist.addSong(song);
        Playlist savedPlaylist = playlistRepository.save(playlist);
        return convertToDTO(savedPlaylist);
    }

    @Override
    @Transactional
    public void removeSongFromPlaylist(Long playlistId, Long songId, String username) {
        Playlist playlist = getPlaylistWithOwnershipCheck(playlistId, username);

        Song song = playlist.getSongs().stream()
                .filter(s -> s.getId().equals(songId))
                .findFirst()
                .orElseThrow(() -> new ResourceNotFoundException("Song not found in playlist with id: " + songId));

        playlist.removeSong(song);
        playlistRepository.save(playlist);
    }

    @Override
    @Transactional
    public PlaylistDTO addSongsToPlaylist(Long playlistId, List<SongCreateDTO> songDTOs, String username) {
        Playlist playlist = getPlaylistWithOwnershipCheck(playlistId, username);

        for (SongCreateDTO songDTO : songDTOs) {
            Song song = new Song();
            song.setTitle(songDTO.title());
            song.setArtist(songDTO.artist());
            song.setDurationInSeconds(songDTO.durationInSeconds());
            playlist.addSong(song);
        }

        Playlist savedPlaylist = playlistRepository.save(playlist);
        return convertToDTO(savedPlaylist);
    }

    @Override
    @Transactional
    public void deletePlaylist(Long playlistId, String username) {
        Playlist playlist = getPlaylistWithOwnershipCheck(playlistId, username);
        playlistRepository.delete(playlist);
    }

    // ========== Advanced 方法（选做）==========

    @Override
    public List<PlaylistDTO> searchPlaylists(String keyword) {
        return playlistRepository.findByNameContainingIgnoreCase(keyword).stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public PlaylistDTO copyPlaylist(Long playlistId, String newName, String username) {
        // 验证原歌单存在且用户有权限访问
        Playlist originalPlaylist = getPlaylistWithOwnershipCheck(playlistId, username);
        
        // 获取当前用户
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + username));
        
        // 创建新歌单
        Playlist newPlaylist = new Playlist();
        newPlaylist.setName(newName);
        newPlaylist.setOwner(user);
        
        // 保存新歌单
        Playlist savedPlaylist = playlistRepository.save(newPlaylist);
        
        // 复制原歌单的所有歌曲
        List<Song> originalSongs = songRepository.findByPlaylistId(originalPlaylist.getId());
        for (Song originalSong : originalSongs) {
            Song newSong = new Song();
            newSong.setTitle(originalSong.getTitle());
            newSong.setArtist(originalSong.getArtist());
            newSong.setDurationInSeconds(originalSong.getDurationInSeconds());
            newSong.setPlaylist(savedPlaylist);
            songRepository.save(newSong);
        }
        
        // 重新加载新歌单以包含所有歌曲
        Playlist updatedPlaylist = playlistRepository.findById(savedPlaylist.getId())
                .orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + savedPlaylist.getId()));
        
        return convertToDTO(updatedPlaylist);
    }
    
    @Override
    public List<PlaylistDTO> filterPlaylists(String username, String ownerName, String nameKeyword, String sortBy, String sortDirection) {
        List<Playlist> playlists;
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + username));
        
        // 如果提供了ownerName，则筛选特定用户的歌单
        if (ownerName != null) {
            User owner = userRepository.findByUsername(ownerName)
                    .orElseThrow(() -> new ResourceNotFoundException("User not found with username: " + ownerName));
            
            // 根据是否提供关键词和排序条件选择不同的查询方法
            if (nameKeyword != null) {
                if (sortBy != null && sortBy.equals("createdAt")) {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称关键词筛选并按创建时间降序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByCreatedAtDesc(owner, nameKeyword);
                    } else {
                        // 按名称关键词筛选并按创建时间升序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByCreatedAtAsc(owner, nameKeyword);
                    }
                } else {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称关键词筛选并按名称降序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByNameDesc(owner, nameKeyword);
                    } else {
                        // 按名称关键词筛选并按名称升序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByNameAsc(owner, nameKeyword);
                    }
                }
            } else {
                if (sortBy != null && sortBy.equals("createdAt")) {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按创建时间降序排序
                        playlists = playlistRepository.findByOwnerOrderByCreatedAtDesc(owner);
                    } else {
                        // 按创建时间升序排序
                        playlists = playlistRepository.findByOwnerOrderByCreatedAtAsc(owner);
                    }
                } else {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称降序排序
                        playlists = playlistRepository.findByOwnerOrderByNameDesc(owner);
                    } else {
                        // 按名称升序排序
                        playlists = playlistRepository.findByOwnerOrderByNameAsc(owner);
                    }
                }
            }
        } else {
            // 未提供ownerName，则筛选当前用户的歌单
            if (nameKeyword != null) {
                if (sortBy != null && sortBy.equals("createdAt")) {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称关键词筛选并按创建时间降序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByCreatedAtDesc(user, nameKeyword);
                    } else {
                        // 按名称关键词筛选并按创建时间升序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByCreatedAtAsc(user, nameKeyword);
                    }
                } else {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称关键词筛选并按名称降序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByNameDesc(user, nameKeyword);
                    } else {
                        // 按名称关键词筛选并按名称升序排序
                        playlists = playlistRepository.findByOwnerAndNameContainingIgnoreCaseOrderByNameAsc(user, nameKeyword);
                    }
                }
            } else {
                if (sortBy != null && sortBy.equals("createdAt")) {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按创建时间降序排序
                        playlists = playlistRepository.findByOwnerOrderByCreatedAtDesc(user);
                    } else {
                        // 按创建时间升序排序
                        playlists = playlistRepository.findByOwnerOrderByCreatedAtAsc(user);
                    }
                } else {
                    if (sortDirection != null && sortDirection.equals("desc")) {
                        // 按名称降序排序
                        playlists = playlistRepository.findByOwnerOrderByNameDesc(user);
                    } else {
                        // 按名称升序排序
                        playlists = playlistRepository.findByOwnerOrderByNameAsc(user);
                    }
                }
            }
        }
        
        // 转换为DTO并返回
        return playlists.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    // 辅助方法：检查歌单所有权
    private Playlist getPlaylistWithOwnershipCheck(Long playlistId, String username) {
        Playlist playlist = playlistRepository.findById(playlistId)
                .orElseThrow(() -> new ResourceNotFoundException("Playlist not found with id: " + playlistId));

        // 检查是否为歌单所有者
        if (!playlist.getOwner().getUsername().equals(username)) {
            throw new UnauthorizedAccessException("You don't have permission to modify this playlist");
        }

        return playlist;
    }

    // 辅助方法：将 Playlist 转换为 PlaylistDTO
    private PlaylistDTO convertToDTO(Playlist playlist) {
        List<SongDTO> songDTOs = playlist.getSongs().stream()
                .map(this::convertSongToDTO)
                .collect(Collectors.toList());
        
        return new PlaylistDTO(
            playlist.getId(),
            playlist.getName(),
            playlist.getOwner().getUsername(),
            songDTOs
        );
    }
    
    // 辅助方法：将 Song 转换为 SongDTO
    private SongDTO convertSongToDTO(Song song) {
        return new SongDTO(
            song.getId(),
            song.getTitle(),
            song.getArtist(),
            song.getDurationInSeconds()
        );
    }
}
