using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using Newtonsoft.Json;

namespace MD5Create
{
    public partial class MD5Create : Form
    {
        public MD5Create()
        {
            InitializeComponent();
            // Initialize progress bar
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;
            progressBar1.Value = 0;
            progressBar1.Step = 1;
        }

        private void Start_Button_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(Path1_Box.Text))
            {
                MessageBox.Show("请先选择目录!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (string.IsNullOrWhiteSpace(textBox1.Text))
            {
                MessageBox.Show("请输入版本号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // Reset progress bar
            progressBar1.Value = 0;

            GenerateMD5Json(Path1_Box.Text);
        }

        private void Choose1_Button_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.Description = "请选择文件夹";
            folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
            folderBrowserDialog1.ShowNewFolderButton = true;
            if (Path1_Box.Text.Length > 0) folderBrowserDialog1.SelectedPath = Path1_Box.Text;
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                Path1_Box.Text = folderBrowserDialog1.SelectedPath;
            }
        }

        private void Exit_Button_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        // 计算 MD5 的值
        private string MD5Generation(string filePath)
        {
            using (var md5 = MD5.Create())
            using (var stream = File.OpenRead(filePath))
            {
                byte[] hash = md5.ComputeHash(stream);
                return BitConverter.ToString(hash).Replace("-", "").ToLower();
            }
        }

        // 获取目录中文件总数(用于进度计算)
        private int GetTotalFileCount(string directoryPath, string excludeFolder)
        {
            int count = Directory.GetFiles(directoryPath).Length;

            foreach (var dir in Directory.GetDirectories(directoryPath))
            {
                if (dir.Equals(excludeFolder, StringComparison.OrdinalIgnoreCase))
                    continue;

                count += GetTotalFileCount(dir, excludeFolder);
            }
            return count;
        }

        // 生成目录结构的 json 表示
        private Dictionary<string, object> GenerateDirectoryJson(string directoryPath, string rootPath,
    int totalFiles, ref int processedFiles, string excludeFolder)
        {
            var result = new Dictionary<string, object>();

            // 处理当前目录文件
            foreach (var file in Directory.GetFiles(directoryPath))
            {
                string fileName = Path.GetFileName(file);
                result[fileName] = MD5Generation(file);

                // 更新进度条
                processedFiles++;
                int progress = (int)((double)processedFiles / totalFiles * 100);
                progressBar1.Invoke((MethodInvoker)(() =>
                {
                    progressBar1.Value = Math.Min(progress, progressBar1.Maximum);
                }));

                // 显示处理路径
                string relativePath = GetRelativePath(file, rootPath);
                Process_Box.Invoke((MethodInvoker)(() =>
                {
                    Process_Box.AppendText($".\\{relativePath}{Environment.NewLine}");
                }));
            }

            // 递归处理子目录(自动跳过排除文件夹)
            foreach (var dir in Directory.GetDirectories(directoryPath))
            {
                if (Path.GetFullPath(dir).Equals(Path.GetFullPath(excludeFolder), StringComparison.OrdinalIgnoreCase))
                    continue;

                string dirName = Path.GetFileName(dir);
                result[dirName] = GenerateDirectoryJson(dir, rootPath, totalFiles,
                                      ref processedFiles, excludeFolder);
            }

            return result;
        }

        // 获取相对路径
        private string GetRelativePath(string fullPath, string basePath)
        {
            if (!basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
                basePath += Path.DirectorySeparatorChar;

            Uri baseUri = new Uri(basePath);
            Uri fullUri = new Uri(fullPath);
            return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString()
                .Replace('/', Path.DirectorySeparatorChar));
        }

        // 生成 json 文件
        private void GenerateMD5Json(string rootDirectory)
        {
            if (!Directory.Exists(rootDirectory))
            {
                MessageBox.Show("指定的目录不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                Process_Box.Clear();
                progressBar1.Value = 0;
                Application.DoEvents(); // 让UI立即更新

                string md5FolderPath = Path.Combine(rootDirectory, "MD5");
                Directory.CreateDirectory(md5FolderPath);

                int totalFiles = GetTotalFileCount(rootDirectory, md5FolderPath);
                int processedFiles = 0;

                // 如果文件数量为0,直接设置进度为100%
                if (totalFiles == 0)
                {
                    progressBar1.Value = 100;
                    Process_Box.AppendText("没有找到任何文件\n");
                    return;
                }

                var directoryStructure = GenerateDirectoryJson(rootDirectory, rootDirectory, totalFiles, ref processedFiles, md5FolderPath);

                // 创建包含版本号的新结构
                var versionedStructure = new Dictionary<string, object>
                {
                    { "version", textBox1.Text.Trim() },
                    { "data", directoryStructure }
                };

                // 序列化和保存JSON
                string json = JsonConvert.SerializeObject(versionedStructure, Newtonsoft.Json.Formatting.Indented);
                string jsonMD5 = CalculateMD5FromString(json);
                string outputPath = Path.Combine(md5FolderPath, $"{jsonMD5}.json");
                File.WriteAllText(outputPath, json);

                // 最终更新
                progressBar1.Value = 100;
                Process_Box.AppendText($"\nmd5.json文件已生成在:{outputPath}\n");
                Process_Box.AppendText($"JSON内容MD5校验值:{jsonMD5}");
                Process_Box.ScrollToCaret();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"生成JSON文件时出错:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 计算字符串的MD5值
        private string CalculateMD5FromString(string input)
        {
            using (var md5 = MD5.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2")); // 使用小写十六进制格式
                }
                return sb.ToString();
            }
        }
    }
}