using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Haoliang.Core.Services;
using Haoliang.Models.Common;

namespace Haoliang.Api.Filters
{
    public class ValidationFilter : IActionFilter
    {
        private readonly ILoggingService _loggingService;

        public ValidationFilter(ILoggingService loggingService)
        {
            _loggingService = loggingService;
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            // Check if model state is valid
            if (!context.ModelState.IsValid)
            {
                LogValidationErrors(context.ModelState);
                context.Result = CreateValidationErrorResponse(context.ModelState);
            }
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            // No operation needed
        }

        private void LogValidationErrors(ModelStateDictionary modelState)
        {
            var errors = new Dictionary<string, List<string>>();

            foreach (var keyModelStatePair in modelState)
            {
                var key = keyModelStatePair.Key;
                var modelStateErrors = keyModelStatePair.Value.Errors;

                if (modelStateErrors.Count > 0)
                {
                    errors[key] = modelStateErrors.Select(error => 
                        string.IsNullOrEmpty(error.ErrorMessage) ? "Validation error occurred" : error.ErrorMessage
                    ).ToList();
                }
            }

            _loggingService.LogWarningAsync($"Model validation failed: {JsonSerializer.Serialize(errors)}").Wait();
        }

        private IActionResult CreateValidationErrorResponse(ModelStateDictionary modelState)
        {
            var errors = new Dictionary<string, string[]>();

            foreach (var keyModelStatePair in modelState)
            {
                var key = keyModelStatePair.Key;
                var errorsArray = keyModelStatePair.Value.Errors.Select(error => 
                    string.IsNullOrEmpty(error.ErrorMessage) ? "Validation error occurred" : error.ErrorMessage
                ).ToArray();

                if (errorsArray.Length > 0)
                {
                    errors[key] = errorsArray;
                }
            }

            var response = new ApiResponse<Dictionary<string, string[]>>
            {
                Success = false,
                Message = "Validation failed",
                ErrorCode = 400,
                Data = errors,
                Timestamp = DateTime.Now
            };

            return new BadRequestObjectResult(response);
        }
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                var errors = new Dictionary<string, string[]>();

                foreach (var keyModelStatePair in context.ModelState)
                {
                    var key = keyModelStatePair.Key;
                    var errorsArray = keyModelStatePair.Value.Errors.Select(error => 
                        string.IsNullOrEmpty(error.ErrorMessage) ? "Validation error occurred" : error.ErrorMessage
                    ).ToArray();

                    if (errorsArray.Length > 0)
                    {
                        errors[key] = errorsArray;
                    }
                }

                var response = new ApiResponse<Dictionary<string, string[]>>
                {
                    Success = false,
                    Message = "Validation failed",
                    ErrorCode = 400,
                    Data = errors,
                    Timestamp = DateTime.Now
                };

                context.Result = new BadRequestObjectResult(response);
            }

            base.OnActionExecuting(context);
        }
    }

    public class ValidationHelper
    {
        public static (bool IsValid, List<string> Errors) ValidateModel(object model)
        {
            var validationContext = new ValidationContext(model);
            var validationResults = new List<ValidationResult>();
            var isValid = Validator.TryValidateObject(model, validationContext, validationResults, true);

            var errors = validationResults.Select(vr => vr.ErrorMessage).ToList();

            return (isValid, errors);
        }

        public static (bool IsValid, List<string> Errors) ValidateDictionary(Dictionary<string, object> data, Dictionary<string, Type> expectedTypes)
        {
            var errors = new List<string>();
            var isValid = true;

            foreach (var kvp in expectedTypes)
            {
                if (!data.ContainsKey(kvp.Key))
                {
                    errors.Add($"Missing required field: {kvp.Key}");
                    isValid = false;
                    continue;
                }

                var value = data[kvp.Key];
                var expectedType = kvp.Value;

                if (value == null)
                {
                    if (expectedType == typeof(string))
                    {
                        errors.Add($"Field {kvp.Key} cannot be empty");
                        isValid = false;
                    }
                    continue;
                }

                if (!expectedType.IsAssignableFrom(value.GetType()))
                {
                    errors.Add($"Field {kvp.Key} must be of type {expectedType.Name}, got {value.GetType().Name}");
                    isValid = false;
                }
            }

            return (isValid, errors);
        }
    }
}