using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using PlaylistShared.Api.Entities; using PlaylistShared.Api.Extensions; using PlaylistShared.Api.Services; using PlaylistShared.Shared.DTO; using PlaylistShared.Shared.Enums; using PlaylistShared.Shared.Models; using YandexMusic; namespace PlaylistShared.Api.Controllers; [ApiController] [Route("api/[controller]")] [Authorize] public class PlaylistController : ControllerBase { private readonly UserManager _userManager; private readonly SharedPlaylistService _sharedService; private readonly YandexMusicService _yandexService; private readonly TrackAdditionLogService _trackLogService; public PlaylistController( UserManager userManager, SharedPlaylistService sharedService, YandexMusicService yandexService, TrackAdditionLogService trackLogService) { _userManager = userManager; _sharedService = sharedService; _yandexService = yandexService; _trackLogService = trackLogService; } [HttpPost("add-tracks")] public async Task>> AddTracks([FromBody] AddTrackRequest request) { var currentUserId = User.GetUserId(); var playlist = await _sharedService.GetEntityByTokenAsync(request.SharedPlaylistToken); if (playlist == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (!await _sharedService.CanAddTrackAsync(playlist, currentUserId)) return StatusCode(403, ApiResponse.Fail(new ErrorResponse { StatusCode = 403, Message = "Недостаточно прав для добавления треков" })); var creator = await _userManager.FindByIdAsync(playlist.CreatorUserId.ToString()); if (creator == null) return StatusCode(500, ApiResponse.Fail(new ErrorResponse { StatusCode = 500, Message = "Владелец плейлиста не найден" })); var updatedPlaylist = await _yandexService.AddTracksAsync(creator, playlist.YandexPlaylistOwnerUid, playlist.YandexPlaylistKind, request.TrackIds); if (updatedPlaylist == null) return StatusCode(500, ApiResponse.Fail(new ErrorResponse { StatusCode = 500, Message = "Ошибка при добавлении треков в Яндекс.Музыку" })); // Логируем добавления для права AddedByUserOnly foreach (var trackId in request.TrackIds) await _trackLogService.LogAdditionAsync(playlist.Id, trackId, currentUserId); return Ok(ApiResponse.Ok(new { message = "Треки успешно добавлены" })); } [HttpPost("remove-tracks")] public async Task>> RemoveTracks([FromBody] AddTrackRequest request) { var currentUserId = User.GetUserId(); var playlist = await _sharedService.GetEntityByTokenAsync(request.SharedPlaylistToken); if (playlist == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); // Проверяем права на удаление каждого трека foreach (var trackId in request.TrackIds) { if (!await _sharedService.CanRemoveTrackAsync(playlist, currentUserId, trackId)) return StatusCode(403, ApiResponse.Fail(new ErrorResponse { StatusCode = 403, Message = $"Недостаточно прав для удаления трека {trackId}" })); } var creator = await _userManager.FindByIdAsync(playlist.CreatorUserId.ToString()); if (creator == null) return StatusCode(500, ApiResponse.Fail(new ErrorResponse { StatusCode = 500, Message = "Владелец плейлиста не найден" })); var updatedPlaylist = await _yandexService.RemoveTracksAsync(creator, playlist.YandexPlaylistOwnerUid, playlist.YandexPlaylistKind, request.TrackIds); if (updatedPlaylist == null) return StatusCode(500, ApiResponse.Fail(new ErrorResponse { StatusCode = 500, Message = "Ошибка при удалении треков из Яндекс.Музыки" })); // Удаляем логи добавления для этих треков foreach (var trackId in request.TrackIds) await _trackLogService.RemoveLogsForTrackAsync(playlist.Id, trackId); return Ok(ApiResponse.Ok(new { message = "Треки успешно удалены" })); } [HttpGet("info/{ownerUid}/{kind}")] public async Task>> GetPlaylistInfo(string ownerUid, string kind) { var currentUserId = User.GetUserId(); // Найти шеринг-плейлист по данным Яндекс var shared = await _sharedService.GetEntityByTokenAsync(null); // не можем по токену, надо по параметрам // Для простоты сделаем отдельный метод поиска по kind/ownerUid var playlistEntity = await _sharedService.GetByYandexIdsAsync(ownerUid, kind); if (playlistEntity == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (!await _sharedService.CanViewAsync(playlistEntity, currentUserId)) return Unauthorized(); var creator = await _userManager.FindByIdAsync(playlistEntity.CreatorUserId.ToString()); var yandexPlaylist = await _yandexService.GetPlaylistAsync(creator, ownerUid, kind); return Ok(ApiResponse.Ok(yandexPlaylist)); } [HttpGet("my")] public async Task>>> GetMyPlaylists() { var userId = User.GetUserId(); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) return Unauthorized(); var decryptedToken = _yandexService.DecryptToken(user.YandexAccessToken); if (string.IsNullOrEmpty(decryptedToken)) return BadRequest(ApiResponse.Fail(new ErrorResponse { StatusCode = 400, Message = "Токен Яндекс.Музыки не установлен или недействителен" })); var yandexClient = new YandexMusicClient(); var authSuccess = await yandexClient.Authorize(decryptedToken); if (!authSuccess) return BadRequest(ApiResponse.Fail(new ErrorResponse { StatusCode = 400, Message = "Не удалось авторизоваться в Яндекс.Музыке. Проверьте токен." })); var favorites = await yandexClient.GetFavoritesAsync(); var ownPlaylists = favorites.Where(p => p.Owner.Uid == yandexClient.Account.Uid).ToList(); var sharedPlaylists = await _sharedService.GetAllByUserAsync(userId); var result = ownPlaylists.Select(p => new YandexPlaylistInfo { Kind = p.Kind, OwnerUid = p.Owner.Uid, Title = p.Title, CoverUrl = p.Cover?.GetUrl() ?? "", TrackCount = p.TrackCount, IsShared = sharedPlaylists.Any(s => s.YandexPlaylistKind == p.Kind && s.YandexPlaylistOwnerUid == p.Owner.Uid), ShareToken = sharedPlaylists.FirstOrDefault(s => s.YandexPlaylistKind == p.Kind && s.YandexPlaylistOwnerUid == p.Owner.Uid)?.ShareToken, }).ToList(); return Ok(ApiResponse>.Ok(result)); } [HttpPost("share")] public async Task>> SharePlaylist([FromBody] SharePlaylistRequest request) { var userId = User.GetUserId(); var user = await _userManager.FindByIdAsync(userId.ToString()); if (user == null) return Unauthorized(); // Проверяем, что плейлист действительно принадлежит пользователю var yandexClient = new YandexMusicClient(); await yandexClient.Authorize(_yandexService.DecryptToken(user.YandexAccessToken)); var playlist = await yandexClient.GetPlaylistAsync(request.OwnerUid, request.Kind); if (playlist == null || playlist.Owner.Uid != yandexClient.Account.Uid) return BadRequest(ApiResponse.Fail(new ErrorResponse { StatusCode = 400, Message = "Плейлист не принадлежит вам" })); var dto = new SharePlaylistDto { YandexPlaylistKind = request.Kind, YandexPlaylistOwnerUid = request.OwnerUid, Title = playlist.Title, Description = playlist.Description, ViewPermission = ViewPermission.Everyone, AddPermission = EditPermission.AuthorizedOnly, RemovePermission = EditPermission.AddedByUserOnly }; var result = await _sharedService.CreateAsync(userId, dto); return Ok(ApiResponse.Ok(result)); } }