using System.Net.Http.Json;
using System.Text.Json;
using DiunaBI.Application.DTOModels.Common;
using DiunaBI.Domain.Entities;

namespace DiunaBI.UI.Shared.Services;

public class JobService
{
    private readonly HttpClient _httpClient;

    public JobService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    private readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNameCaseInsensitive = true
    };

    public async Task<PagedResult<QueueJob>> GetJobsAsync(int page = 1, int pageSize = 50, List<JobStatus>? statuses = null, JobType? jobType = null, Guid? layerId = null)
    {
        var start = (page - 1) * pageSize;
        var query = $"Jobs?start={start}&limit={pageSize}";

        if (statuses != null && statuses.Count > 0)
        {
            foreach (var status in statuses)
            {
                query += $"&statuses={(int)status}";
            }
        }

        if (jobType.HasValue)
            query += $"&jobType={(int)jobType.Value}";

        if (layerId.HasValue)
            query += $"&layerId={layerId.Value}";

        var response = await _httpClient.GetAsync(query);
        response.EnsureSuccessStatusCode();

        var json = await response.Content.ReadAsStringAsync();
        var result = JsonSerializer.Deserialize<PagedResult<QueueJob>>(json, _jsonOptions);

        return result ?? new PagedResult<QueueJob>();
    }

    public async Task<QueueJob?> GetJobByIdAsync(Guid id)
    {
        var response = await _httpClient.GetAsync($"Jobs/{id}");

        if (!response.IsSuccessStatusCode)
            return null;

        return await response.Content.ReadFromJsonAsync<QueueJob>();
    }

    public async Task<bool> RetryJobAsync(Guid id)
    {
        var response = await _httpClient.PostAsync($"Jobs/{id}/retry", null);
        return response.IsSuccessStatusCode;
    }

    public async Task<bool> CancelJobAsync(Guid id)
    {
        var response = await _httpClient.DeleteAsync($"Jobs/{id}");
        return response.IsSuccessStatusCode;
    }

    public async Task<JobStats?> GetStatsAsync()
    {
        var response = await _httpClient.GetAsync("Jobs/stats");

        if (!response.IsSuccessStatusCode)
            return null;

        return await response.Content.ReadFromJsonAsync<JobStats>();
    }

    public async Task<CreateJobResult?> CreateJobForLayerAsync(Guid layerId)
    {
        var response = await _httpClient.PostAsync($"Jobs/create-for-layer/{layerId}", null);

        if (!response.IsSuccessStatusCode)
            return null;

        return await response.Content.ReadFromJsonAsync<CreateJobResult>();
    }

    public async Task<(bool success, int jobsCreated, string message)> ScheduleAllJobsAsync(string? nameFilter = null)
    {
        try
        {
            var query = string.IsNullOrEmpty(nameFilter) ? "" : $"?nameFilter={Uri.EscapeDataString(nameFilter)}";
            var response = await _httpClient.PostAsync($"Jobs/ui/schedule{query}", null);

            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadAsStringAsync();
                return (false, 0, $"Failed to schedule jobs: {error}");
            }

            var json = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<JsonElement>(json, _jsonOptions);

            var jobsCreated = result.GetProperty("jobsCreated").GetInt32();
            var message = result.GetProperty("message").GetString() ?? "Jobs scheduled";

            return (true, jobsCreated, message);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Scheduling jobs failed: {ex.Message}");
            return (false, 0, $"Error: {ex.Message}");
        }
    }

    public async Task<(bool success, int jobsCreated, string message)> ScheduleImportJobsAsync(string? nameFilter = null)
    {
        try
        {
            var query = string.IsNullOrEmpty(nameFilter) ? "" : $"?nameFilter={Uri.EscapeDataString(nameFilter)}";
            var response = await _httpClient.PostAsync($"Jobs/ui/schedule/imports{query}", null);

            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadAsStringAsync();
                return (false, 0, $"Failed to schedule import jobs: {error}");
            }

            var json = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<JsonElement>(json, _jsonOptions);

            var jobsCreated = result.GetProperty("jobsCreated").GetInt32();
            var message = result.GetProperty("message").GetString() ?? "Import jobs scheduled";

            return (true, jobsCreated, message);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Scheduling import jobs failed: {ex.Message}");
            return (false, 0, $"Error: {ex.Message}");
        }
    }

    public async Task<(bool success, int jobsCreated, string message)> ScheduleProcessJobsAsync()
    {
        try
        {
            var response = await _httpClient.PostAsync("Jobs/ui/schedule/processes", null);

            if (!response.IsSuccessStatusCode)
            {
                var error = await response.Content.ReadAsStringAsync();
                return (false, 0, $"Failed to schedule process jobs: {error}");
            }

            var json = await response.Content.ReadAsStringAsync();
            var result = JsonSerializer.Deserialize<JsonElement>(json, _jsonOptions);

            var jobsCreated = result.GetProperty("jobsCreated").GetInt32();
            var message = result.GetProperty("message").GetString() ?? "Process jobs scheduled";

            return (true, jobsCreated, message);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Scheduling process jobs failed: {ex.Message}");
            return (false, 0, $"Error: {ex.Message}");
        }
    }
}

public class JobStats
{
    public int Pending { get; set; }
    public int Running { get; set; }
    public int Completed { get; set; }
    public int Failed { get; set; }
    public int Retrying { get; set; }
    public int Total { get; set; }
}

public class CreateJobResult
{
    public bool Success { get; set; }
    public Guid JobId { get; set; }
    public string? Message { get; set; }
    public bool Existing { get; set; }
}
