using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using System.Net.Mime;
using TakeoutSaaS.AdminApi.Contracts.Requests;
using TakeoutSaaS.Application.Dictionary.Contracts;
using TakeoutSaaS.Application.Dictionary.Models;
using TakeoutSaaS.Application.Dictionary.Services;
using TakeoutSaaS.Domain.Dictionary.Enums;
using TakeoutSaaS.Module.Authorization.Attributes;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;

namespace TakeoutSaaS.AdminApi.Controllers;

/// <summary>
/// 字典分组管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/admin/v{version:apiVersion}/dictionary/groups")]
public sealed class DictionaryGroupsController(
    DictionaryCommandService commandService,
    DictionaryQueryService queryService,
    DictionaryImportExportService importExportService)
    : BaseApiController
{
    /// <summary>
    /// 查询字典分组。
    /// </summary>
    [HttpGet]
    [PermissionAuthorize("dictionary:group:read")]
    [ProducesResponseType(typeof(ApiResponse<PagedResult<DictionaryGroupDto>>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<PagedResult<DictionaryGroupDto>>> List([FromQuery] DictionaryGroupQuery query, CancellationToken cancellationToken)
    {
        var result = await queryService.GetGroupsAsync(query, cancellationToken);
        return ApiResponse<PagedResult<DictionaryGroupDto>>.Ok(result);
    }

    /// <summary>
    /// 获取字典分组详情。
    /// </summary>
    [HttpGet("{groupId:long}")]
    [PermissionAuthorize("dictionary:group:read")]
    [ProducesResponseType(typeof(ApiResponse<DictionaryGroupDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<DictionaryGroupDto>> Detail(long groupId, CancellationToken cancellationToken)
    {
        var result = await queryService.GetGroupByIdAsync(groupId, cancellationToken);
        return result == null
            ? ApiResponse<DictionaryGroupDto>.Error(ErrorCodes.NotFound, "字典分组不存在")
            : ApiResponse<DictionaryGroupDto>.Ok(result);
    }

    /// <summary>
    /// 创建字典分组。
    /// </summary>
    [HttpPost]
    [PermissionAuthorize("dictionary:group:create")]
    [ProducesResponseType(typeof(ApiResponse<DictionaryGroupDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<DictionaryGroupDto>> Create([FromBody] CreateDictionaryGroupRequest request, CancellationToken cancellationToken)
    {
        var result = await commandService.CreateGroupAsync(request, cancellationToken);
        return ApiResponse<DictionaryGroupDto>.Ok(result);
    }

    /// <summary>
    /// 更新字典分组。
    /// </summary>
    [HttpPut("{groupId:long}")]
    [PermissionAuthorize("dictionary:group:update")]
    [ProducesResponseType(typeof(ApiResponse<DictionaryGroupDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<DictionaryGroupDto>> Update(long groupId, [FromBody] UpdateDictionaryGroupRequest request, CancellationToken cancellationToken)
    {
        var result = await commandService.UpdateGroupAsync(groupId, request, cancellationToken);
        return ApiResponse<DictionaryGroupDto>.Ok(result);
    }

    /// <summary>
    /// 删除字典分组。
    /// </summary>
    [HttpDelete("{groupId:long}")]
    [PermissionAuthorize("dictionary:group:delete")]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
    public async Task<ApiResponse<object>> Delete(long groupId, CancellationToken cancellationToken)
    {
        var success = await commandService.DeleteGroupAsync(groupId, cancellationToken);
        return success
            ? ApiResponse.Success()
            : ApiResponse.Error(ErrorCodes.NotFound, "字典分组不存在");
    }

    /// <summary>
    /// 导出字典分组数据。
    /// </summary>
    [HttpPost("{groupId:long}/export")]
    [PermissionAuthorize("dictionary:group:read")]
    [Produces("application/octet-stream")]
    [ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
    public async Task<IActionResult> Export(long groupId, [FromBody] DictionaryExportRequest request, CancellationToken cancellationToken)
    {
        var format = NormalizeFormat(request.Format);
        await using var stream = new MemoryStream();

        if (format == "json")
        {
            await importExportService.ExportToJsonAsync(groupId, stream, cancellationToken);
        }
        else
        {
            await importExportService.ExportToCsvAsync(groupId, stream, cancellationToken);
        }

        var extension = format == "json" ? "json" : "csv";
        var fileName = $"dictionary_{groupId}_{DateTime.UtcNow:yyyyMMdd_HHmmss}.{extension}";
        Response.Headers[HeaderNames.ContentDisposition] = new ContentDispositionHeaderValue("attachment")
        {
            FileName = fileName,
            FileNameStar = fileName
        }.ToString();

        var contentType = format == "json" ? MediaTypeNames.Application.Json : "text/csv";
        return File(stream.ToArray(), contentType);
    }

    /// <summary>
    /// 导入字典分组数据。
    /// </summary>
    [HttpPost("{groupId:long}/import")]
    [PermissionAuthorize("dictionary:item:update")]
    [ProducesResponseType(typeof(ApiResponse<DictionaryImportResultDto>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<DictionaryImportResultDto>> Import(
        long groupId,
        [FromForm] DictionaryImportFormRequest request,
        CancellationToken cancellationToken)
    {
        if (request.File.Length > 10 * 1024 * 1024)
        {
            return ApiResponse<DictionaryImportResultDto>.Error(ErrorCodes.BadRequest, "导入文件不能超过 10MB");
        }

        var format = NormalizeFormat(request.Format);
        var conflictMode = ParseConflictMode(request.ConflictMode);

        await using var stream = request.File.OpenReadStream();
        var importRequest = new DictionaryImportRequest
        {
            GroupId = groupId,
            FileName = request.File.FileName,
            FileSize = request.File.Length,
            ConflictMode = conflictMode,
            FileStream = stream
        };

        var result = format == "json"
            ? await importExportService.ImportFromJsonAsync(importRequest, cancellationToken)
            : await importExportService.ImportFromCsvAsync(importRequest, cancellationToken);

        return ApiResponse<DictionaryImportResultDto>.Ok(result);
    }

    private static string NormalizeFormat(string? format)
    {
        if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase))
        {
            return "json";
        }

        return "csv";
    }

    private static ConflictResolutionMode ParseConflictMode(string? conflictMode)
    {
        if (string.IsNullOrWhiteSpace(conflictMode))
        {
            return ConflictResolutionMode.Skip;
        }

        return Enum.TryParse<ConflictResolutionMode>(conflictMode, ignoreCase: true, out var mode)
            ? mode
            : ConflictResolutionMode.Skip;
    }
}
