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; using PlaylistShared.Shared.SharedPlaylist; using PlaylistShared.Shared.Yandex; namespace PlaylistShared.Api.Controllers; [ApiController] [Route("api/[controller]")] public class SharedPlaylistController : ControllerBase { private readonly SharedPlaylistService _sharedService; private readonly YandexMusicService _yandexService; private readonly UserManager _userManager; private readonly UserSessionService _userSessionService; private readonly TrackAdditionLogService _trackAdditionLogService; private readonly TrackRemovalLogService _trackRemovalLogService; public SharedPlaylistController( SharedPlaylistService sharedService, YandexMusicService yandexService, UserManager userManager, TrackAdditionLogService trackAdditionLogService, TrackRemovalLogService trackRemovalLogService, UserSessionService userSessionService) { _sharedService = sharedService; _yandexService = yandexService; _userManager = userManager; _trackAdditionLogService = trackAdditionLogService; _trackRemovalLogService = trackRemovalLogService; _userSessionService = userSessionService; } // GET /api/sharedplaylist/{token} [HttpGet("{token}")] public async Task>> GetByToken(string token) { var currentUserId = User.GetUserIdOrNull(); var entity = await _sharedService.GetEntityByTokenAsync(token); if (entity == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (!await _sharedService.CanViewAsync(entity, currentUserId)) return Unauthorized(ApiResponse.Fail(new ErrorResponse { StatusCode = 401, Message = "Недостаточно прав" })); return Ok(ApiResponse.Ok(_sharedService.MapToDto(entity))); } // GET /api/sharedplaylist/{token}/tracks [HttpGet("{token}/tracks")] public async Task>> GetTracks(string token) { var currentUserId = User.GetUserIdOrNull(); var playlist = await _sharedService.GetEntityByTokenAsync(token); if (playlist == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (!await _sharedService.CanViewAsync(playlist, currentUserId)) return Unauthorized(); var creator = await _userManager.FindByIdAsync(playlist.CreatorUserId.ToString()); if (creator == null) return StatusCode(500, ApiResponse.Fail(new ErrorResponse { StatusCode = 500, Message = "Владелец плейлиста не найден" })); var dto = await _yandexService.GetPlaylistDataAsync(creator, playlist.YandexPlaylistOwnerUid, playlist.YandexPlaylistKind); if (dto == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден в Яндекс.Музыке" })); return Ok(ApiResponse.Ok(dto)); } // PUT /api/sharedplaylist/{token}/permissions [HttpPut("{token}/permissions")] [Authorize] public async Task>> UpdatePermissions(string token, [FromBody] UpdatePermissionsDto dto) { var userId = User.GetUserId(); var playlist = await _sharedService.GetEntityByTokenAsync(token); if (playlist == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (playlist.CreatorUserId != userId) return Forbid(); var updated = await _sharedService.UpdatePermissionsAsync(playlist.Id, dto); if (updated == null) return BadRequest(ApiResponse.Fail(new ErrorResponse { StatusCode = 400, Message = "Ошибка обновления прав" })); return Ok(ApiResponse.Ok(updated)); } // POST /api/sharedplaylist/{token}/add-tracks [HttpPost("{token}/add-tracks")] public async Task>> AddTracks(string token, [FromBody] UpdateTrackListRequest request) { var currentUserId = User.GetUserIdOrNull(); var playlist = await _sharedService.GetEntityByTokenAsync(token); 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 = "Ошибка при добавлении треков" })); var session = await _userSessionService.GetOrCreateCurrentSessionAsync(currentUserId); var sessionId = session.SessionId; foreach (var trackId in request.TrackIds) { await _trackAdditionLogService.LogAdditionAsync(playlist.Id, trackId, currentUserId, sessionId); } return Ok(ApiResponse.Ok(new { message = "Треки добавлены" })); } // GET /api/sharedplaylist/{token}/additions [HttpGet("{token}/additions")] public async Task>>> GetAdditions(string token) { var currentUserId = User.GetUserIdOrNull(); var playlist = await _sharedService.GetEntityByTokenAsync(token); if (playlist == null) return NotFound(ApiResponse>.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); if (!await _sharedService.CanViewAsync(playlist, currentUserId)) return Unauthorized(); var additions = await _trackAdditionLogService.GetAdditionUserNamesAsync(playlist.Id); return Ok(ApiResponse>.Ok(additions)); } // POST /api/sharedplaylist/{token}/remove-tracks [HttpPost("{token}/remove-tracks")] public async Task>> RemoveTracks(string token, [FromBody] UpdateTrackListRequest request) { var currentUserId = User.GetUserIdOrNull(); var playlist = await _sharedService.GetEntityByTokenAsync(token); if (playlist == null) return NotFound(ApiResponse.Fail(new ErrorResponse { StatusCode = 404, Message = "Плейлист не найден" })); var session = await _userSessionService.GetOrCreateCurrentSessionAsync(currentUserId); var sessionId = session.SessionId; foreach (var trackId in request.TrackIds) { if (!await _sharedService.CanRemoveTrackAsync(playlist, currentUserId, trackId, sessionId)) 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 _trackRemovalLogService.LogRemovalAsync(playlist.Id, trackId, currentUserId, sessionId); await _trackAdditionLogService.RemoveLogsForTrackAsync(playlist.Id, trackId); } return Ok(ApiResponse.Ok(new { message = "Треки удалены" })); } }