using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudWebApi.Controllers;

/// <summary>
/// Инфо о скважине
/// </summary>
[Route("api/well")]
[ApiController]
[Authorize]
public class WellController : ControllerBase
{
    private readonly IWellService wellService;

    public WellController(IWellService wellService)
    {
        this.wellService = wellService;
    }

    /// <summary>
    /// Возвращает список доступных скважин
    /// </summary>
    /// <param name="token"> Токен отмены задачи </param>
    /// <returns>Список скважин</returns>
    [HttpGet]
    [Permission]
    [ProducesResponseType(typeof(IEnumerable<WellDto>), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> GetWellsAsync(CancellationToken token)
    {
        var idCompany = User.GetCompanyId();

        if (idCompany is null)
            return NoContent();

        var wells = await wellService.GetAsync(new() { IdCompany = idCompany },
            token).ConfigureAwait(false);

        return Ok(wells);
    }

    /// <summary>
    /// Возвращает список доступных скважин
    /// </summary>
    /// <param name="token"> Токен отмены задачи </param>
    /// <returns>Список скважин</returns>
    [HttpGet("wellTree")]
    [ProducesResponseType(typeof(IEnumerable<DepositBranchDto>), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> GetWellTreeAsync(CancellationToken token)
    {
        var idCompany = User.GetCompanyId();

        if (idCompany is null)
            return NoContent();

        var wells = await wellService.GetWellTreeAsync((int)idCompany,
            token).ConfigureAwait(false);

        return Ok(wells);
    }

    /// <summary>
    /// Возвращает информацию о требуемой скважине 
    /// </summary>
    /// <param name="idWell"> Id требуемой скважины </param>
    /// <param name="token"> Токен отмены задачи </param>
    /// <returns>Информация о требуемой скважине </returns>
    [HttpGet("{idWell}")]
    [Permission]
    [ProducesResponseType(typeof(WellMapInfoWithTelemetryStat), (int)System.Net.HttpStatusCode.OK)]
    [ProducesResponseType((int)System.Net.HttpStatusCode.NoContent)]
    public async Task<IActionResult> GetAsync(int idWell, CancellationToken token)
    {
        var idCompany = User.GetCompanyId();

        if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync(idCompany ?? default, idWell, token).ConfigureAwait(false))
            return Forbid();

        var well = await wellService.GetOrDefaultStatAsync(idWell, token);

        return Ok(well);
    }

    /// <summary>
    /// Редактирует указанные поля скважины
    /// </summary>
    /// <param name="dto"> Объект параметров скважины.
    /// IdWellType: 1 - Наклонно-направленная, 2 - Горизонтальная.
    /// State: 0 - Неизвестно, 1 - В работе, 2 - Завершена.</param>
    /// <param name="token"> Токен отмены задачи </param>
    /// <returns></returns>
    [HttpPut]
    [Permission]
    [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> UpdateWellAsync(WellDto dto,
        CancellationToken token)
    {
        var idCompany = User.GetCompanyId();

        if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
            dto.Id, token).ConfigureAwait(false))
            return Forbid();

        var result = await wellService.UpdateAsync(dto, token)
            .ConfigureAwait(false);

        return Ok(result);

    }

    /// <summary>
    /// Обновляет статус скважины
    /// </summary>
    /// <param name="idWell">ключ скважины</param>
    /// <param name="idState">статус: 0 - Неизвестно, 1 - В работе, 2 - Завершена.</param>
    /// <param name="token"></param>
    /// <returns></returns>
    [HttpPut("{idWell}/state")]
    [Permission]
    [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
    public async Task<IActionResult> UpdateWellStateAsync(int idWell,
        [Range(0, 2, ErrorMessage = "Статус некорректен")] int idState,
        CancellationToken token)
    {
        var idCompany = User.GetCompanyId();

        if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
            idWell, token).ConfigureAwait(false))
            return Forbid();

        var dto = await wellService.GetOrDefaultAsync(idWell, token);
        
        if (dto is null)
            return this.ValidationBadRequest(nameof(idWell), $"Скважина с id: {idWell} недоступна");

        dto.IdState = idState;

        var result = await wellService.UpdateAsync(dto, token)
            .ConfigureAwait(false);

        return Ok(result);

    }
}