using HoneyBox.Admin.Business.Models.Upload;
using HoneyBox.Admin.Business.Services.Interfaces;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;

namespace HoneyBox.Admin.Business.Services.Storage;

/// <summary>
/// 本地存储提供者
/// 将文件保存到 wwwroot/uploads/{yyyy}/{MM}/{dd}/ 目录
/// </summary>
public class LocalStorageProvider : IStorageProvider
{
    private readonly IWebHostEnvironment _environment;
    private readonly ILogger<LocalStorageProvider> _logger;
    private const string UploadBasePath = "uploads";

    public LocalStorageProvider(
        IWebHostEnvironment environment,
        ILogger<LocalStorageProvider> logger)
    {
        _environment = environment;
        _logger = logger;
    }

    /// <inheritdoc />
    public string StorageType => "1";

    /// <inheritdoc />
    public bool SupportsDirectUpload => false;

    /// <inheritdoc />
    public async Task<UploadResult> UploadAsync(Stream fileStream, string fileName, string contentType)
    {
        try
        {
            // 生成日期目录路径: uploads/2026/01/19/
            var now = DateTime.Now;
            var datePath = Path.Combine(
                now.Year.ToString(),
                now.Month.ToString("D2"),
                now.Day.ToString("D2"));

            // 生成唯一文件名
            var uniqueFileName = GenerateUniqueFileName(fileName);

            // 构建完整的物理路径
            var relativePath = Path.Combine(UploadBasePath, datePath);
            var physicalPath = Path.Combine(_environment.WebRootPath, relativePath);

            // 确保目录存在
            EnsureDirectoryExists(physicalPath);

            // 完整文件路径
            var fullFilePath = Path.Combine(physicalPath, uniqueFileName);

            // 保存文件
            await using var fileStreamOutput = new FileStream(fullFilePath, FileMode.Create, FileAccess.Write);
            await fileStream.CopyToAsync(fileStreamOutput);

            // 生成相对URL路径 (使用正斜杠)
            var url = $"/{UploadBasePath}/{datePath.Replace(Path.DirectorySeparatorChar, '/')}/{uniqueFileName}";

            _logger.LogInformation("本地存储上传成功: {FileName} -> {Url}", fileName, url);

            return UploadResult.Ok(url);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "本地存储上传失败: {FileName}", fileName);
            return UploadResult.Fail($"保存文件失败: {ex.Message}");
        }
    }

    /// <inheritdoc />
    public Task<bool> DeleteAsync(string fileUrl)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(fileUrl))
            {
                return Task.FromResult(false);
            }

            // 将URL转换为物理路径
            // URL格式: /uploads/2026/01/19/xxx.jpg
            var relativePath = fileUrl.TrimStart('/').Replace('/', Path.DirectorySeparatorChar);
            var physicalPath = Path.Combine(_environment.WebRootPath, relativePath);

            if (File.Exists(physicalPath))
            {
                File.Delete(physicalPath);
                _logger.LogInformation("本地存储删除成功: {Url}", fileUrl);
                return Task.FromResult(true);
            }

            _logger.LogWarning("本地存储删除失败，文件不存在: {Url}", fileUrl);
            return Task.FromResult(false);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "本地存储删除失败: {Url}", fileUrl);
            return Task.FromResult(false);
        }
    }

    /// <inheritdoc />
    public Task<PresignedUrlResponse?> GetPresignedUploadUrlAsync(string fileName, string contentType, int expiresInSeconds = 600)
    {
        // 本地存储不支持客户端直传，返回null
        _logger.LogDebug("本地存储不支持客户端直传");
        return Task.FromResult<PresignedUrlResponse?>(null);
    }

    /// <summary>
    /// 生成唯一文件名
    /// 格式: {timestamp}_{guid}{extension}
    /// </summary>
    private static string GenerateUniqueFileName(string originalFileName)
    {
        var extension = Path.GetExtension(originalFileName).ToLowerInvariant();
        var timestamp = DateTime.Now.ToString("yyyyMMddHHmmssfff");
        var guid = Guid.NewGuid().ToString("N")[..8]; // 取GUID前8位
        return $"{timestamp}_{guid}{extension}";
    }

    /// <summary>
    /// 确保目录存在，不存在则创建
    /// </summary>
    private void EnsureDirectoryExists(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
            _logger.LogDebug("创建目录: {Path}", path);
        }
    }
}
