using System.Security.Cryptography.X509Certificates;
using FitConnect.Models;
using FitConnect.Services;
using FitConnect.Services.Models;
using Microsoft.Extensions.Logging;

namespace FitConnect;

/// <summary>
///     The FitConnect API Client
/// </summary>
// ReSharper disable once UnusedType.Global
public class Client {
    private readonly string _clientId;
    private readonly string _clientSecret;
    private readonly Sender _sender;
    private readonly Subscriber _subscriber;



    public Client(FitConnectEndpoints endpoints,
        string clientId, string clientSecret,
        X509Certificate2? certificate = null,
        ILogger? logger = null) {
        _clientId = clientId;
        _clientSecret = clientSecret;
        _sender = new Sender(logger, endpoints, certificate);
        _subscriber = new Subscriber(logger, endpoints, certificate);
        //_service = new FitConnectApiService(endpoints, logger);
    }


    /// <summary>
    /// Get destination for submission.
    /// <para>Leika-Key and one of the area specifier has to be set.</para>
    /// </summary>
    /// <param name="leiaKey">Mandatory</param>
    /// <param name="ags"></param>
    /// <param name="ars"></param>
    /// <param name="areaId"></param>
    /// <returns></returns>
    public async Task<string> GetDestinationIdAsync(string leiaKey, string? ags, string? ars,
        string? areaId) {
        if (string.IsNullOrEmpty(leiaKey)) {
            throw new ArgumentException("leiaKey is mandatory");
        }

        if (string.IsNullOrEmpty(ags) && 
            string.IsNullOrEmpty(ars) && 
            string.IsNullOrEmpty(areaId)) {
            throw new ArgumentException("One of the area specifier has to be set");
        }
        
        return await _sender.GetDestinationIdAsync(leiaKey, ags, ars, areaId);
    }

    /// <summary>
    ///     Sending a submission to the FitConnect API<br/>
    /// <para>The submission is prepared for sending to the FitConnect API.</para>
    /// </summary>
    /// <param name="submission">The submission to send</param>
    /// <returns>success</returns>
    // ReSharper disable once MemberCanBePrivate.Global
    public async Task<bool> SendSubmissionAsync(Submission submission) {
        // Einreichung anlegen und ankündigen
        var createSubmissionDto = _sender.CreateSubmissionDto(submission);

        // Anlagen verschlüsseln
        var encryptedAttachments = submission.Attachments
            .Select(a => _sender.EncryptAttachment(a)).ToList();

        // Anlagen hochladen
        await _sender.UploadAttachmentsAsync(encryptedAttachments);

        // Metadaten befüllen und verschlüsseln
        var metaData = await _sender.CreateMetadataAsync("", new byte[] { });

        // Fachdaten verschlüsseln
        var encryptedData = _sender.EncryptDataAsync(submission.Data);

        // Fachdaten & Metadaten hochladen und Einreichung absenden
        await _sender.SubmitSubmissionAsync(submission);

        return true;
    }

    /// <summary>
    ///     Gets all submissions from the FitConnect API
    /// </summary>
    /// <returns>List of the available submissions</returns>
    // ReSharper disable once MemberCanBePrivate.Global
    public async Task<List<Submission>> GetSubmissionsAsync(string destinationId, int offset = 0,
        int limit = 100) {
        // var pickUpList =
        //     await _service.SubmissionService.ListSubmissions(destinationId, offset, limit);
        // return pickUpList.Submissions.Select(dto => (Submission)dto).ToList();
        throw new NotImplementedException();
    }

    /// <summary>
    ///     Sending a submission to the FitConnect API
    /// </summary>
    /// <param name="submission">The submission to send</param>
    /// <returns>success</returns>
    public bool SendSubmission(Submission submission) {
        return SendSubmissionAsync(submission).Result;
    }

    /// <summary>
    ///     Gets all submissions from the FitConnect API
    /// </summary>
    /// <returns>List of the available submissions</returns>
    public List<Submission> GetSubmissions(string destinationId, int offset = 0,
        int limit = 100) {
        return GetSubmissionsAsync(destinationId, offset, limit).Result;
    }
}