package com.vibevault.service;

import com.vibevault.dto.PlaylistDTO;
import com.vibevault.dto.SongCreateDTO;
import com.vibevault.dto.SongDTO;
import com.vibevault.exception.ResourceNotFoundException;
import com.vibevault.exception.UnauthorizedException;
import com.vibevault.model.Playlist;
import com.vibevault.model.Song;
import com.vibevault.model.User;
import com.vibevault.repository.PlaylistRepository;
import com.vibevault.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 歌单服务实现
 * 
 * 需要实现：
 * - 所有 PlaylistService 接口中定义的方法
 * - 将实体转换为 DTO 返回给调用者
 * - 资源不存在时抛出 ResourceNotFoundException
 * - [Challenge] 检查用户是否有权限操作歌单（所有权检查）
 */
@Service
public class PlaylistServiceImpl implements PlaylistService {

    private final PlaylistRepository playlistRepository;
    private final UserRepository userRepository;

    public PlaylistServiceImpl(PlaylistRepository playlistRepository, UserRepository userRepository) {
        this.playlistRepository = playlistRepository;
        this.userRepository = userRepository;
    }

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

    @Override
    public PlaylistDTO getPlaylistById(Long id) {
        Playlist playlist = playlistRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("歌单不存在，ID: " + id));
        return toDTO(playlist);
    }

    @Override
    @Transactional
    public PlaylistDTO createPlaylist(String name, String ownerUsername) {
        // 查找所有者用户
        User owner = userRepository.findByUsername(ownerUsername)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在，用户名: " + ownerUsername));
        
        // 创建新歌单
        Playlist playlist = new Playlist(name, owner);
        
        // 保存歌单并返回DTO
        return toDTO(playlistRepository.save(playlist));
    }

    @Override
    @Transactional
    public PlaylistDTO addSongToPlaylist(Long playlistId, SongCreateDTO song, String username) {
        // 查找歌单
        Playlist playlist = playlistRepository.findById(playlistId)
                .orElseThrow(() -> new ResourceNotFoundException("歌单不存在，ID: " + playlistId));
        
        // 检查权限
        checkPermission(playlist, username);
        
        // 创建新歌曲
        Song newSong = new Song(song.title(), song.artist(), song.durationInSeconds());
        
        // 添加歌曲到歌单
        playlist.addSong(newSong);
        
        // 保存歌单并返回DTO
        return toDTO(playlistRepository.save(playlist));
    }

    @Override
    @Transactional
    public void removeSongFromPlaylist(Long playlistId, Long songId, String username) {
        // 查找歌单
        Playlist playlist = playlistRepository.findById(playlistId)
                .orElseThrow(() -> new ResourceNotFoundException("歌单不存在，ID: " + playlistId));
        
        // 检查权限
        checkPermission(playlist, username);
        
        // 查找歌曲
        Song song = playlist.getSongs().stream()
                .filter(s -> s.getId().equals(songId))
                .findFirst()
                .orElseThrow(() -> new ResourceNotFoundException("歌曲不存在，ID: " + songId));
        
        // 从歌单移除歌曲
        playlist.removeSong(song);
        
        // 保存歌单
        playlistRepository.save(playlist);
    }

    @Override
    @Transactional
    public void deletePlaylist(Long playlistId, String username) {
        // 查找歌单
        Playlist playlist = playlistRepository.findById(playlistId)
                .orElseThrow(() -> new ResourceNotFoundException("歌单不存在，ID: " + playlistId));
        
        // 检查权限
        checkPermission(playlist, username);
        
        // 删除歌单
        playlistRepository.delete(playlist);
    }

    // ========== Advanced 方法 ==========

    @Override
    @Transactional
    public List<PlaylistDTO> searchPlaylists(String keyword) {
        // 根据关键字搜索所有歌单
        List<Playlist> playlists = playlistRepository.findByNameContaining(keyword);
        
        return playlists.stream()
                .map(this::toDTO)
                .toList();
    }

    @Override
    @Transactional
    public PlaylistDTO copyPlaylist(Long sourcePlaylistId, String newName, String username) {
        // 1. 查找源歌单
        Playlist sourcePlaylist = playlistRepository.findById(sourcePlaylistId)
                .orElseThrow(() -> new ResourceNotFoundException("源歌单不存在，ID: " + sourcePlaylistId));
        
        // 2. 获取当前用户
        User currentUser = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("用户不存在，用户名: " + username));
        
        // 3. 创建新的歌单
        Playlist newPlaylist = new Playlist(newName, currentUser);
        
        // 4. 复制所有歌曲
        for (Song sourceSong : sourcePlaylist.getSongs()) {
            Song newSong = new Song(sourceSong.getTitle(), sourceSong.getArtist(), sourceSong.getDurationInSeconds());
            newPlaylist.addSong(newSong);
        }
        
        // 5. 保存并返回新的歌单
        return toDTO(playlistRepository.save(newPlaylist));
    }

    // ========== 辅助方法 ==========

    /**
     * 将 Playlist 实体转换为 DTO
     */
    private PlaylistDTO toDTO(Playlist playlist) {
        List<SongDTO> songDTOs = playlist.getSongs().stream()
                .map(this::toSongDTO)
                .toList();
        return new PlaylistDTO(
                playlist.getId(),
                playlist.getName(),
                playlist.getOwner().getUsername(),
                songDTOs
        );
    }

    /**
     * 将 Song 实体转换为 DTO
     */
    private SongDTO toSongDTO(Song song) {
        return new SongDTO(
                song.getId(),
                song.getTitle(),
                song.getArtist(),
                song.getDurationInSeconds()
        );
    }

    /**
     * [Challenge] 检查用户是否有权限操作指定歌单
     * 规则：歌单所有者或管理员可以操作
     */
    private void checkPermission(Playlist playlist, String username) {
        // 如果是管理员角色，直接允许操作
        if (playlist.getOwner().getRole().equals("ROLE_ADMIN")) {
            return;
        }
        // 否则检查是否是歌单所有者
        if (!playlist.getOwner().getUsername().equals(username)) {
            throw new UnauthorizedException("无权限操作此歌单");
        }
    }
}
