using CMSMicroservice.Application.DayaLoanCQ.Services;
using CMSMicroservice.Domain.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using System.Linq;

namespace CMSMicroservice.Infrastructure.Services;

/// <summary>
/// Mock Implementation برای شبیه‌سازی Daya API
/// این کلاس فقط برای تست و توسعه است و باید با Implementation واقعی جایگزین شود
/// </summary>
public class MockDayaLoanApiService : IDayaLoanApiService
{
    private readonly ILogger<MockDayaLoanApiService> _logger;

    public MockDayaLoanApiService(ILogger<MockDayaLoanApiService> logger)
    {
        _logger = logger;
    }

    public async Task<List<DayaLoanStatusResult>> CheckLoanStatusAsync(
        List<string> nationalCodes,
        CancellationToken cancellationToken = default)
    {
        _logger.LogWarning("⚠️ Using MOCK Daya API Service - Replace with real implementation!");
        
        // شبیه‌سازی تاخیر شبکه
        await Task.Delay(100, cancellationToken);
        
        var results = new List<DayaLoanStatusResult>();
        
        foreach (var nationalCode in nationalCodes)
        {
            // شبیه‌سازی: کدملی‌هایی که با 1 شروع می‌شوند وام گرفته‌اند
            if (nationalCode.StartsWith("1"))
            {
                results.Add(new DayaLoanStatusResult
                {
                    NationalCode = nationalCode,
                    Status = DayaLoanStatus.PendingReceive,
                    ContractNumber = $"MOCK-DAYA-{nationalCode}-{DateTime.Now.Ticks}"
                });
            }
            // شبیه‌سازی: کدملی‌هایی که با 2 شروع می‌شوند رد شده‌اند
            else if (nationalCode.StartsWith("2"))
            {
                results.Add(new DayaLoanStatusResult
                {
                    NationalCode = nationalCode,
                    Status = DayaLoanStatus.Rejected,
                    ContractNumber = null
                });
            }
            // بقیه: هنوز بررسی نشده‌اند
            else
            {
                results.Add(new DayaLoanStatusResult
                {
                    NationalCode = nationalCode,
                    Status = DayaLoanStatus.PendingReceive,
                    ContractNumber = null // هنوز قرارداد صادر نشده
                });
            }
        }
        
        _logger.LogInformation("Mock Daya API returned {Count} results", results.Count);
        return results;
    }
}

/// <summary>
/// Real Implementation برای API واقعی دایا
/// مبتنی بر مستند TA-DAYA-S10-G-MerchantServices
/// </summary>
public class DayaLoanApiService : IDayaLoanApiService
{
    private readonly HttpClient _httpClient;
    private readonly ILogger<DayaLoanApiService> _logger;
    private readonly IConfiguration _configuration;

    public DayaLoanApiService(
        HttpClient httpClient, 
        ILogger<DayaLoanApiService> logger,
        IConfiguration configuration)
    {
        _httpClient = httpClient;
        _logger = logger;
        _configuration = configuration;
        
        // تنظیم Base Address از Configuration
        var baseAddress = _configuration["DayaApi:BaseAddress"] ?? "https://testdaya.tadbirandishan.com";
        _httpClient.BaseAddress = new Uri(baseAddress);
        
        // تنظیم merchant-permission-key از Configuration
        var permissionKey = _configuration["DayaApi:MerchantPermissionKey"];
        if (!string.IsNullOrEmpty(permissionKey) && _httpClient.DefaultRequestHeaders.TryGetValues("merchant-permission-key", out var values))
        {
            if (values== null || !values.Any())
            {
                
            _httpClient.DefaultRequestHeaders.Add("merchant-permission-key", permissionKey);
            }
        }
        else
        {
            _logger.LogWarning("⚠️ DayaApi:MerchantPermissionKey is not configured in appsettings!");
        }
    }

    public async Task<List<DayaLoanStatusResult>> CheckLoanStatusAsync(
        List<string> nationalCodes,
        CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("Calling Daya API for {Count} national codes", nationalCodes.Count);

            // ساخت Request Body
            var requestBody = new DayaContractsRequest
            {
                NationalCodes = nationalCodes
            };

            var response = await _httpClient.PostAsJsonAsync(
                "/api/merchant/contracts", 
                requestBody, 
                cancellationToken);
            var x = await response.Content.ReadAsStringAsync();
            // خواندن پاسخ
            var apiResponse = await response.Content.ReadFromJsonAsync<DayaContractsResponse>(cancellationToken);

            // بررسی موفقیت
            if (apiResponse == null)
            {
                _logger.LogError("Daya API returned null response");
                return CreateEmptyResults(nationalCodes);
            }

            if (!apiResponse.Succeed)
            {
                _logger.LogWarning("Daya API call failed. Code: {Code}, Message: {Message}", 
                    apiResponse.Code, apiResponse.Message);
                return CreateEmptyResults(nationalCodes);
            }

            if (apiResponse.Data == null || !apiResponse.Data.Any())
            {
                _logger.LogInformation("Daya API returned no contract data");
                return CreateEmptyResults(nationalCodes);
            }

            // تبدیل نتایج API به مدل داخلی
            var results = MapApiResponseToResults(apiResponse.Data, nationalCodes);

            _logger.LogInformation("Daya API returned {Count} contracts for {RequestCount} national codes", 
                results.Count(r => !string.IsNullOrEmpty(r.ContractNumber)), 
                nationalCodes.Count);

            return results;
        }
        catch (HttpRequestException ex)
        {
            _logger.LogError(ex, "HTTP error calling Daya API. Status: {StatusCode}", ex.StatusCode);
            return CreateEmptyResults(nationalCodes);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unexpected error calling Daya API");
            return CreateEmptyResults(nationalCodes);
        }
    }

    /// <summary>
    /// تبدیل پاسخ API دایا به مدل داخلی
    /// </summary>
    private List<DayaLoanStatusResult> MapApiResponseToResults(
        List<DayaContractData> apiData, 
        List<string> requestedNationalCodes)
    {
        var results = new List<DayaLoanStatusResult>();

        // برای هر کد ملی درخواستی
        foreach (var nationalCode in requestedNationalCodes)
        {
            // پیدا کردن آخرین قرارداد این کد ملی (براساس تاریخ)
            var latestContract = apiData
                .Where(d => d.NationalCode == nationalCode)
                .OrderByDescending(d => d.DateTime)
                .FirstOrDefault();

            if (latestContract != null)
            {
                // تعیین وضعیت براساس StatusDescription
                var status = MapStatusDescription(latestContract.StatusDescription);

                results.Add(new DayaLoanStatusResult
                {
                    NationalCode = nationalCode,
                    Status = status,
                    ContractNumber = latestContract.ApplicationNo
                });

                _logger.LogDebug("Daya contract found for {NationalCode}: {ContractNo}, Status: {Status}", 
                    nationalCode, latestContract.ApplicationNo, latestContract.StatusDescription);
            }
            else
            {
                // هیچ قراردادی برای این کد ملی پیدا نشد
                results.Add(new DayaLoanStatusResult
                {
                    NationalCode = nationalCode,
                    Status = DayaLoanStatus.NotRequested,
                    ContractNumber = null
                });
            }
        }

        return results;
    }

    /// <summary>
    /// تبدیل StatusDescription دایا به Enum داخلی
    /// </summary>
    private DayaLoanStatus MapStatusDescription(string statusDescription)
    {
        if (string.IsNullOrWhiteSpace(statusDescription))
            return DayaLoanStatus.NotRequested;

        // براساس مستند دایا: "فعال شده (در انتظار تسویه)" = وام تایید شده
        if (statusDescription.Contains("فعال شده") || statusDescription.Contains("در انتظار تسویه"))
            return DayaLoanStatus.PendingReceive;

        if (statusDescription.Contains("رد شده") || statusDescription.Contains("رد"))
            return DayaLoanStatus.Rejected;

        if (statusDescription.Contains("بررسی") || statusDescription.Contains("در حال"))
            return DayaLoanStatus.UnderReview;

        // پیش‌فرض
        return DayaLoanStatus.NotRequested;
    }

    /// <summary>
    /// ساخت نتایج خالی در صورت خطا
    /// </summary>
    private List<DayaLoanStatusResult> CreateEmptyResults(List<string> nationalCodes)
    {
        return nationalCodes.Select(nc => new DayaLoanStatusResult
        {
            NationalCode = nc,
            Status = DayaLoanStatus.NotRequested,
            ContractNumber = null
        }).ToList();
    }
}

#region Daya API Models

/// <summary>
/// Request body برای /api/merchant/contracts
/// </summary>
internal class DayaContractsRequest
{
    [JsonPropertyName("NationalCodes")]
    public List<string> NationalCodes { get; set; } = new();
}

/// <summary>
/// Response از /api/merchant/contracts
/// </summary>
internal class DayaContractsResponse
{
    [JsonPropertyName("succeed")]
    public bool Succeed { get; set; }

    [JsonPropertyName("code")]
    public int Code { get; set; }

    [JsonPropertyName("message")]
    public string? Message { get; set; }

    [JsonPropertyName("data")]
    public List<DayaContractData>? Data { get; set; }
}

/// <summary>
/// داده‌های قرارداد در پاسخ API
/// </summary>
internal class DayaContractData
{
    [JsonPropertyName("nationalCode")]
    public string NationalCode { get; set; } = string.Empty;

    [JsonPropertyName("applicationNo")]
    public string ApplicationNo { get; set; } = string.Empty;

    [JsonPropertyName("statusDescription")]
    public string StatusDescription { get; set; } = string.Empty;

    [JsonPropertyName("dateTime")]
    public DateTime DateTime { get; set; }
}

#endregion
