using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LSFE.MobApp.Services.Coverage
{
    public interface IFileDownloadService
    {
        Task<string> DownloadFileAsync(string fileUrl, string fileName, CancellationToken cancellationToken);
        Task<bool> IsFileDownloadedAsync(string fileName);
        string GetLocalFilePath(string fileName);
    }
    public class FileDownloadService : IFileDownloadService
    {
        private readonly HttpClient _httpClient;
        private readonly string _downloadFolder;
        private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(3); // Limit concurrent downloads

        public FileDownloadService(IHttpClientFactory httpClientFactory)
        {
            _httpClient = httpClientFactory.CreateClient("ApiClient");
            _httpClient.Timeout = TimeSpan.FromMinutes(20);

            _downloadFolder = Path.Combine(FileSystem.AppDataDirectory, "ProductMaterials");
            Directory.CreateDirectory(_downloadFolder);
        }

        public async Task<string> DownloadFileAsync(string fileUrl, string fileName, CancellationToken cancellationToken = default)
        {
            await _semaphore.WaitAsync(cancellationToken);

            try
            {
                var localPath = Path.Combine(_downloadFolder, fileName);

                if (File.Exists(localPath))
                {
                    var fileInfo = new FileInfo(localPath);
                    if (fileInfo.Length > 0)
                        return localPath;

                    File.Delete(localPath);
                }

                var tempPath = localPath + ".tmp";

                using var response = await _httpClient.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
                response.EnsureSuccessStatusCode();

                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
                await using var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None);

                await stream.CopyToAsync(fileStream, cancellationToken);
                await fileStream.FlushAsync(cancellationToken);
                fileStream.Close();

                if (File.Exists(localPath))
                    File.Delete(localPath);

                File.Move(tempPath, localPath);

                return localPath;
            }
            catch (HttpRequestException ex) when (ex.InnerException is System.Security.Authentication.AuthenticationException)
            {
                Debug.WriteLine($"SSL/TLS error for {fileName}: {ex.Message}");
                throw new InvalidOperationException("SSL certificate validation failed. Please check server certificate configuration.", ex);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Download failed for {fileName}: {ex.Message}");
                throw;
            }
            finally
            {
                _semaphore.Release();
            }
        }

        public Task<bool> IsFileDownloadedAsync(string fileName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(fileName))
                    return Task.FromResult(false);

                var localPath = Path.Combine(_downloadFolder, fileName);

                if (!File.Exists(localPath))
                    return Task.FromResult(false);

                // Verify file is not empty/corrupted
                var fileInfo = new FileInfo(localPath);
                return Task.FromResult(fileInfo.Length > 0);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error checking file existence for {fileName}: {ex.Message}");
                return Task.FromResult(false);
            }
        }

        public string GetLocalFilePath(string fileName)
        {
            return Path.Combine(_downloadFolder, fileName);
        }
    }
}