using Microsoft.AspNetCore.Mvc;
using Solar.Api.Models;
using Solar.Api.Services;
using Swashbuckle.AspNetCore.Annotations;
using System.Net.Mime;

namespace Solar.Api.Controllers;

[ApiController]
[Consumes(MediaTypeNames.Application.Json)]
[Produces(MediaTypeNames.Application.Json)]
public class SolarLogController : ControllerBase
{
    private readonly SolarService solarService;
    private readonly ILogger<SolarLogController> logger;

    public SolarLogController(
        SolarService solarService,
        ILogger<SolarLogController> logger)
    {
        this.solarService = solarService;
        this.logger = logger;
    }

    [HttpGet()]
    [Route("/day")]
    public async Task<ActionResult<DayResponse>> GetDayDetails(
        [SwaggerParameter(Required = true)]
        [SwaggerSchema(Format = "date")]
        [FromQuery]
        string date)
    {
        var parsedDate = TryParseDate(date);
        if (!parsedDate.HasValue || parsedDate.Value.Year < 2000 || parsedDate.Value.Year > 3000)
        {
            logger.LogInformation("Invalid date {Date} requested", date);
            return BadRequest();
        }

        return await solarService.GetDayDetails(parsedDate.Value);
    }

    /// Parameter <parameter>to</parameter> is inclusive
    [HttpGet()]
    [Route("/days")]
    public async Task<ActionResult<DaysResponse>> GetDaySummaries(
        [SwaggerParameter(Required = true)]
        [SwaggerSchema(Format = "date")]
        [FromQuery]
        string start,
        [SwaggerParameter(Required = true)]
        [SwaggerSchema(Format = "date")]
        [FromQuery]
        string stop)
    {
        var parsedStartDate = TryParseDate(start);
        if (!parsedStartDate.HasValue || parsedStartDate.Value.Year < 2000 || parsedStartDate.Value.Year > 3000)
        {
            logger.LogInformation("Invalid start date {Date} requested", start);
            return BadRequest();
        }

        var parsedStopDate = TryParseDate(stop);
        if (!parsedStopDate.HasValue || parsedStopDate.Value.Year < 2000 || parsedStopDate.Value.Year > 3000)
        {
            logger.LogInformation("Invalid stop date {Date} requested", stop);
            return BadRequest();
        }
        else if (parsedStopDate < parsedStartDate)
        {
            logger.LogInformation("Stop date {StopDate} must come before start date {StartDate} requested", stop, start);
            return BadRequest();
        }

        return await solarService.GetDaySummaries(parsedStartDate.Value, parsedStopDate.Value);
    }

    [HttpGet()]
    [Route("/months")]
    public async Task<ActionResult<MonthSummariesResponse>> GetMonthSummaries(
        [SwaggerParameter(Required = true)]
        [SwaggerSchema(Format = "yyyy-MM")]
        [FromQuery]
        string start,
        [SwaggerParameter(Required = true)]
        [SwaggerSchema(Format = "yyyy-MM")]
        [FromQuery]
        string stop)
    {
        var parsedStartDate = TryParseDate($"{start}-01");
        if (!parsedStartDate.HasValue || parsedStartDate.Value.Year < 2000 || parsedStartDate.Value.Year > 3000)
        {
            logger.LogInformation("Invalid start year month {YearMonth} requested", start);
            return BadRequest();
        }

        var parsedStopDate = TryParseDate($"{stop}-01");
        if (!parsedStopDate.HasValue || parsedStopDate.Value.Year < 2000 || parsedStopDate.Value.Year > 3000)
        {
            logger.LogInformation("Invalid stop year month {YearMonth} requested", stop);
            return BadRequest();
        }
        else if (parsedStopDate < parsedStartDate)
        {
            logger.LogInformation("Stop year month {StopYearMonth} must come before start year month {StartYearMonth} requested", stop, start);
            return BadRequest();
        }

        return await solarService.GetMonthSummaries(
            parsedStartDate.Value.Year,
            parsedStartDate.Value.Month,
            parsedStopDate.Value.Year,
            parsedStopDate.Value.Month);
    }

    private static DateOnly? TryParseDate(string value)
    {
        if (DateOnly.TryParseExact(value, "yyyy-MM-dd", out var date))
        {
            return date;
        }

        return null;
    }
}
