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;
///
/// Mock Implementation برای شبیهسازی Daya API
/// این کلاس فقط برای تست و توسعه است و باید با Implementation واقعی جایگزین شود
///
public class MockDayaLoanApiService : IDayaLoanApiService
{
private readonly ILogger _logger;
public MockDayaLoanApiService(ILogger logger)
{
_logger = logger;
}
public async Task> CheckLoanStatusAsync(
List nationalCodes,
CancellationToken cancellationToken = default)
{
_logger.LogWarning("⚠️ Using MOCK Daya API Service - Replace with real implementation!");
// شبیهسازی تاخیر شبکه
await Task.Delay(100, cancellationToken);
var results = new List();
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;
}
}
///
/// Real Implementation برای API واقعی دایا
/// مبتنی بر مستند TA-DAYA-S10-G-MerchantServices
///
public class DayaLoanApiService : IDayaLoanApiService
{
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
private readonly IConfiguration _configuration;
public DayaLoanApiService(
HttpClient httpClient,
ILogger 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.Add("merchant-permission-key", permissionKey);
}
else
{
_logger.LogWarning("⚠️ DayaApi:MerchantPermissionKey is not configured in appsettings!");
}
}
public async Task> CheckLoanStatusAsync(
List nationalCodes,
CancellationToken cancellationToken = default)
{
try
{
_logger.LogInformation("Calling Daya API for {Count} national codes", nationalCodes.Count);
// ساخت Request Body
var requestBody = new DayaContractsRequest
{
NationalCodes = nationalCodes
};
// فراخوانی API
var response = await _httpClient.PostAsJsonAsync(
"/api/merchant/contracts",
requestBody,
cancellationToken);
// خواندن پاسخ
var apiResponse = await response.Content.ReadFromJsonAsync(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);
}
}
///
/// تبدیل پاسخ API دایا به مدل داخلی
///
private List MapApiResponseToResults(
List apiData,
List requestedNationalCodes)
{
var results = new List();
// برای هر کد ملی درخواستی
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;
}
///
/// تبدیل StatusDescription دایا به Enum داخلی
///
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;
}
///
/// ساخت نتایج خالی در صورت خطا
///
private List CreateEmptyResults(List nationalCodes)
{
return nationalCodes.Select(nc => new DayaLoanStatusResult
{
NationalCode = nc,
Status = DayaLoanStatus.NotRequested,
ContractNumber = null
}).ToList();
}
}
#region Daya API Models
///
/// Request body برای /api/merchant/contracts
///
internal class DayaContractsRequest
{
[JsonPropertyName("NationalCodes")]
public List NationalCodes { get; set; } = new();
}
///
/// Response از /api/merchant/contracts
///
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? Data { get; set; }
}
///
/// دادههای قرارداد در پاسخ API
///
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