using MediatR;
using Microsoft.Extensions.Logging;
using NetworkResurrector.Server.Wrapper.Services;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace NetworkResurrector.Api.Application.Queries
{
    public class GetSystemVersion
    {
        public class Query : IRequest<Model> { }

        public class Model
        {
            public ServiceVersion Api { get; set; }
            public ServiceVersion Server { get; set; }
        }

        public record ServiceVersion(string Version, DateTime LastReleaseDate);

        public class QueryHandler : IRequestHandler<Query, Model>
        {
            private readonly IResurrectorService _resurrectorService;
            private readonly ILogger<GetSystemVersion> _logger;

            public QueryHandler(IResurrectorService resurrectorService, ILogger<GetSystemVersion> logger)
            {
                _resurrectorService=resurrectorService;
                _logger=logger;
            }

            public async Task<Model> Handle(Query request, CancellationToken cancellationToken)
            {
                var apiVersion = GetApiVersion();
                var (version, lastUpdateDate) = await GetServerVersion();

                var result = new Model
                {
                    Api = apiVersion,
                    Server = new ServiceVersion(FormatVersion(version), lastUpdateDate)
                };

                return result;
            }

            private ServiceVersion GetApiVersion()
            {
                var version = Environment.GetEnvironmentVariable("APP_VERSION");
                var appDate = Environment.GetEnvironmentVariable("APP_DATE");

                if (string.IsNullOrEmpty(version))
                    version = Assembly.GetEntryAssembly().GetName().Version.ToString();

                if (!DateTime.TryParse(appDate, out var lastReleaseDate))
                {
                    var location = Assembly.GetExecutingAssembly().Location;
                    lastReleaseDate = File.GetLastWriteTime(location);
                }

                var result = new ServiceVersion(FormatVersion(version), lastReleaseDate);
                return result;
            }

            private async Task<ServiceVersion> GetServerVersion()
            {
                try
                {
                    var serverVersion = await _resurrectorService.GetServiceVersion();
                    return new ServiceVersion(serverVersion.Version, serverVersion.LastReleaseDate);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Server version could not be obtained.");
                }
                return new ServiceVersion("0.0.0", DateTime.MinValue);
            }

            private string FormatVersion(string version)
            {
                if (string.IsNullOrEmpty(version))
                    return string.Empty;
                var parts = version.Split('.');
                if (parts.Length < 3)
                    return version;
                var shortVersion = string.Join('.', parts.Take(3));
                return shortVersion;
            }
        }
    }
}
