using OI.Metrology.Server.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using System.Globalization;
using System.Text.Json;

namespace OI.Metrology.Server.Repository;

public class ExportRepository : IExportRepository
{

    private readonly Serilog.ILogger _Log;
    private readonly string _RepositoryName;
    private readonly AppSettings _AppSettings;
    private readonly Dictionary<string, Dictionary<long, HeaderCommon>> _RdsToHeaderCommonCollection;

    public ExportRepository(AppSettings appSettings)
    {
        _AppSettings = appSettings;
        _RdsToHeaderCommonCollection = new();
        _RepositoryName = nameof(ExportRepository)[..^10];
        _Log = Serilog.Log.ForContext<ExportRepository>();
    }

    private static string[] Get()
    {
        DateTime dateTime = DateTime.Now;
        DateTime lastWeekDateTime = dateTime.AddDays(-7);
        Calendar calendar = new CultureInfo("en-US").Calendar;
        string weekOfYear = $"{dateTime:yyyy}_Week_{calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
        string lastWeekOfYear = $"{lastWeekDateTime:yyyy}_Week_{calendar.GetWeekOfYear(lastWeekDateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}";
        return new string[] { weekOfYear, lastWeekOfYear };
    }

    private List<string> GetFiles(HeaderCommon headerCommon, string searchPattern)
    {
        List<string> results = new();
        string directory;
        string[] weeks = Get();
        foreach (string weekYear in weeks)
        {
            if (headerCommon.ID < 1)
                directory = Path.Combine(_AppSettings.ApiExportPath, "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}");
            else
                directory = Path.Combine(_AppSettings.ApiExportPath, "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}", $"-{headerCommon.ID}");
            if (!Directory.Exists(directory))
                continue;
            results.AddRange(Directory.GetFiles(directory, searchPattern, SearchOption.AllDirectories));
        }
        return results;
    }

    string IExportRepository.GetExport(HeaderCommon headerCommon)
    {
        string result;
        List<string> files = GetFiles(headerCommon, "*.txt");
        if (files.Count != 1)
            result = string.Empty;
        else
            result = File.ReadAllText(files.First());
        return result;
    }

    Result<HeaderCommon[]> IExportRepository.GetHeaders(HeaderCommon headerCommon)
    {
        Result<HeaderCommon[]>? result;
        List<HeaderCommon> results = new();
        string json;
        HeaderCommon? hc;
        string? directory;
        string directoryName;
        JsonElement? jsonElement;
        const string ticks = "Ticks";
        JsonProperty[] jsonProperties;
        List<string> files = GetFiles(headerCommon, "*.json");
        foreach (string file in files)
        {
            json = File.ReadAllText(file);
            hc = JsonSerializer.Deserialize<HeaderCommon>(json);
            if (hc is null)
                continue;
            if (hc.ID < 1)
            {
                directory = Path.GetDirectoryName(file);
                if (directory is null)
                    continue;
                directoryName = Path.GetFileName(directory);
                if (directoryName.Length < 1 || directoryName[0] != '-' || !long.TryParse(directoryName[1..], out long id))
                    continue;
                hc.ID = id;
            }
            jsonElement = JsonSerializer.Deserialize<JsonElement>(json);
            if (jsonElement is not null && jsonElement.Value.ValueKind == JsonValueKind.Object)
            {
                jsonProperties = (from l in jsonElement.Value.EnumerateObject() where l.Name == ticks select l).ToArray();
                if (jsonProperties.Any() && long.TryParse(jsonProperties[0].Value.ToString(), out long ticksValue))
                    hc.Date = new(ticksValue);
            }
            results.Add(hc);
        }
        result = new()
        {
            Results = results.ToArray(),
            TotalRows = results.Count,
        };
        return result;
    }

    Result<HeaderCommon[]> IExportRepository.GetLogistics(HeaderCommon headerCommon)
    {
        Result<HeaderCommon[]>? result;
        List<HeaderCommon> results = new();
        string json;
        HeaderCommon? hc;
        List<string> files = GetFiles(headerCommon, "*.json");
        foreach (string file in files)
        {
            json = File.ReadAllText(file);
            hc = JsonSerializer.Deserialize<HeaderCommon>(json);
            if (hc is null)
                continue;
            results.Add(hc);
        }
        result = new()
        {
            Results = results.ToArray(),
            TotalRows = results.Count,
        };
        return result;
    }

    string IExportRepository.GetProcessDataStandardFormat(HeaderCommon headerCommon)
    {
        string result;
        List<string> files = GetFiles(headerCommon, "*.pdsf");
        if (files.Count != 1)
            result = string.Empty;
        else
            result = File.ReadAllText(files.First());
        return result;
    }

}