using System.Net.Http;
using System.Net;
using System.Web.Http;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System;

/////http://127.0.0.1:9981/api/file/browse

/// <summary>
/// 
/// </summary>
namespace WebApi
{
    /// <summary>
    /// 
    /// </summary>
    [RoutePrefix("api/file")]
    public class IFileController : ApiController
    {
        // 基础路径配置
        private readonly string _basePath = @"D:\项目文件";

        /// <summary>
        /// 请求DTO
        /// </summary>
        public class FileRequestDto
        {
            public string RelativePath { get; set; } = "";
        }

        /// <summary>
        /// 浏览文件或文件夹，前端传相对路径，返回文件夹内容或文件流（图片等可预览）
        /// </summary>
        [HttpPost]
        [Route("browse")]
        public IHttpActionResult BrowsePath([FromBody] FileRequestDto request)
        {
            try
            {
                if (request == null)
                    request = new FileRequestDto();

                if (string.IsNullOrEmpty(request.RelativePath) || request.RelativePath == "/")
                {
                    request.RelativePath = "";
                }

                string fullPath = Path.Combine(_basePath, request.RelativePath.Replace('/', Path.DirectorySeparatorChar));

                if (!IsPathSafe(fullPath))
                {
                    return Ok(new { success = false, message = "无效的路径" });
                }

                if (!Directory.Exists(fullPath) && !System.IO.File.Exists(fullPath))
                {
                    return Ok(new { success = false, message = "路径不存在" });
                }

                if (System.IO.File.Exists(fullPath))
                {
                    return GetFilePreview(fullPath, request.RelativePath);
                }

                if (Directory.Exists(fullPath))
                {
                    return GetDirectoryContents(fullPath, request.RelativePath);
                }

                return Ok(new { success = false, message = "路径不存在" });
            }
            catch (Exception ex)
            {
                return Ok(new { success = false, message = $"服务器错误: {ex.Message}" });
            }
        }

        /// <summary>
        /// 获取文件预览数据（图片/文本base64，前端可直接预览）
        /// </summary>
        private IHttpActionResult GetFilePreview(string fullPath, string relativePath)
        {
            try
            {
                var fileInfo = new FileInfo(fullPath);
                var extension = fileInfo.Extension.ToLowerInvariant();
                var previewable = IsPreviewableFile(extension);
                var contentType = GetContentType(fileInfo.Name);

                bool tooLarge = fileInfo.Length > 10 * 1024 * 1024; // 10MB限制
                string base64String = null;
                string dataUrl = null;
                bool canPreview = previewable && !tooLarge;
                if (canPreview)
                {
                    var fileBytes = System.IO.File.ReadAllBytes(fullPath);
                    base64String = Convert.ToBase64String(fileBytes);
                    dataUrl = $"data:{contentType};base64,{base64String}";
                }

                var result = new
                {
                    success = true,
                    type = "file",
                    path = relativePath,
                    name = fileInfo.Name,
                    size = fileInfo.Length,
                    extension = fileInfo.Extension,
                    contentType = contentType,
                    isPreviewable = canPreview,
                    base64Data = base64String,
                    dataUrl = dataUrl,
                    created = fileInfo.CreationTime,
                    modified = fileInfo.LastWriteTime,
                    message = tooLarge ? "文件过大，无法预览，可下载" : null
                };
                return Ok(result);
            }
            catch (Exception ex)
            {
                return Ok(new { success = false, message = $"获取文件预览失败: {ex.Message}" });
            }
        }

        /// <summary>
        /// 判断文件是否可预览
        /// </summary>
        private bool IsPreviewableFile(string extension)
        {
            var previewableExtensions = new[]
            {
                ".bmp", ".jpg", ".jpeg", ".png", ".gif", ".tiff", ".tif", ".webp",
                ".txt", ".json", ".xml", ".csv", ".log", ".md"
            };
            return previewableExtensions.Contains(extension);
        }

        /// <summary>
        /// 安全检查：确保路径在基础目录内，防止路径遍历攻击
        /// </summary>
        private bool IsPathSafe(string fullPath)
        {
            try
            {
                var basePath = Path.GetFullPath(_basePath);
                var requestedPath = Path.GetFullPath(fullPath);
                return requestedPath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 根据文件扩展名获取MIME类型（兼容C# 7.3）
        /// </summary>
        private string GetContentType(string fileName)
        {
            var extension = Path.GetExtension(fileName).ToLowerInvariant();
            if (extension == ".bmp") return "image/bmp";
            if (extension == ".jpg" || extension == ".jpeg") return "image/jpeg";
            if (extension == ".png") return "image/png";
            if (extension == ".gif") return "image/gif";
            if (extension == ".tiff" || extension == ".tif") return "image/tiff";
            if (extension == ".webp") return "image/webp";
            if (extension == ".pdf") return "application/pdf";
            if (extension == ".txt") return "text/plain";
            if (extension == ".json") return "application/json";
            if (extension == ".xml") return "application/xml";
            if (extension == ".csv") return "text/csv";
            if (extension == ".md") return "text/markdown";
            if (extension == ".log") return "text/plain";
            if (extension == ".zip") return "application/zip";
            if (extension == ".rar") return "application/x-rar-compressed";
            return "application/octet-stream";
        }

        private IHttpActionResult GetDirectoryContents(string fullPath, string relativePath)
        {
            try
            {
                var items = new List<object>();
                var directories = Directory.GetDirectories(fullPath);
                foreach (var dir in directories)
                {
                    var dirInfo = new DirectoryInfo(dir);
                    var subPath = string.IsNullOrEmpty(relativePath)
                        ? dirInfo.Name
                        : $"{relativePath}/{dirInfo.Name}";
                    items.Add(new
                    {
                        name = dirInfo.Name,
                        type = "directory",
                        path = subPath,
                        created = dirInfo.CreationTime,
                        modified = dirInfo.LastWriteTime,
                        isPreviewable = false
                    });
                }
                var files = Directory.GetFiles(fullPath);
                foreach (var file in files)
                {
                    var fileInfo = new FileInfo(file);
                    var filePath = string.IsNullOrEmpty(relativePath)
                        ? fileInfo.Name
                        : $"{relativePath}/{fileInfo.Name}";
                    var extension = fileInfo.Extension.ToLowerInvariant();
                    items.Add(new
                    {
                        name = fileInfo.Name,
                        type = "file",
                        path = filePath,
                        size = fileInfo.Length,
                        extension = fileInfo.Extension,
                        created = fileInfo.CreationTime,
                        modified = fileInfo.LastWriteTime,
                        isPreviewable = IsPreviewableFile(extension),
                        contentType = GetContentType(fileInfo.Name)
                    });
                }
                var result = new
                {
                    success = true,
                    type = "directory",
                    path = relativePath,
                    items = items.OrderBy(x => ((dynamic)x).type == "directory" ? 0 : 1)
                           .ThenBy(x => ((dynamic)x).name)
                           .ToList()
                };
                return Ok(result);
            }
            catch (Exception ex)
            {
                return Ok(new { success = false, message = $"读取目录失败: {ex.Message}" });
            }
        }

        [HttpPost]
        [Route("download")]
        public IHttpActionResult DownloadFile([FromBody] FileRequestDto request)
        {
            try
            {
                if (request == null || string.IsNullOrEmpty(request.RelativePath))
                    return Ok(new { success = false, message = "文件路径不能为空" });

                string fullPath = Path.Combine(_basePath, request.RelativePath.Replace('/', Path.DirectorySeparatorChar));
                if (!IsPathSafe(fullPath) || !System.IO.File.Exists(fullPath))
                    return Ok(new { success = false, message = "文件不存在" });

                var fileInfo = new FileInfo(fullPath);
                var contentType = GetContentType(fileInfo.Name);

                var response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StreamContent(new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                };
                response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
                response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
                {
                    FileName = fileInfo.Name
                };
                return ResponseMessage(response);
            }
            catch (Exception ex)
            {
                return Ok(new { success = false, message = $"下载文件失败: {ex.Message}" });
            }
        }
    }
}

