using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PARR.API.Contracts.V1;
using PARR.API.Contracts.V1.Requests.BaseRequests;
using PARR.API.Contracts.V1.Requests.Queries;
using PARR.API.Contracts.V1.Responses;
using PARR.API.Contracts.V1.Responses.Base;
using PARR.API.Contracts.V1.Responses.Statistics;
using PARR.API.Controllers.V1.Base;
using PARR.API.Helpers;
using PARR.Core.Repositories.Interfaces;
using PARR.Domain.Common.Roles;
using PARR.Domain.Entities;

namespace PARR.API.Controllers.V1.Statistics
{
    /// <summary>
    /// Статистика по истории робота
    /// </summary>
    [Authorize(Roles = ParrRoles.Administrator.Role)]
    public class StatRobotHistoryController : BaseApiController
    {
        private readonly IRobotHistoryRepository robotHistoryService;
        private readonly IRobotHistoryLevelRepository robotHistoryLevelService;
        private readonly IMapper mapper;

        public StatRobotHistoryController(
            IRobotHistoryRepository robotHistoryService,
            IRobotHistoryLevelRepository robotHistoryLevelService,
            IMapper mapper
            )
        {
            this.robotHistoryService = robotHistoryService;
            this.robotHistoryLevelService = robotHistoryLevelService;
            this.mapper = mapper;
        }

        /// <summary>
        /// Статистика истории роботов
        /// </summary>
        /// <returns></returns>
        [HttpGet(ApiRoutes.StatRobotHistory.Get)]
        public async Task<IActionResult> Get([FromQuery] StatRobotHistoryQuery request, [FromQuery] TimeZoneOffsetClient timeZoneQuery)
        {
            if (!request.Date.HasValue)
                request.Date = DateOnly.FromDateTime(DateTimeOffset.UtcNow.Date);

            #region всего

            var allQuery = robotHistoryService.Get()
                .AsNoTracking();

            if (request.HistoryLevel.HasValue)
                allQuery = allQuery.Where(t => t.HistoryLevel == (int)request.HistoryLevel);

            var allStat = await allQuery
                .GroupBy(t => t.HistoryLevel)
                .Select(t => new { HistoryLevel = t.Key, Count = t.Count() })
                .ToListAsync();

            var allStatDict = allStat.ToDictionary(s => s.HistoryLevel, s => s.Count);

            #endregion

            // Формируем диапазон в пользовательском времени
            var userDateStart = new DateTimeOffset(request.Date.Value.Year, request.Date.Value.Month, request.Date.Value.Day, 0, 0, 0, timeZoneQuery.TimeZoneOffset);
            var userDateEnd = userDateStart.AddDays(1);

            // Конвертируем в UTC для сравнения с БД
            var utcStart = userDateStart.UtcDateTime;
            var utcEnd = userDateEnd.UtcDateTime;

            // за дату

            #region Статистика за дату

            var dateStatQuery = robotHistoryService.Get()
                                    .AsNoTracking();

            if (request.HistoryLevel.HasValue)
                dateStatQuery = dateStatQuery.Where(t => t.HistoryLevel == (int)request.HistoryLevel);

            var dateStat = await dateStatQuery
                                    //.Where(t => t.DateCreated.DateTime.Date == request.Date.Value.Date)
                                    //.Where(t => t.DateCreated.UtcDateTime >= utcStart && t.DateCreated.UtcDateTime < utcEnd)
                                    .FilterByDateRangeUtc(t => t.DateCreated, utcStart, utcEnd)
                                    .GroupBy(t => t.HistoryLevel)
                                    .Select(t => new { HistoryLevel = t.Key, Count = t.Count() })
                                    .ToListAsync();

            var dateStatDict = dateStat.ToDictionary(s => s.HistoryLevel, s => s.Count);

            //var dateStat = await robotHistoryService.Get()
            //                        .AsNoTracking()
            //                        //.Where(t => t.DateCreated.DateTime.Date == request.Date.Value.Date)
            //                        //.Where(t => t.DateCreated.UtcDateTime >= utcStart && t.DateCreated.UtcDateTime < utcEnd)
            //                        .FilterByDateRangeUtc(t => t.DateCreated, utcStart, utcEnd)
            //                        .GroupBy(t => t.HistoryLevel)
            //                        .Select(t => new { HistoryLevel = t.Key, Count = t.Count() })
            //                        .ToListAsync();

            #endregion

            IQueryable<RobotHistoryLevel> levelsQuery = robotHistoryLevelService.Get().AsNoTracking();

            if (request.HistoryLevel.HasValue)
                levelsQuery = levelsQuery.Where(t => t.Level == (int)request.HistoryLevel.Value);

            var levels = await levelsQuery.OrderBy(t => t.Level).ToListAsync();

            var response = new List<StatRobotHistoryResponse>();

            foreach (var level in levels)
            {
                response.Add(new StatRobotHistoryResponse
                {
                    AllCount = allStatDict.GetValueOrDefault(level.Level, 0), //allStat.FirstOrDefault(t => t.HistoryLevel == level.Level)?.Count ?? 0,
                    DateCount = dateStatDict.GetValueOrDefault(level.Level, 0), //dateStat.FirstOrDefault(t => t.HistoryLevel == level.Level)?.Count ?? 0,
                    Date = request.Date.Value,
                    Level = mapper.Map<RobotHistoryLevelResponse>(level)
                });
            }

            return Ok(new Response<List<StatRobotHistoryResponse>>(response, true));
        }
    }
}
