using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using planli.backend.DTOs;
using planli.backend.planli.db;
using Microsoft.EntityFrameworkCore;
using planli.backend.Enums;
using planli.backend.planli.db.Model;

namespace planli.backend.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    [Authorize] // requires valid JWT for all endpoints in this controller
    public class ToDoController : BaseController
    {
        private readonly PlanliDbContext _db;

        public ToDoController(PlanliDbContext db)
        {
            _db = db;
        }

        // GET api/ToDo?boardId=X get ToDos from Board with ID X
        [HttpGet]
        public async Task<IActionResult> GetToDos([FromQuery] int boardId)
        {
            var currentUserId = GetCurrentUserId();

            var isMember = await _db.BoardMembers
                .AnyAsync(m => m.BoardId == boardId && m.UserId == currentUserId);
            if (!isMember) return Forbid();

            var todos = await _db.ToDos
                .Where(t => t.BoardId == boardId)
                .OrderByDescending(t => t.Priority)
                .Select(t => new ToDoResponseDto
                {
                    Id = t.Id,
                    Title = t.Title,
                    Priority = t.Priority,
                    Status = t.Status,
                    CreatedAt = t.CreatedAt
                })
                .ToListAsync();

            return Ok(todos);
        }

        // GET api/ToDo/X get ToDo with ID X
        [HttpGet("{id}")]
        public async Task<IActionResult> GetToDo(int id)
        {
            var currentUserId = GetCurrentUserId();

            var todo = await _db.ToDos.FindAsync(id);
            if (todo == null) return NotFound();

            var isMember = await _db.BoardMembers
                .AnyAsync(m => m.BoardId == todo.BoardId && m.UserId == currentUserId);
            if (!isMember) return Forbid();

            return Ok(new ToDoResponseDto {
                Id = todo.Id,
                Title = todo.Title,
                Description = todo.Description,
                Priority = todo.Priority,
                BoardId = todo.BoardId,
                Status = todo.Status,
                CreatedAt = todo.CreatedAt,
                IsRecurring = todo.IsRecurring,
                Recurrence = todo.Recurrence
            });
        }

        // POST api/todo create new ToDo
        [HttpPost]
        public async Task<IActionResult> CreateToDo(ToDoCreateDto dto)
        {
            var currentUserId = GetCurrentUserId();

            var isMember = await _db.BoardMembers
                .AnyAsync(m => m.BoardId == dto.BoardId && m.UserId == currentUserId
                           && (m.Role == BoardRole.Owner || m.Role == BoardRole.Editor));
            if (!isMember) return Forbid();

            var todo = new ToDo
            {
                Title = dto.Title,
                Description = dto.Description ?? "none",
                Priority = dto.Priority,
                BoardId = dto.BoardId,
                UserId = GetCurrentUserId(),
                Status = CurrentToDoStatus.NotStarted,
                CreatedAt = DateOnly.FromDateTime(DateTime.UtcNow),
                IsRecurring = dto.IsRecurring,
                Recurrence = dto.IsRecurring ? dto.Recurrence : null
            };

            _db.ToDos.Add(todo);
            await _db.SaveChangesAsync();

            return CreatedAtAction(nameof(GetToDo), new { id = todo.Id }, new ToDoResponseDto
            {
                Id = todo.Id,
                Title = todo.Title,
                Description = todo.Description,
                Priority = todo.Priority,
                BoardId = todo.BoardId,
                UserId = todo.UserId,
                Status = todo.Status,
                CreatedAt = todo.CreatedAt,
                IsRecurring = todo.IsRecurring,
                Recurrence = todo.Recurrence
            });
        }

        // PUT api/todos/X update ToDo with ID X
        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateToDo(int id, ToDoUpdateDto dto)
        {
            var currentUserId = GetCurrentUserId();

            var todo = await _db.ToDos.FindAsync(id);
            if (todo == null) return NotFound();

            var isMember = await _db.BoardMembers
                .AnyAsync(m => m.BoardId == todo.BoardId && m.UserId == currentUserId
                    && (m.Role == BoardRole.Owner || m.Role == BoardRole.Editor));
            if (!isMember) return Forbid();

            // only update fields that were actually sent
            if (dto.Title != null) todo.Title = dto.Title;
            if (dto.Description != null) todo.Description = dto.Description;
            if (dto.Status != null) todo.Status = dto.Status.Value;
            if (dto.Priority != null) todo.Priority = dto.Priority.Value;
            if (dto.IsRecurring != null) todo.IsRecurring = dto.IsRecurring;
            if (dto.Recurrence != null) todo.Recurrence = dto.Recurrence;

            await _db.SaveChangesAsync();
            return NoContent();
        }

        // DELETE api/todos/X delete ToDo with ID X
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteToDo(int id)
        {
            var currentUserId = GetCurrentUserId();

            var todo = await _db.ToDos.FindAsync(id);
            if (todo == null) return NotFound();

            var isMember = await _db.BoardMembers
                .AnyAsync(m => m.BoardId == todo.BoardId && m.UserId == currentUserId
                   && (m.Role == BoardRole.Owner || m.Role == BoardRole.Editor));
            if (!isMember) return Forbid();

            _db.ToDos.Remove(todo);
            await _db.SaveChangesAsync();
            return NoContent();
        }
    }
}
