using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.ProcessMap;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Mvc;
using System;
using Microsoft.AspNetCore.Authorization;

namespace AsbCloudWebApi.Controllers;

/// <summary>
/// Проработка скважины
/// </summary>
public class ProcessMapWellboreDevelopmentController : CrudWellRelatedController<ProcessMapWellboreDevelopmentDto, 
	IProcessMapWellboreDevelopmentRepository>
{
	private readonly IUserRepository userRepository;
	private readonly IProcessMapWellboreDevelopmentService processMapWellboreDevelopmentService;

	public ProcessMapWellboreDevelopmentController(IWellService wellService,
		IProcessMapWellboreDevelopmentRepository processMapWellboreDevelopmentRepository,
		IUserRepository userRepository,
		IProcessMapWellboreDevelopmentService processMapWellboreDevelopmentService)
		: base(wellService, processMapWellboreDevelopmentRepository)
	{
		this.userRepository = userRepository;
		this.processMapWellboreDevelopmentService = processMapWellboreDevelopmentService;
	}

	/// <summary>
	/// Добавить запись проработки
	/// </summary>
	/// <param name="value"></param>
	/// <param name="token"></param>
	/// <returns></returns>
	/// <exception cref="ForbidException"></exception>
	public override async Task<ActionResult<int>> InsertAsync(ProcessMapWellboreDevelopmentDto value, CancellationToken token)
	{
		value.IdUser = User.GetUserId() 
						?? throw new ForbidException("Неизвестный пользователь");
		
		await AssertUserHasAccessToProcessMapWellboreDevelopmentAsync(value.IdWell, value.IdUser, token);
		
		return await processMapWellboreDevelopmentService.InsertAsync(value, token);
	}

	/// <summary>
	/// Обновить запись проработки
	/// </summary>
	/// <param name="value"></param>
	/// <param name="token"></param>
	/// <returns></returns>
	public override async Task<ActionResult<int>> UpdateAsync(ProcessMapWellboreDevelopmentDto value, CancellationToken token)
	{
		value.IdUser = User.GetUserId() 
						?? throw new ForbidException("Неизвестный пользователь");
		
		await AssertUserHasAccessToProcessMapWellboreDevelopmentAsync(value.IdWell, value.IdUser, token);

		return await processMapWellboreDevelopmentService.UpdateAsync(value, token);
	}
	
	/// <summary>
	/// Возвращает проработки по uid телеметрии
	/// </summary>
	/// <param name="uid">Уникальный ключ телеметрии</param>
	/// <param name="updateFrom">Необязательный параметр. Начальная дата</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet("telemetry/{uid}")]
	[AllowAnonymous]
	[ProducesResponseType(typeof(IEnumerable<ProcessMapWellboreDevelopmentDto>), (int)System.Net.HttpStatusCode.OK)]
	public async Task<IActionResult> GetByUidAsync(string uid, DateTime updateFrom, CancellationToken cancellationToken)
	{
		var dto = await processMapWellboreDevelopmentService.GetByTelemetryAsync(uid, updateFrom, 
			cancellationToken);

		return Ok(dto);
	}

	private async Task AssertUserHasAccessToProcessMapWellboreDevelopmentAsync(int idUser, int idWell, CancellationToken cancellationToken)
	{
		var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken) 
					?? throw new ForbidException($"Скважины с {idWell} не существует");
		
		var idCompany = User.GetCompanyId();
		if (!idCompany.HasValue || !await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, idWell, cancellationToken))
			throw new ForbidException("Нет доступа к скважине");

		if (well.IdState == 2 && !userRepository.HasPermission(idUser, "ProcessMap.editCompletedWell"))
			throw new ForbidException("Недостаточно прав для редактирования РТК завершённой скважины");
	}
}