using System;
using System.Text;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using ReZero.DependencyInjection;
using medical.transfomer.business;
using medical.transfomer.entity;
using SqlSugar;

namespace medical.transfomer.service
{
    /// <summary>
    /// 医保交易服务,提供医保接口的请求处理功能
    /// </summary>
    public class MedicalInsuranceTransactionService : IScopeContract
    {
        private readonly TransformerFactory _transformerFactory;
        private readonly ILogger<MedicalInsuranceTransactionService> _logger;
        private readonly ISqlSugarClient _db;
        private readonly IHttpClientFactory _httpClientFactory;

        public MedicalInsuranceTransactionService(
            TransformerFactory transformerFactory,
            ILogger<MedicalInsuranceTransactionService> logger,
            ISqlSugarClient db,
            IHttpClientFactory httpClientFactory)
        {
            _transformerFactory = transformerFactory;
            _logger = logger;
            _db = db;
            _httpClientFactory = httpClientFactory;
        }

        /// <summary>
        /// 执行医保交易
        /// </summary>
        /// <param name="methodName">方法名称</param>
        /// <param name="inputData">输入数据</param>
        /// <returns>处理结果</returns>
        public async Task<object> ExecuteTransaction(string methodName, JToken inputData)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            
            try
            {
                _logger.LogInformation($"开始执行医保交易: {methodName}");
                
                // 将JToken转换为JObject传递给转换工厂
                JObject inputObject = inputData as JObject;
                if (inputObject == null && inputData != null)
                {
                    inputObject = new JObject();
                    inputObject["data"] = inputData;
                }
                
                // 调用转换工厂执行方法
                var result = await _transformerFactory.ExecuteMethod(methodName, inputObject);
                
                _logger.LogInformation($"医保交易执行完成: {methodName}");
                
                // 计算耗时
                stopwatch.Stop();
                long elapsedTime = stopwatch.ElapsedMilliseconds;
                
                // 保存成功日志
                await SaveTransactionLog(
                    methodName,
                    inputData.ToString(),
                    result == null ? null : JsonSerializer.Serialize(result),
                    1,
                    "",
                    elapsedTime);
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"执行医保交易异常: {methodName}");
                
                // 计算耗时
                stopwatch.Stop();
                long elapsedTime = stopwatch.ElapsedMilliseconds;
                
                // 保存失败日志
                await SaveTransactionLog(
                    methodName,
                    inputData.ToString(),
                    null,
                    0,
                    ex.Message,
                    elapsedTime);
                
                return new { code = -1, msg = $"交易执行异常: {ex.Message}" };
            }
        }

        /// <summary>
        /// 根据方法ID获取方法配置信息
        /// </summary>
        /// <param name="methodId">方法ID</param>
        /// <returns>方法配置信息</returns>
        public async Task<STD_METHOD_CONFIG> GetMethodConfigById(string methodId)
        {
            return await _db.Queryable<STD_METHOD_CONFIG>()
                .FirstAsync(m => m.METHOD_ID == methodId);
        }

        /// <summary>
        /// 根据方法名称获取方法配置信息
        /// </summary>
        /// <param name="methodName">方法名称</param>
        /// <returns>方法配置信息</returns>
        public async Task<STD_METHOD_CONFIG> GetMethodConfigByName(string methodName)
        {
            return await _db.Queryable<STD_METHOD_CONFIG>()
                .FirstAsync(m => m.METHOD_NAME == methodName);
        }

        /// <summary>
        /// 获取方法的映射配置
        /// </summary>
        /// <param name="methodId">方法ID</param>
        /// <param name="parameterType">参数类型(1:入参, 2:出参)</param>
        /// <returns>对象装配配置列表</returns>
        public async Task<List<STD_OBJECT_ASSEMBLY>> GetMethodAssemblies(string methodId, int parameterType)
        {
            return await _db.Queryable<STD_OBJECT_ASSEMBLY>()
                .Where(a => a.METHOD_REF == methodId && a.PARAMETR_TYPE == parameterType)
                .ToListAsync();
        }

        /// <summary>
        /// 获取映射表的字段映射关系
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="isSystemToInterface">是否为系统到接口的映射</param>
        /// <returns>字段映射关系列表</returns>
        public async Task<List<STD_OBJECT_MAPPING>> GetFieldMappings(string tableName, bool isSystemToInterface)
        {
            if (isSystemToInterface)
            {
                return await _db.Queryable<STD_OBJECT_MAPPING>()
                    .Where(m => m.SYSTEM_TABLE_NAME == tableName)
                    .ToListAsync();
            }
            else
            {
                return await _db.Queryable<STD_OBJECT_MAPPING>()
                    .Where(m => m.OBJECT_TABLE_NAME == tableName)
                    .ToListAsync();
            }
        }

        /// <summary>
        /// 保存交易日志
        /// </summary>
        /// <param name="methodName">方法名称</param>
        /// <param name="requestData">请求数据</param>
        /// <param name="responseData">响应数据</param>
        /// <param name="status">状态(1:成功, 0:失败)</param>
        /// <param name="errorMessage">错误信息</param>
        /// <param name="elapsedTime">耗时(毫秒)</param>
        /// <returns></returns>
        public async Task SaveTransactionLog(
            string methodName, 
            string requestData, 
            string responseData, 
            int status, 
            string errorMessage,
            long elapsedTime)
        {
            try
            {
                // 获取方法配置
                var methodConfig = await GetMethodConfigByName(methodName);
                
                if (methodConfig == null)
                {
                    _logger.LogWarning($"未找到方法配置,无法保存交易日志: {methodName}");
                    return;
                }

                // 创建日志实体
                var transLog = new STD_TRANSACTION_LOG
                {
                    METHOD_ID = methodConfig.METHOD_ID,
                    METHOD_NAME = methodName,
                    REQUEST_TIME = DateTime.Now,
                    REQUEST_DATA = methodConfig.SAVE_INPUT == 1 ? requestData : null,
                    RESPONSE_TIME = DateTime.Now,
                    RESPONSE_DATA = methodConfig.SAVE_OUTPUT == 1 ? responseData : null,
                    STATUS = status,
                    ERROR_MESSAGE = errorMessage,
                    ELAPSED_TIME = elapsedTime,
                    CLIENT_IP = "", // TODO: 获取客户端IP
                    USER_ID = ""    // TODO: 获取当前用户ID
                };

                // 保存到数据库
                await _db.Insertable(transLog).ExecuteCommandAsync();
                
                _logger.LogInformation($"保存交易日志成功: {methodName}, 状态: {status}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "保存交易日志异常");
            }
        }

        /// <summary>
        /// 直接调用医保接口
        /// </summary>
        /// <param name="endpoint">接口地址</param>
        /// <param name="requestData">请求数据</param>
        /// <returns>响应结果</returns>
        public async Task<JToken> CallMedicalInsuranceApi(string endpoint, JToken requestData)
        {
            try
            {
                var httpClient = _httpClientFactory.CreateClient("MedicalInsurance");
                
                // 将JToken转换为字符串
                string requestContent = requestData.ToString();
                var content = new StringContent(
                    requestContent,
                    Encoding.UTF8,
                    "application/json");

                var response = await httpClient.PostAsync(endpoint, content);
                response.EnsureSuccessStatusCode();

                var responseString = await response.Content.ReadAsStringAsync();
                return JToken.Parse(responseString);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"调用医保接口异常: {endpoint}");
                throw;
            }
        }
    }
}