using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
using MCPForUnity.Editor.Helpers;

namespace MCPForUnity.Editor.Tools
{
    /// <summary>
    /// Handles procedural texture generation operations.
    /// Supports patterns (checkerboard, stripes, dots, grid, brick),
    /// gradients, noise, and direct pixel manipulation.
    /// </summary>
    [McpForUnityTool("manage_texture", AutoRegister = false, Group = "vfx")]
    public static class ManageTexture
    {
        private const int MaxTextureDimension = 1024;
        private const int MaxTexturePixels = 1024 * 1024;
        private const int MaxNoiseWork = 4000000;
        private static readonly List<string> ValidActions = new List<string>
        {
            "create",
            "modify",
            "delete",
            "create_sprite",
            "apply_pattern",
            "apply_gradient",
            "apply_noise",
            "set_import_settings"
        };

        private static ErrorResponse ValidateDimensions(int width, int height, List<string> warnings)
        {
            if (width <= 0 || height <= 0)
                return new ErrorResponse($"Invalid dimensions: {width}x{height}. Must be positive.");
            if (width > MaxTextureDimension || height > MaxTextureDimension)
                warnings.Add($"Dimensions exceed recommended max {MaxTextureDimension} per side (got {width}x{height}).");
            long totalPixels = (long)width * height;
            if (totalPixels > MaxTexturePixels)
                warnings.Add($"Total pixels exceed recommended max {MaxTexturePixels} (got {width}x{height}).");
            return null;
        }


        public static object HandleCommand(JObject @params)
        {
            string action = @params["action"]?.ToString()?.ToLowerInvariant();
            if (string.IsNullOrEmpty(action))
            {
                return new ErrorResponse("Action parameter is required.");
            }

            if (!ValidActions.Contains(action))
            {
                string validActionsList = string.Join(", ", ValidActions);
                return new ErrorResponse(
                    $"Unknown action: '{action}'. Valid actions are: {validActionsList}"
                );
            }

            string path = @params["path"]?.ToString();

            try
            {
                switch (action)
                {
                    case "create":
                    case "create_sprite":
                        return CreateTexture(@params, action == "create_sprite");
                    case "modify":
                        return ModifyTexture(@params);
                    case "delete":
                        return DeleteTexture(path);
                    case "apply_pattern":
                        return ApplyPattern(@params);
                    case "apply_gradient":
                        return ApplyGradient(@params);
                    case "apply_noise":
                        return ApplyNoise(@params);
                    case "set_import_settings":
                        return SetImportSettings(@params);
                    default:
                        return new ErrorResponse($"Unknown action: '{action}'");
                }
            }
            catch (Exception e)
            {
                McpLog.Error($"[ManageTexture] Action '{action}' failed: {e}");
                return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
            }
        }

        // --- Action Implementations ---

        private static object CreateTexture(JObject @params, bool asSprite)
        {
            string path = @params["path"]?.ToString();
            if (string.IsNullOrEmpty(path))
                return new ErrorResponse("'path' is required for create.");

            string imagePath = @params["imagePath"]?.ToString();
            bool hasImage = !string.IsNullOrEmpty(imagePath);

            int width = @params["width"]?.ToObject<int>() ?? 64;
            int height = @params["height"]?.ToObject<int>() ?? 64;
            List<string> warnings = new List<string>();

            // Validate dimensions
            if (!hasImage)
            {
                var dimensionError = ValidateDimensions(width, height, warnings);
                if (dimensionError != null)
                    return dimensionError;
            }

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            EnsureDirectoryExists(fullPath);

            try
            {
                var fillColorToken = @params["fillColor"];
                var patternToken = @params["pattern"];
                var pixelsToken = @params["pixels"];

                if (hasImage && (fillColorToken != null || patternToken != null || pixelsToken != null))
                {
                    return new ErrorResponse("imagePath cannot be combined with fillColor, pattern, or pixels.");
                }

                int patternSize = 8;
                if (!hasImage && patternToken != null)
                {
                    patternSize = @params["patternSize"]?.ToObject<int>() ?? 8;
                    if (patternSize <= 0)
                        return new ErrorResponse("patternSize must be greater than 0.");
                }

                Texture2D texture;
                if (hasImage)
                {
                    string resolvedImagePath = ResolveImagePath(imagePath);
                    if (!File.Exists(resolvedImagePath))
                        return new ErrorResponse($"Image file not found at '{imagePath}'.");

                    byte[] imageBytes = File.ReadAllBytes(resolvedImagePath);
                    texture = new Texture2D(2, 2, TextureFormat.RGBA32, false);
                    if (!texture.LoadImage(imageBytes))
                    {
                        UnityEngine.Object.DestroyImmediate(texture);
                        return new ErrorResponse($"Failed to load image from '{imagePath}'.");
                    }

                    width = texture.width;
                    height = texture.height;
                    var imageDimensionError = ValidateDimensions(width, height, warnings);
                    if (imageDimensionError != null)
                    {
                        UnityEngine.Object.DestroyImmediate(texture);
                        return imageDimensionError;
                    }
                }
                else
                {
                    texture = new Texture2D(width, height, TextureFormat.RGBA32, false);

                    // Check for fill color
                    if (fillColorToken != null && fillColorToken.Type == JTokenType.Array)
                    {
                        Color32 fillColor = TextureOps.ParseColor32(fillColorToken as JArray);
                        TextureOps.FillTexture(texture, fillColor);
                    }

                    // Check for pattern
                    if (patternToken != null)
                    {
                        string pattern = patternToken.ToString();
                        var palette = TextureOps.ParsePalette(@params["palette"] as JArray);
                        ApplyPatternToTexture(texture, pattern, palette, patternSize);
                    }

                    // Check for direct pixel data
                    if (pixelsToken != null)
                    {
                        TextureOps.ApplyPixelData(texture, pixelsToken, width, height);
                    }

                    // If nothing specified, create transparent texture
                    if (fillColorToken == null && patternToken == null && pixelsToken == null)
                    {
                        TextureOps.FillTexture(texture, new Color32(0, 0, 0, 0));
                    }
                }

                texture.Apply();

                // Save to disk
                byte[] imageData = TextureOps.EncodeTexture(texture, fullPath);
                if (imageData == null || imageData.Length == 0)
                {
                    UnityEngine.Object.DestroyImmediate(texture);
                    return new ErrorResponse($"Failed to encode texture for '{fullPath}'");
                }
                File.WriteAllBytes(GetAbsolutePath(fullPath), imageData);

                AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);

                // Configure texture importer settings if provided
                JToken importSettingsToken = @params["importSettings"];
                JToken spriteSettingsToken = @params["spriteSettings"];

                if (importSettingsToken != null)
                {
                    ConfigureTextureImporter(fullPath, importSettingsToken);
                }
                else if (asSprite || spriteSettingsToken != null)
                {
                    // Legacy sprite configuration
                    ConfigureAsSprite(fullPath, spriteSettingsToken);
                }

                // Clean up memory
                UnityEngine.Object.DestroyImmediate(texture);
                foreach (var warning in warnings)
                {
                    McpLog.Warn($"[ManageTexture] {warning}");
                }

                return new SuccessResponse(
                    $"Texture created at '{fullPath}' ({width}x{height})" + (asSprite ? " as sprite" : ""),
                    new
                    {
                        path = fullPath,
                        width,
                        height,
                        asSprite = asSprite || spriteSettingsToken != null || (importSettingsToken?["textureType"]?.ToString() == "Sprite"),
                        warnings = warnings.Count > 0 ? warnings : null
                    }
                );
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Failed to create texture: {e.Message}");
            }
        }

        private static object ModifyTexture(JObject @params)
        {
            string path = @params["path"]?.ToString();
            if (string.IsNullOrEmpty(path))
                return new ErrorResponse("'path' is required for modify.");

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            if (!AssetExists(fullPath))
                return new ErrorResponse($"Texture not found at path: {fullPath}");

            try
            {
                var setPixelsToken = @params["setPixels"] as JObject;
                bool hasImportSettings = HasImportSettingsParams(@params);

                // Validate import settings before any writes
                if (hasImportSettings)
                {
                    var validationError = ValidateImportSettingsParams(@params);
                    if (validationError != null) return validationError;
                }

                // Fast path: only import settings, no pixel changes
                if (setPixelsToken == null && hasImportSettings)
                {
                    var error = ApplyImportSettingsParams(fullPath, @params);
                    if (error != null) return error;
                    return new SuccessResponse($"Texture modified: {fullPath}");
                }

                // Pixel modification path
                if (setPixelsToken != null)
                {
                    Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(fullPath);
                    if (texture == null)
                        return new ErrorResponse($"Failed to load texture at path: {fullPath}");

                    string absolutePath = GetAbsolutePath(fullPath);
                    byte[] fileData = File.ReadAllBytes(absolutePath);
                    Texture2D editableTexture = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
                    editableTexture.LoadImage(fileData);

                    int x = setPixelsToken["x"]?.ToObject<int>() ?? 0;
                    int y = setPixelsToken["y"]?.ToObject<int>() ?? 0;
                    int w = setPixelsToken["width"]?.ToObject<int>() ?? 1;
                    int h = setPixelsToken["height"]?.ToObject<int>() ?? 1;

                    if (w <= 0 || h <= 0)
                    {
                        UnityEngine.Object.DestroyImmediate(editableTexture);
                        return new ErrorResponse("setPixels width and height must be positive.");
                    }

                    var pixelsToken = setPixelsToken["pixels"];
                    var colorToken = setPixelsToken["color"];

                    if (pixelsToken != null)
                    {
                        TextureOps.ApplyPixelDataToRegion(editableTexture, pixelsToken, x, y, w, h);
                    }
                    else if (colorToken != null)
                    {
                        Color32 color = TextureOps.ParseColor32(colorToken as JArray);
                        int startX = Mathf.Max(0, x);
                        int startY = Mathf.Max(0, y);
                        int endX = Mathf.Min(x + w, editableTexture.width);
                        int endY = Mathf.Min(y + h, editableTexture.height);

                        for (int py = startY; py < endY; py++)
                        {
                            for (int px = startX; px < endX; px++)
                            {
                                editableTexture.SetPixel(px, py, color);
                            }
                        }
                    }
                    else
                    {
                        UnityEngine.Object.DestroyImmediate(editableTexture);
                        return new ErrorResponse("setPixels requires 'color' or 'pixels'.");
                    }

                    editableTexture.Apply();

                    byte[] imageData = TextureOps.EncodeTexture(editableTexture, fullPath);
                    if (imageData == null || imageData.Length == 0)
                    {
                        UnityEngine.Object.DestroyImmediate(editableTexture);
                        return new ErrorResponse($"Failed to encode texture for '{fullPath}'");
                    }
                    File.WriteAllBytes(absolutePath, imageData);
                    AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);
                    UnityEngine.Object.DestroyImmediate(editableTexture);
                }

                if (hasImportSettings)
                {
                    var importError = ApplyImportSettingsParams(fullPath, @params);
                    if (importError != null) return importError;
                }

                return new SuccessResponse($"Texture modified: {fullPath}");
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Failed to modify texture: {e.Message}");
            }
        }

        private static object DeleteTexture(string path)
        {
            if (string.IsNullOrEmpty(path))
                return new ErrorResponse("'path' is required for delete.");

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            if (!AssetExists(fullPath))
                return new ErrorResponse($"Texture not found at path: {fullPath}");

            try
            {
                bool success = AssetDatabase.DeleteAsset(fullPath);
                if (success)
                    return new SuccessResponse($"Texture deleted: {fullPath}");
                else
                    return new ErrorResponse($"Failed to delete texture: {fullPath}");
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Error deleting texture: {e.Message}");
            }
        }

        private static object ApplyPattern(JObject @params)
        {
            // Reuse CreateTexture with pattern
            return CreateTexture(@params, false);
        }

        private static object ApplyGradient(JObject @params)
        {
            string path = @params["path"]?.ToString();
            if (string.IsNullOrEmpty(path))
                return new ErrorResponse("'path' is required for apply_gradient.");

            int width = @params["width"]?.ToObject<int>() ?? 64;
            int height = @params["height"]?.ToObject<int>() ?? 64;
            List<string> warnings = new List<string>();
            var dimensionError = ValidateDimensions(width, height, warnings);
            if (dimensionError != null)
                return dimensionError;
            string gradientType = @params["gradientType"]?.ToString() ?? "linear";
            float angle = @params["gradientAngle"]?.ToObject<float>() ?? 0f;

            var palette = TextureOps.ParsePalette(@params["palette"] as JArray);
            if (palette == null || palette.Count < 2)
            {
                // Default gradient palette
                palette = new List<Color32> { new Color32(0, 0, 0, 255), new Color32(255, 255, 255, 255) };
            }

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            EnsureDirectoryExists(fullPath);

            Texture2D texture = null;
            try
            {
                texture = new Texture2D(width, height, TextureFormat.RGBA32, false);

                if (gradientType == "radial")
                {
                    ApplyRadialGradient(texture, palette);
                }
                else
                {
                    ApplyLinearGradient(texture, palette, angle);
                }

                texture.Apply();

                byte[] imageData = TextureOps.EncodeTexture(texture, fullPath);
                if (imageData == null || imageData.Length == 0)
                {
                    return new ErrorResponse($"Failed to encode texture for '{fullPath}'");
                }
                File.WriteAllBytes(GetAbsolutePath(fullPath), imageData);

                AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);

                // Configure as sprite if requested
                JToken spriteSettingsToken = @params["spriteSettings"];
                if (spriteSettingsToken != null)
                {
                    ConfigureAsSprite(fullPath, spriteSettingsToken);
                }

                foreach (var warning in warnings)
                {
                    McpLog.Warn($"[ManageTexture] {warning}");
                }

                return new SuccessResponse(
                    $"Gradient texture created at '{fullPath}' ({width}x{height})",
                    new
                    {
                        path = fullPath,
                        width,
                        height,
                        gradientType,
                        warnings = warnings.Count > 0 ? warnings : null
                    }
                );
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Failed to create gradient texture: {e.Message}");
            }
            finally
            {
                if (texture != null)
                    UnityEngine.Object.DestroyImmediate(texture);
            }
        }

        private static object ApplyNoise(JObject @params)
        {
            string path = @params["path"]?.ToString();
            if (string.IsNullOrEmpty(path))
                return new ErrorResponse("'path' is required for apply_noise.");

            int width = @params["width"]?.ToObject<int>() ?? 64;
            int height = @params["height"]?.ToObject<int>() ?? 64;
            List<string> warnings = new List<string>();
            var dimensionError = ValidateDimensions(width, height, warnings);
            if (dimensionError != null)
                return dimensionError;
            float scale = @params["noiseScale"]?.ToObject<float>() ?? 0.1f;
            int octaves = @params["octaves"]?.ToObject<int>() ?? 1;
            if (octaves <= 0)
                return new ErrorResponse("octaves must be greater than 0.");
            long noiseWork = (long)width * height * octaves;
            if (noiseWork > MaxNoiseWork)
                warnings.Add($"Noise workload exceeds recommended max {MaxNoiseWork} (got {width}x{height}x{octaves}).");

            var palette = TextureOps.ParsePalette(@params["palette"] as JArray);
            if (palette == null || palette.Count < 2)
            {
                palette = new List<Color32> { new Color32(0, 0, 0, 255), new Color32(255, 255, 255, 255) };
            }

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            EnsureDirectoryExists(fullPath);

            Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
            try
            {
                ApplyPerlinNoise(texture, palette, scale, octaves);

                texture.Apply();

                byte[] imageData = TextureOps.EncodeTexture(texture, fullPath);
                if (imageData == null || imageData.Length == 0)
                {
                    return new ErrorResponse($"Failed to encode texture for '{fullPath}'");
                }
                File.WriteAllBytes(GetAbsolutePath(fullPath), imageData);

                AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);

                // Configure as sprite if requested
                JToken spriteSettingsToken = @params["spriteSettings"];
                if (spriteSettingsToken != null)
                {
                    ConfigureAsSprite(fullPath, spriteSettingsToken);
                }

                foreach (var warning in warnings)
                {
                    McpLog.Warn($"[ManageTexture] {warning}");
                }

                return new SuccessResponse(
                    $"Noise texture created at '{fullPath}' ({width}x{height})",
                    new
                    {
                        path = fullPath,
                        width,
                        height,
                        noiseScale = scale,
                        octaves,
                        warnings = warnings.Count > 0 ? warnings : null
                    }
                );
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Failed to create noise texture: {e.Message}");
            }
            finally
            {
                if (texture != null)
                    UnityEngine.Object.DestroyImmediate(texture);
            }
        }

        // --- Pattern Helpers ---

        private static void ApplyPatternToTexture(Texture2D texture, string pattern, List<Color32> palette, int patternSize)
        {
            if (palette == null || palette.Count == 0)
            {
                palette = new List<Color32> { new Color32(255, 255, 255, 255), new Color32(0, 0, 0, 255) };
            }

            int width = texture.width;
            int height = texture.height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Color32 color = GetPatternColor(x, y, pattern, palette, patternSize, width, height);
                    texture.SetPixel(x, y, color);
                }
            }
        }

        private static Color32 GetPatternColor(int x, int y, string pattern, List<Color32> palette, int size, int width, int height)
        {
            int colorIndex = 0;

            switch (pattern.ToLower())
            {
                case "checkerboard":
                    colorIndex = ((x / size) + (y / size)) % 2;
                    break;

                case "stripes":
                case "stripes_v":
                    colorIndex = (x / size) % palette.Count;
                    break;

                case "stripes_h":
                    colorIndex = (y / size) % palette.Count;
                    break;

                case "stripes_diag":
                    colorIndex = ((x + y) / size) % palette.Count;
                    break;

                case "dots":
                    int cx = (x % (size * 2)) - size;
                    int cy = (y % (size * 2)) - size;
                    bool inDot = (cx * cx + cy * cy) < (size * size / 4);
                    colorIndex = inDot ? 1 : 0;
                    break;

                case "grid":
                    bool onGridLine = (x % size == 0) || (y % size == 0);
                    colorIndex = onGridLine ? 1 : 0;
                    break;

                case "brick":
                    int row = y / size;
                    int offset = (row % 2) * (size / 2);
                    bool onBorder = ((x + offset) % size == 0) || (y % size == 0);
                    colorIndex = onBorder ? 1 : 0;
                    break;

                default:
                    colorIndex = 0;
                    break;
            }

            return palette[Mathf.Clamp(colorIndex, 0, palette.Count - 1)];
        }

        // --- Gradient Helpers ---

        private static void ApplyLinearGradient(Texture2D texture, List<Color32> palette, float angle)
        {
            int width = texture.width;
            int height = texture.height;
            float radians = angle * Mathf.Deg2Rad;
            Vector2 dir = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians));
            float denomX = Mathf.Max(1, width - 1);
            float denomY = Mathf.Max(1, height - 1);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    float nx = x / denomX;
                    float ny = y / denomY;
                    float t = Vector2.Dot(new Vector2(nx, ny), dir);
                    t = Mathf.Clamp01((t + 1f) / 2f);

                    Color32 color = LerpPalette(palette, t);
                    texture.SetPixel(x, y, color);
                }
            }
        }

        private static void ApplyRadialGradient(Texture2D texture, List<Color32> palette)
        {
            int width = texture.width;
            int height = texture.height;
            float cx = width / 2f;
            float cy = height / 2f;
            float maxDist = Mathf.Sqrt(cx * cx + cy * cy);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    float dx = x - cx;
                    float dy = y - cy;
                    float dist = Mathf.Sqrt(dx * dx + dy * dy);
                    float t = Mathf.Clamp01(dist / maxDist);

                    Color32 color = LerpPalette(palette, t);
                    texture.SetPixel(x, y, color);
                }
            }
        }

        private static Color32 LerpPalette(List<Color32> palette, float t)
        {
            if (palette.Count == 1) return palette[0];
            if (t <= 0) return palette[0];
            if (t >= 1) return palette[palette.Count - 1];

            float scaledT = t * (palette.Count - 1);
            int index = Mathf.FloorToInt(scaledT);
            float localT = scaledT - index;

            if (index >= palette.Count - 1)
                return palette[palette.Count - 1];

            Color c1 = palette[index];
            Color c2 = palette[index + 1];
            return Color.Lerp(c1, c2, localT);
        }

        // --- Noise Helpers ---

        private static void ApplyPerlinNoise(Texture2D texture, List<Color32> palette, float scale, int octaves)
        {
            int width = texture.width;
            int height = texture.height;

            // Random offset to ensure different patterns
            float offsetX = UnityEngine.Random.Range(0f, 1000f);
            float offsetY = UnityEngine.Random.Range(0f, 1000f);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    float noiseValue = 0f;
                    float amplitude = 1f;
                    float frequency = 1f;
                    float maxValue = 0f;

                    for (int o = 0; o < octaves; o++)
                    {
                        float sampleX = (x + offsetX) * scale * frequency;
                        float sampleY = (y + offsetY) * scale * frequency;
                        noiseValue += Mathf.PerlinNoise(sampleX, sampleY) * amplitude;
                        maxValue += amplitude;
                        amplitude *= 0.5f;
                        frequency *= 2f;
                    }

                    float t = Mathf.Clamp01(noiseValue / maxValue);
                    Color32 color = LerpPalette(palette, t);
                    texture.SetPixel(x, y, color);
                }
            }
        }

        private static bool HasImportSettingsParams(JObject @params)
        {
            JToken importSettingsToken = @params["import_settings"] ?? @params["importSettings"];
            JToken asSpriteToken = @params["as_sprite"] ?? @params["spriteSettings"];

            bool hasImportSettings = importSettingsToken is JObject importObject && importObject.HasValues;
            bool hasSpriteSettings = (asSpriteToken is JObject spriteObject && spriteObject.HasValues)
                || (asSpriteToken?.Type == JTokenType.Boolean && asSpriteToken.ToObject<bool>());

            return hasImportSettings || hasSpriteSettings;
        }

        private static object ValidateImportSettingsParams(JObject @params)
        {
            JToken importSettingsToken = @params["import_settings"] ?? @params["importSettings"];
            JToken asSpriteToken = @params["as_sprite"] ?? @params["spriteSettings"];

            if (importSettingsToken != null && asSpriteToken != null)
            {
                return new ErrorResponse("Cannot specify both 'import_settings' and 'as_sprite'.");
            }
            return null;
        }

        private static object ApplyImportSettingsParams(string fullPath, JObject @params)
        {
            JToken importSettingsToken = @params["import_settings"] ?? @params["importSettings"];
            JToken asSpriteToken = @params["as_sprite"] ?? @params["spriteSettings"];

            if (importSettingsToken != null && asSpriteToken != null)
            {
                return new ErrorResponse(
                    "Cannot specify both 'import_settings' and 'as_sprite'. " +
                    "Use 'import_settings' with textureType='Sprite' instead.");
            }

            if (importSettingsToken != null)
            {
                ConfigureTextureImporter(fullPath, importSettingsToken);
            }
            else if (asSpriteToken != null &&
                     (asSpriteToken.Type == JTokenType.Boolean ? asSpriteToken.ToObject<bool>() : true))
            {
                ConfigureAsSprite(fullPath, asSpriteToken.Type == JTokenType.Object ? asSpriteToken : null);
            }

            return null;
        }

        private static object SetImportSettings(JObject @params)
        {
            var toolParams = new MCPForUnity.Editor.Helpers.ToolParams(@params);
            var pathResult = toolParams.GetRequired("path", "'path' is required for set_import_settings.");
            if (!pathResult.IsSuccess)
                return new ErrorResponse(pathResult.ErrorMessage);
            string path = pathResult.Value;

            string fullPath = AssetPathUtility.SanitizeAssetPath(path);
            if (!AssetExists(fullPath))
                return new ErrorResponse($"Texture not found at path: {fullPath}");

            try
            {
                if (!HasImportSettingsParams(@params))
                {
                    return new ErrorResponse("Either 'import_settings' or 'as_sprite' is required.");
                }

                var error = ApplyImportSettingsParams(fullPath, @params);
                if (error != null) return error;

                return new SuccessResponse($"Import settings updated for: {fullPath}", new { path = fullPath });
            }
            catch (Exception e)
            {
                return new ErrorResponse($"Failed to set import settings: {e.Message}");
            }
        }

        private static void ConfigureAsSprite(string path, JToken spriteSettings)
        {
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            if (importer == null)
            {
                McpLog.Warn($"[ManageTexture] Could not get TextureImporter for {path}");
                return;
            }

            importer.textureType = TextureImporterType.Sprite;
            importer.spriteImportMode = SpriteImportMode.Single;

            if (spriteSettings != null && spriteSettings.Type == JTokenType.Object)
            {
                var settings = spriteSettings as JObject;

                // Pivot
                var pivotToken = settings["pivot"];
                if (pivotToken is JArray pivotArray && pivotArray.Count >= 2)
                {
                    importer.spritePivot = new Vector2(
                        pivotArray[0].ToObject<float>(),
                        pivotArray[1].ToObject<float>()
                    );
                }

                // Pixels per unit
                var ppuToken = settings["pixelsPerUnit"];
                if (ppuToken != null)
                {
                    importer.spritePixelsPerUnit = ppuToken.ToObject<float>();
                }
            }

            importer.SaveAndReimport();
        }

        private static void ConfigureTextureImporter(string path, JToken importSettings)
        {
            TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
            if (importer == null)
            {
                McpLog.Warn($"[ManageTexture] Could not get TextureImporter for {path}");
                return;
            }

            if (importSettings == null || importSettings.Type != JTokenType.Object)
            {
                return;
            }

            var settings = importSettings as JObject;

            // Texture Type
            var textureTypeToken = settings["textureType"];
            if (textureTypeToken != null)
            {
                string typeStr = textureTypeToken.ToString();
                if (TryParseEnum<TextureImporterType>(typeStr, out var textureType))
                {
                    importer.textureType = textureType;
                }
            }

            // Texture Shape
            var textureShapeToken = settings["textureShape"];
            if (textureShapeToken != null)
            {
                string shapeStr = textureShapeToken.ToString();
                if (TryParseEnum<TextureImporterShape>(shapeStr, out var textureShape))
                {
                    importer.textureShape = textureShape;
                }
            }

            // sRGB
            var srgbToken = settings["sRGBTexture"];
            if (srgbToken != null)
            {
                importer.sRGBTexture = srgbToken.ToObject<bool>();
            }

            // Alpha Source
            var alphaSourceToken = settings["alphaSource"];
            if (alphaSourceToken != null)
            {
                string alphaStr = alphaSourceToken.ToString();
                if (TryParseEnum<TextureImporterAlphaSource>(alphaStr, out var alphaSource))
                {
                    importer.alphaSource = alphaSource;
                }
            }

            // Alpha Is Transparency
            var alphaTransToken = settings["alphaIsTransparency"];
            if (alphaTransToken != null)
            {
                importer.alphaIsTransparency = alphaTransToken.ToObject<bool>();
            }

            // Readable
            var readableToken = settings["isReadable"];
            if (readableToken != null)
            {
                importer.isReadable = readableToken.ToObject<bool>();
            }

            // Mipmaps
            var mipmapToken = settings["mipmapEnabled"];
            if (mipmapToken != null)
            {
                importer.mipmapEnabled = mipmapToken.ToObject<bool>();
            }

            // Mipmap Filter
            var mipmapFilterToken = settings["mipmapFilter"];
            if (mipmapFilterToken != null)
            {
                string filterStr = mipmapFilterToken.ToString();
                if (TryParseEnum<TextureImporterMipFilter>(filterStr, out var mipmapFilter))
                {
                    importer.mipmapFilter = mipmapFilter;
                }
            }

            // Wrap Mode
            var wrapModeToken = settings["wrapMode"];
            if (wrapModeToken != null)
            {
                string wrapStr = wrapModeToken.ToString();
                if (TryParseEnum<TextureWrapMode>(wrapStr, out var wrapMode))
                {
                    importer.wrapMode = wrapMode;
                }
            }

            // Wrap Mode U
            var wrapModeUToken = settings["wrapModeU"];
            if (wrapModeUToken != null)
            {
                string wrapStr = wrapModeUToken.ToString();
                if (TryParseEnum<TextureWrapMode>(wrapStr, out var wrapMode))
                {
                    importer.wrapModeU = wrapMode;
                }
            }

            // Wrap Mode V
            var wrapModeVToken = settings["wrapModeV"];
            if (wrapModeVToken != null)
            {
                string wrapStr = wrapModeVToken.ToString();
                if (TryParseEnum<TextureWrapMode>(wrapStr, out var wrapMode))
                {
                    importer.wrapModeV = wrapMode;
                }
            }

            // Filter Mode
            var filterModeToken = settings["filterMode"];
            if (filterModeToken != null)
            {
                string filterStr = filterModeToken.ToString();
                if (TryParseEnum<FilterMode>(filterStr, out var filterMode))
                {
                    importer.filterMode = filterMode;
                }
            }

            // Aniso Level
            var anisoToken = settings["anisoLevel"];
            if (anisoToken != null)
            {
                importer.anisoLevel = anisoToken.ToObject<int>();
            }

            // Max Texture Size
            var maxSizeToken = settings["maxTextureSize"];
            if (maxSizeToken != null)
            {
                importer.maxTextureSize = maxSizeToken.ToObject<int>();
            }

            // Compression
            var compressionToken = settings["textureCompression"];
            if (compressionToken != null)
            {
                string compStr = compressionToken.ToString();
                if (TryParseEnum<TextureImporterCompression>(compStr, out var compression))
                {
                    importer.textureCompression = compression;
                }
            }

            // Crunched Compression
            var crunchedToken = settings["crunchedCompression"];
            if (crunchedToken != null)
            {
                importer.crunchedCompression = crunchedToken.ToObject<bool>();
            }

            // Compression Quality
            var qualityToken = settings["compressionQuality"];
            if (qualityToken != null)
            {
                importer.compressionQuality = qualityToken.ToObject<int>();
            }

            // --- Sprite-specific settings ---

            // Sprite Import Mode
            var spriteModeToken = settings["spriteImportMode"];
            if (spriteModeToken != null)
            {
                string modeStr = spriteModeToken.ToString();
                if (TryParseEnum<SpriteImportMode>(modeStr, out var spriteMode))
                {
                    importer.spriteImportMode = spriteMode;
                }
            }

            // Sprite Pixels Per Unit
            var ppuToken = settings["spritePixelsPerUnit"];
            if (ppuToken != null)
            {
                importer.spritePixelsPerUnit = ppuToken.ToObject<float>();
            }

            // Sprite Pivot
            var pivotToken = settings["spritePivot"];
            if (pivotToken is JArray pivotArray && pivotArray.Count >= 2)
            {
                importer.spritePivot = new Vector2(
                    pivotArray[0].ToObject<float>(),
                    pivotArray[1].ToObject<float>()
                );
            }

            // Apply sprite settings using TextureImporterSettings helper
            TextureImporterSettings importerSettings = new TextureImporterSettings();
            importer.ReadTextureSettings(importerSettings);

            bool settingsChanged = false;

            // Sprite Mesh Type
            var meshTypeToken = settings["spriteMeshType"];
            if (meshTypeToken != null)
            {
                string meshStr = meshTypeToken.ToString();
                if (TryParseEnum<SpriteMeshType>(meshStr, out var meshType))
                {
                    importerSettings.spriteMeshType = meshType;
                    settingsChanged = true;
                }
            }

            // Sprite Extrude
            var extrudeToken = settings["spriteExtrude"];
            if (extrudeToken != null)
            {
                importerSettings.spriteExtrude = (uint)extrudeToken.ToObject<int>();
                settingsChanged = true;
            }
            
            if (settingsChanged)
            {
                importer.SetTextureSettings(importerSettings);
            }

            importer.SaveAndReimport();
        }

        private static bool TryParseEnum<T>(string value, out T result) where T : struct
        {
            // Try exact match first
            if (Enum.TryParse<T>(value, true, out result))
            {
                return true;
            }

            // Try without common prefixes/suffixes
            string cleanValue = value.Replace("_", "").Replace("-", "");
            if (Enum.TryParse<T>(cleanValue, true, out result))
            {
                return true;
            }

            result = default;
            return false;
        }

        private static bool AssetExists(string path)
        {
            return !string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(path));
        }

        private static void EnsureDirectoryExists(string assetPath)
        {
            string directory = Path.GetDirectoryName(assetPath);
            if (!string.IsNullOrEmpty(directory) && !Directory.Exists(GetAbsolutePath(directory)))
            {
                Directory.CreateDirectory(GetAbsolutePath(directory));
                AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
            }
        }

        private static string GetAbsolutePath(string assetPath)
        {
            return Path.Combine(Directory.GetCurrentDirectory(), assetPath);
        }

        private static string ResolveImagePath(string imagePath)
        {
            if (Path.IsPathRooted(imagePath))
                return imagePath;

            return Path.Combine(Directory.GetCurrentDirectory(), imagePath);
        }
    }
}
