using System;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.AutogeneratedDailyReport;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.AutoGeneratedDailyReports;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace AsbCloudWebApi.Controllers;

/// <summary>
/// Контроллер для авто-генерируемых суточных отчётов
/// </summary>
[ApiController]
[Route("api/well/{idWell}/[controller]")]
[Authorize]
public class AutoGeneratedDailyReportController : ControllerBase
{
	private readonly IAutoGeneratedDailyReportService autoGeneratedDailyReportService;
	private readonly IWellService wellService;

	public AutoGeneratedDailyReportController(IAutoGeneratedDailyReportService autoGeneratedDailyReportService,
		IWellService wellService)
	{
		this.autoGeneratedDailyReportService = autoGeneratedDailyReportService;
		this.wellService = wellService;
	}
	
	/// <summary>
	/// Формирование отчёта
	/// </summary>
	/// <param name="idWell">Id скважины</param>
	/// <param name="reportDate">Дата отчёта</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet]
	[ProducesResponseType(typeof(PhysicalFileResult), (int)HttpStatusCode.OK, "application/octet-stream")]
	[ProducesResponseType(StatusCodes.Status204NoContent)]
	public async Task<IActionResult> GenerateReportAsync([FromRoute] int idWell, 
		[Required] DateOnly reportDate, 
		CancellationToken cancellationToken)
	{
		if (!await CanUserAccessToWellAsync(idWell, cancellationToken))
			return Forbid();
		
		var reportFile = await autoGeneratedDailyReportService.GenerateAsync(idWell,
			reportDate,
			cancellationToken);

		return File(reportFile.stream, "application/octet-stream", reportFile.fileName);
	}

	/// <summary>
	/// Список файлов суточных отчётов
	/// </summary>
	/// <param name="idWell">Id скважины</param>
	/// <param name="request">Параметры запроса</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet("all")]
	[ProducesResponseType(typeof(PaginationContainer<AutoGeneratedDailyReportInfoDto>), (int)HttpStatusCode.OK)]
	public async Task<IActionResult> GetListAsync([FromRoute][Required] int idWell,
		[FromQuery] AutoGeneratedDailyReportRequest request,
		CancellationToken cancellationToken)
	{
		if (!await CanUserAccessToWellAsync(idWell, cancellationToken))
			return Forbid();
		
		var reports = await autoGeneratedDailyReportService.GetListAsync(idWell, 
			request, 
			cancellationToken);

		return Ok(reports);
	}

	/// <summary>
	/// Диапазон дат для формирования суточных отчётов
	/// </summary>
	/// <param name="idWell"></param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet("datesRange")]
	[ProducesResponseType(typeof(DatesRangeDto), (int)HttpStatusCode.OK)]
	public async Task<IActionResult> GetDatesRangeAsync(int idWell, CancellationToken cancellationToken)
	{
		if (!await CanUserAccessToWellAsync(idWell, cancellationToken))
			return Forbid();

		return Ok(await autoGeneratedDailyReportService.GetDatesRangeAsync(idWell, cancellationToken));
	}

	private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken cancellationToken)
	{
		int? idCompany = User.GetCompanyId();
		return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
			idWell, cancellationToken).ConfigureAwait(false);
	}
}