using adas_core.Application.Exceptions;
using adas_core.Application.Services.Interfaces;
using adas_core.Authentication.Attributes;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson;

namespace adas_core.Controllers;
/// <summary>
/// Retrieves API endPoints for managing Camera Service
/// </summary>
[ApiController]
public class CameraController(ICameraService cameraService) : ControllerBase
{
    /// <summary>
    /// Retrieves a paginated list of cameras based on the provided pagination filter.
    /// Validates that the request is not null before delegating to the camera service.
    /// </summary>
    /// <param name="request">The pagination filter containing paging criteria.</param>
    /// <param name="withPoCs">Indicates whether the result should include PoCs (Points of Contact).</param>
    /// <returns>An <see cref="IActionResult"/> containing the paginated cameras returned by the service.</returns>
    /// <exception cref="BadRequestException">Thrown when the <paramref name="request"/> parameter is null.</exception>
    [HttpPost("paginated")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> GetPaginatedCamera([FromBody] PaginationFilter request, bool withPoCs)
    {
        if (request == null) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestMissingParameters);
        var cameras = await cameraService.GetPaginatedCameras(request);
        return Ok(cameras);
    }
    /// <summary>
    /// Searches for cameras whose names match the specified search text and returns the matching results.
    /// </summary>
    /// <param name="textToSearch">The text used to search for cameras by name.</param>
    /// <returns>An <see cref="IActionResult"/> containing the list of cameras that match the search criteria.</returns>
    [HttpGet("{textToSearch}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> GetSearchByName(string textToSearch)
    {
        var cameras = await cameraService.GetSearchByNameCameras(textToSearch);
        return Ok(cameras);
    }
    /// <summary>
    /// Creates a new camera by inserting the provided camera data into the system.
    /// Requires the caller to have the <c>AuthSome</c> permission role.
    /// </summary>
    /// <param name="camera">The camera entity to be created, provided in the request body.</param>
    /// <returns>An <see cref="IActionResult"/> containing the newly inserted camera wrapped in an HTTP 200 OK response.</returns>
    [HttpPost]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> CreateCamera([FromBody] Camera camera)
    {
        var cam = await cameraService.InsertCamera(camera);
        return Ok(cam);
    }
    /// <summary>
    /// Updates an existing camera identified by the provided id with the supplied camera data.
    /// Throws a <see cref="BadRequestException"/> when the id cannot be parsed as a valid ObjectId.
    /// </summary>
    /// <param name="id">The identifier of the camera to update, provided in the route.</param>
    /// <param name="camera">The camera payload containing the updated information.</param>
    /// <returns>An <see cref="IActionResult"/> containing the updated camera when the operation succeeds.</returns>
    /// <exception cref="BadRequestException">Thrown when the provided id is not a valid ObjectId.</exception>
    [HttpPut("{id}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> UpdateCamera(string id, [FromBody] Camera camera)
    {
        if (!ObjectId.TryParse(id, out var idParsed)) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestMissingParameters);
        var cameraUpdated = await cameraService.UpdateCameraById(idParsed, camera);
        return Ok(cameraUpdated);
    }
    /// <summary>
    /// Deletes a camera identified by the provided id after validating that the id is a well-formed ObjectId.
    /// </summary>
    /// <param name="id">The string representation of the camera's ObjectId to be deleted.</param>
    /// <returns>An <see cref="IActionResult"/> containing the result of the delete operation when the id is valid.</returns>
    /// <exception cref="BadRequestException">Thrown when the provided <paramref name="id"/> cannot be parsed as a valid ObjectId.</exception>
    [HttpDelete("{id}")]
    [AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
    public async Task<IActionResult> DeleteCamera(string id)
    {
        if (!ObjectId.TryParse(id, out var idParsed)) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestMissingParameters);
        var cameraUpdated = await cameraService.DeleteCamera(idParsed);
        return Ok(cameraUpdated);
    }
}