// EN: Schedules Controller - Shop-wide staff schedule queries.
// VI: Controller Schedules - Truy vấn lịch làm việc nhân viên theo shop.

using BookingService.API.Application.DTOs;
using BookingService.API.Application.Queries;
using BookingService.API.Models.Responses;
using BookingService.Domain.AggregatesModel.StaffAggregate;
using BookingService.Infrastructure.Repositories;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BookingService.API.Controllers;

[ApiController]
[Route("api/v1/schedules")]
[Produces("application/json")]
[Authorize]
public class SchedulesController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IStaffScheduleRepository _scheduleRepository;
    private readonly ILogger<SchedulesController> _logger;

    public SchedulesController(IMediator mediator, IStaffScheduleRepository scheduleRepository, ILogger<SchedulesController> logger)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        _scheduleRepository = scheduleRepository ?? throw new ArgumentNullException(nameof(scheduleRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Get all staff schedules for a shop.
    /// VI: Lấy tất cả lịch làm việc nhân viên cho một shop.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(ApiResponse<List<StaffScheduleDto>>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<ApiResponse<List<StaffScheduleDto>>>> GetSchedulesByShop(
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        if (shopId == Guid.Empty)
            return BadRequest(ApiResponse<List<StaffScheduleDto>>.Fail("Shop ID is required"));

        var query = new GetSchedulesByShopQuery(shopId);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(ApiResponse<List<StaffScheduleDto>>.Ok(result));
    }

    /// <summary>
    /// EN: Create a single schedule entry.
    /// VI: Tạo một entry lịch làm việc.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(ApiResponse<StaffScheduleDto>), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<ApiResponse<StaffScheduleDto>>> CreateSchedule(
        [FromBody] CreateScheduleRequest request,
        CancellationToken cancellationToken = default)
    {
        if (request.ShopId == Guid.Empty || request.StaffId == Guid.Empty)
            return BadRequest(ApiResponse<StaffScheduleDto>.Fail("ShopId and StaffId are required"));

        if (!TimeOnly.TryParse(request.StartTime, out var startTime) ||
            !TimeOnly.TryParse(request.EndTime, out var endTime))
            return BadRequest(ApiResponse<StaffScheduleDto>.Fail("Invalid time format. Use HH:mm"));

        var schedule = new StaffSchedule(request.StaffId, request.ShopId, request.DayOfWeek, startTime, endTime);
        _scheduleRepository.Add(schedule);
        await _scheduleRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Schedule created: {Id} for staff {StaffId}", schedule.Id, request.StaffId);

        var dto = new StaffScheduleDto
        {
            Id = schedule.Id,
            StaffId = schedule.StaffId,
            ShopId = schedule.ShopId,
            DayOfWeek = schedule.DayOfWeek,
            StartTime = schedule.StartTime,
            EndTime = schedule.EndTime
        };
        return Created($"/api/v1/schedules/{schedule.Id}", ApiResponse<StaffScheduleDto>.Ok(dto));
    }

    /// <summary>
    /// EN: Delete a schedule entry by ID.
    /// VI: Xóa một entry lịch làm việc theo ID.
    /// </summary>
    [HttpDelete("{id:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteSchedule(Guid id, CancellationToken cancellationToken = default)
    {
        var schedule = await _scheduleRepository.GetByIdAsync(id, cancellationToken);
        if (schedule == null)
            return NotFound(ApiResponse<object>.Fail("Schedule not found"));

        _scheduleRepository.Remove(schedule);
        await _scheduleRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Schedule deleted: {Id}", id);
        return Ok(new { success = true, message = "Schedule deleted" });
    }
}

public record CreateScheduleRequest
{
    public Guid ShopId { get; init; }
    public Guid StaffId { get; init; }
    public int DayOfWeek { get; init; }
    public string StartTime { get; init; } = "08:00";
    public string EndTime { get; init; } = "17:00";
}
