// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.AspNetCore.Components;
using Radzen;
using Radzen.Blazor;
using SelmoStudio.Hmi.Server.AuditTrail.Model;
using SelmoStudio.Hmi.Server.AuditTrail.Service;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.WellKnownTypes;
using SelmoStudio.Hmi.Server.Shared.Resources;
using System.Globalization;
using System.Linq.Dynamic.Core;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.Helpers;

namespace SelmoStudio.Hmi.Server.AuditTrail.Pages
{
    public partial class AuditTrailPage
    {
        private bool _isButtonDisabled;
        private WellKnownContentFlexDirection _contentFlexDirection = WellKnownContentFlexDirection.Column;
        private AuditTrailClass _auditTrail;
        private IEnumerable<AuditTrailEntry> _filteredAuditTrailEntries;
        private WellKnownFileFormat _exportFileFormat = WellKnownFileFormat.Csv;
        private string _exportFilename = "exported-audit-trail.csv";
        private RadzenDataGrid<AuditTrailEntry> _auditTrailGrid;
        private List<AuditTrailEntry> _exportPayload;
        private DateTime? _startDate;
        private DateTime? _endDate;

        [Inject]
        private IAuditTrailService _auditTrailService { get; set; }

        [Inject]
        private DialogService _dialogService { get; set; }

        protected override async Task OnParametersSetAsync()
        {
            await Load();

            await base.OnParametersSetAsync();
        }

        protected override Task OnAfterRenderAsync(bool firstRender)
        {
            SetExportContent();

            SetButtonsDisabledStatus();

            return base.OnAfterRenderAsync(firstRender);
        }

        private void OnStartDateChanged(DateTime? value)
        {
            _startDate = value;

            if (_endDate.HasValue && _startDate.HasValue && _endDate.Value < _startDate.Value)
            {
                _endDate = _startDate;
            }

            OnDateFilterChanged();
        }

        private void OnEndDateChanged(DateTime? value)
        {
            _endDate = value;

            if (_startDate.HasValue && _endDate.HasValue && _startDate.Value > _endDate.Value)
            {
                _startDate = _endDate;
            }

            OnDateFilterChanged();
        }

        private void OnDateFilterChanged()
        {
            _auditTrailGrid.Reload();
        }

        private void StartDateRender(DateRenderEventArgs args)
        {
            if (_endDate.HasValue && args.Date > _endDate.Value)
            {
                args.Disabled = true;
            }
        }

        private void EndDateRender(DateRenderEventArgs args)
        {
            if (_startDate.HasValue && args.Date < _startDate.Value)
            {
                args.Disabled = true;
            }
        }

        private async Task LoadData(LoadDataArgs args)
        {
            var query = _auditTrail.Entries.AsQueryable();

            string descriptionFilter = null;
            string userFilter = null;

            if (args.Filters != null)
            {
                foreach (var filter in args.Filters)
                {
                    if (filter.Property == "Description")
                    {
                        descriptionFilter = (string)filter.FilterValue;
                    }
                    else if (filter.Property == "User")
                    {
                        userFilter = (string)filter.FilterValue;
                    }
                }
            }

            query = query.Where(entry => ((!_startDate.HasValue || entry.TimeStamp.Date >= _startDate.Value.Date) &&
                 (!_endDate.HasValue || entry.TimeStamp <= AdjustEndDateValue(_endDate.Value))) &&
                (string.IsNullOrEmpty(descriptionFilter) || (entry.Description != null && entry.Description.Contains(descriptionFilter, StringComparison.OrdinalIgnoreCase))) &&
                (string.IsNullOrEmpty(userFilter) || (entry.User != null && entry.User.Contains(userFilter, StringComparison.OrdinalIgnoreCase))));

            _filteredAuditTrailEntries = query.ToList();

            await InvokeAsync(StateHasChanged);
        }

        private async Task Reload()
        {
            _auditTrailService?.Reload();
            await Load();
        }

        private DateTime AdjustEndDateValue(DateTime dateTime)
        {
            return dateTime.Date.AddDays(1).AddTicks(-1);
        }

        private async Task Clear()
        {
            var numberOfSelectedEntries = _filteredAuditTrailEntries.Count();
            var confirmationTextResourceKey = numberOfSelectedEntries > 1 ? nameof(HmiResource.AuditTrailEntriesRemovalConfirmationText)
                : nameof(HmiResource.AuditTrailEntryRemovalConfirmationText);

            var result = await _dialogService.Confirm(_localizer[confirmationTextResourceKey, numberOfSelectedEntries],
                _localizer[nameof(HmiResource.AuditTrailRemovalConfirmationTitle)], new ConfirmOptions
                {
                    OkButtonText = _localizer[nameof(HmiResource.Yes)],
                    CancelButtonText = _localizer[nameof(HmiResource.No)],
                });

            if (result.HasValue && result.Value)
            {
                _auditTrailService.ClearEntries(_filteredAuditTrailEntries.ToList());
                await Load();
            }
        }

        private void SetFilteredAuditTrailEntries(IList<AuditTrailEntry> filteredAuditTrailEntries)
        {
            _filteredAuditTrailEntries = filteredAuditTrailEntries;
        }

        private void SetExportContent()
        {
            _exportPayload = _filteredAuditTrailEntries.ToList();
            InvokeAsync(() => StateHasChanged());
        }

        private void SetButtonsDisabledStatus()
        {
            _isButtonDisabled = _filteredAuditTrailEntries.Count() == 0;
        }

        private async Task Load()
        {
            _auditTrail = await _auditTrailService.GetAsync();
            ResetFilters();
            SetFilteredAuditTrailEntries(_auditTrail.Entries);
        }

        private void ResetFilters()
        {
            if (_auditTrailGrid != null)
            {
                foreach (var column in _auditTrailGrid.ColumnsCollection)
                {
                    _auditTrailGrid.ClearFilter(column);
                }
            }

            _startDate = null;
            _endDate = null;
        }

        private string CurrentUICultureDateFormat => DateTimeFormatter.CurrentUICultureDateFormat;

        private string FormatDateTime(DateTime date)
        {
            return DateTimeFormatter.FormatDateTime(date);
        }
    }
}