using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using CustomAssetBundleSystem;

/// <summary>
/// Unity Editor tool to build AssetBundles and generate catalog.json
/// Menu: Tools > AssetBundles > Build for Android
/// </summary>
public class AssetBundleBuilder : EditorWindow
{
    private static string outputPath = "ServerData/AssetBundles/Android";
    private static BuildTarget buildTarget = BuildTarget.Android;

    [MenuItem("Tools/AssetBundles/Build for Android")]
    public static void BuildAssetBundles()
    {
        Debug.Log("=== Custom AssetBundle Builder ===");

        // Create output directory
        string fullOutputPath = Path.Combine(Application.dataPath, "..", outputPath);
        if (!Directory.Exists(fullOutputPath))
        {
            Directory.CreateDirectory(fullOutputPath);
            Debug.Log($"Created output directory: {fullOutputPath}");
        }

        // Build options
        BuildAssetBundleOptions options = BuildAssetBundleOptions.ChunkBasedCompression |
                                          BuildAssetBundleOptions.StrictMode;

        // Build the bundles
        Debug.Log($"Building AssetBundles to: {fullOutputPath}");
        Debug.Log($"Target platform: {buildTarget}");

        AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(
            fullOutputPath,
            options,
            buildTarget
        );

        if (manifest == null)
        {
            Debug.LogError("✗ AssetBundle build failed!");
            EditorUtility.DisplayDialog("Build Failed", "AssetBundle build failed! Check console for errors.", "OK");
            return;
        }

        Debug.Log("✓ AssetBundles built successfully!");

        // Generate the JSON catalog
        GenerateCatalog(fullOutputPath, manifest);

        Debug.Log("=== Build Complete ===");
        EditorUtility.DisplayDialog("Build Complete", 
            $"AssetBundles built successfully!\n\nOutput: {fullOutputPath}\n\nNext: Upload to VPS", 
            "OK");
    }

    /// <summary>
    /// Generate catalog.json from built AssetBundles
    /// </summary>
    private static void GenerateCatalog(string outputPath, AssetBundleManifest manifest)
    {
        Debug.Log("Generating catalog.json...");

        var catalog = new RemoteAssetCatalog
        {
            version = Application.version,
            timestamp = System.DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
            baseUrl = "https://assetbundle.uncaptured.co",
            bundles = new List<RemoteAssetCatalog.BundleEntry>()
        };

        // Get all bundle names
        string[] allBundles = manifest.GetAllAssetBundles();

        foreach (string bundleName in allBundles)
        {
            string bundlePath = Path.Combine(outputPath, bundleName);

            if (!File.Exists(bundlePath))
            {
                Debug.LogWarning($"Bundle file not found: {bundlePath}");
                continue;
            }

            // Get file info
            FileInfo fileInfo = new FileInfo(bundlePath);

            // Calculate hash
            string hash = CalculateMD5(bundlePath);

            // Get scenes in this bundle
            var scenePaths = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
            var sceneNames = new List<string>();

            foreach (var scenePath in scenePaths)
            {
                if (scenePath.EndsWith(".unity"))
                {
                    string sceneName = Path.GetFileNameWithoutExtension(scenePath);
                    sceneNames.Add(sceneName);
                }
            }

            // Get dependencies
            var dependencies = new List<string>();
            string[] bundleDeps = manifest.GetAllDependencies(bundleName);
            dependencies.AddRange(bundleDeps);

            // Create bundle entry
            var entry = new RemoteAssetCatalog.BundleEntry
            {
                bundleName = Path.GetFileNameWithoutExtension(bundleName),
                fileName = bundleName,
                hash = hash,
                size = fileInfo.Length,
                scenes = sceneNames,
                dependencies = dependencies
            };

            catalog.bundles.Add(entry);

            Debug.Log($"  ✓ Added bundle: {bundleName}");
            Debug.Log($"    - Size: {fileInfo.Length / 1024f / 1024f:F2} MB");
            Debug.Log($"    - Hash: {hash}");
            Debug.Log($"    - Scenes: {sceneNames.Count}");
            Debug.Log($"    - Dependencies: {dependencies.Count}");
        }

        // Save catalog as JSON
        string catalogPath = Path.Combine(outputPath, "catalog.json");
        string json = JsonUtility.ToJson(catalog, true);
        File.WriteAllText(catalogPath, json);

        Debug.Log($"✓ Catalog generated: {catalogPath}");
        Debug.Log($"  Total bundles: {catalog.bundles.Count}");
        Debug.Log($"  Catalog size: {json.Length / 1024f:F2} KB");

        // Also save a pretty-printed version for debugging
        string prettyPath = Path.Combine(outputPath, "catalog_readable.json");
        File.WriteAllText(prettyPath, json);
        Debug.Log($"✓ Readable catalog: {prettyPath}");
    }

    /// <summary>
    /// Calculate MD5 hash of a file
    /// </summary>
    private static string CalculateMD5(string filePath)
    {
        using (var md5 = MD5.Create())
        using (var stream = File.OpenRead(filePath))
        {
            byte[] hash = md5.ComputeHash(stream);
            StringBuilder sb = new StringBuilder();
            foreach (byte b in hash)
            {
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString();
        }
    }

    [MenuItem("Tools/AssetBundles/Open Output Folder")]
    public static void OpenOutputFolder()
    {
        string fullPath = Path.Combine(Application.dataPath, "..", outputPath);
        if (Directory.Exists(fullPath))
        {
            EditorUtility.RevealInFinder(fullPath);
        }
        else
        {
            Debug.LogWarning($"Output folder doesn't exist: {fullPath}");
        }
    }

    [MenuItem("Tools/AssetBundles/Clear Cache")]
    public static void ClearCache()
    {
        if (EditorUtility.DisplayDialog("Clear AssetBundle Cache?", 
            "This will delete all cached AssetBundles. Continue?", 
            "Yes", "Cancel"))
        {
            Caching.ClearCache();
            Debug.Log("✓ AssetBundle cache cleared");
        }
    }

    [MenuItem("Tools/AssetBundles/Settings")]
    public static void ShowSettings()
    {
        var window = GetWindow<AssetBundleBuilder>("AssetBundle Builder");
        window.Show();
    }

    // Editor Window GUI
    void OnGUI()
    {
        GUILayout.Label("Custom AssetBundle Builder", EditorStyles.boldLabel);
        GUILayout.Space(10);

        EditorGUILayout.HelpBox(
            "This tool builds AssetBundles and generates a JSON catalog for remote loading.\n\n" +
            "1. Mark your scenes/assets with AssetBundle names\n" +
            "2. Click 'Build for Android'\n" +
            "3. Upload ServerData/AssetBundles/Android/ to your VPS",
            MessageType.Info);

        GUILayout.Space(10);

        // Output path
        GUILayout.Label("Output Path:", EditorStyles.boldLabel);
        outputPath = EditorGUILayout.TextField(outputPath);

        GUILayout.Space(5);

        // Build target
        GUILayout.Label("Build Target:", EditorStyles.boldLabel);
        buildTarget = (BuildTarget)EditorGUILayout.EnumPopup(buildTarget);

        GUILayout.Space(10);

        // Build button
        if (GUILayout.Button("Build AssetBundles", GUILayout.Height(40)))
        {
            BuildAssetBundles();
        }

        GUILayout.Space(5);

        // Utility buttons
        using (new EditorGUILayout.HorizontalScope())
        {
            if (GUILayout.Button("Open Output Folder"))
            {
                OpenOutputFolder();
            }

            if (GUILayout.Button("Clear Cache"))
            {
                ClearCache();
            }
        }

        GUILayout.Space(20);

        // Info section
        GUILayout.Label("Current Settings:", EditorStyles.boldLabel);
        EditorGUILayout.LabelField("Unity Version:", Application.unityVersion);
        EditorGUILayout.LabelField("App Version:", Application.version);
        EditorGUILayout.LabelField("Company:", Application.companyName);

        GUILayout.Space(10);

        // Quick guide
        if (GUILayout.Button("Show Quick Guide"))
        {
            ShowQuickGuide();
        }
    }

    private static void ShowQuickGuide()
    {
        EditorUtility.DisplayDialog("AssetBundle Quick Guide",
            "STEP 1: Mark Assets for Bundling\n" +
            "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
            "• Select your Game scene in Project window\n" +
            "• In Inspector, find 'AssetBundle' dropdown (bottom)\n" +
            "• Select 'New...' and name it 'gamescene'\n\n" +

            "STEP 2: Build AssetBundles\n" +
            "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
            "• Tools → AssetBundles → Build for Android\n" +
            "• Wait for build to complete\n" +
            "• Files created in ServerData/AssetBundles/Android/\n\n" +

            "STEP 3: Upload to VPS\n" +
            "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
            "• scp -r ServerData/AssetBundles/Android/* user@server:/var/www/AssetBundles/Android/\n\n" +

            "STEP 4: Update Your Code\n" +
            "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
            "• Replace Addressables calls with CustomAssetBundleSceneLoader\n" +
            "• Build APK and test!",
            "Got it!");
    }
}
