using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MilitaryTrainingManagement.Models.DTOs;
using MilitaryTrainingManagement.Services.Interfaces;

namespace MilitaryTrainingManagement.Controllers;

/// <summary>
/// 审计日志控制器
/// </summary>
[ApiController]
[Route("api/admin/audit")]
[Authorize]
public class AuditController : BaseApiController
{
    private readonly IAuditService _auditService;
    private readonly ILogger<AuditController> _logger;

    public AuditController(IAuditService auditService, ILogger<AuditController> logger)
    {
        _auditService = auditService;
        _logger = logger;
    }

    /// <summary>
    /// 获取审计日志列表
    /// </summary>
    [HttpGet]
    [Authorize(Policy = "DivisionLevel")]
    public async Task<ActionResult<IEnumerable<AuditLogDto>>> GetLogs([FromQuery] AuditLogQueryDto query)
    {
        try
        {
            var parameters = new AuditLogQueryParameters
            {
                EntityType = query.EntityType,
                EntityId = query.EntityId,
                Action = query.Action,
                UserId = query.UserId,
                OrganizationalUnitId = query.OrganizationalUnitId,
                FromDate = query.FromDate,
                ToDate = query.ToDate,
                IsSuccess = query.IsSuccess,
                PageNumber = query.PageNumber,
                PageSize = query.PageSize
            };

            var logs = await _auditService.GetLogsAsync(parameters);
            var dtos = logs.Select(MapToDto);
            return Ok(dtos);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取审计日志失败");
            return StatusCode(500, "获取审计日志失败");
        }
    }


    /// <summary>
    /// 获取实体的审计历史
    /// </summary>
    [HttpGet("entity/{entityType}/{entityId}")]
    [Authorize(Policy = "DivisionLevel")]
    public async Task<ActionResult<EntityHistoryDto>> GetEntityHistory(string entityType, int entityId)
    {
        try
        {
            var logs = await _auditService.GetEntityHistoryAsync(entityType, entityId);
            var dto = new EntityHistoryDto
            {
                EntityType = entityType,
                EntityId = entityId,
                History = logs.Select(MapToDto).ToList()
            };
            return Ok(dto);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取实体审计历史失败: {EntityType} {EntityId}", entityType, entityId);
            return StatusCode(500, "获取实体审计历史失败");
        }
    }

    /// <summary>
    /// 获取用户的操作历史
    /// </summary>
    [HttpGet("user/{userId}")]
    [Authorize(Policy = "DivisionLevel")]
    public async Task<ActionResult<IEnumerable<AuditLogDto>>> GetUserActivity(
        int userId, 
        [FromQuery] DateTime? fromDate = null, 
        [FromQuery] DateTime? toDate = null)
    {
        try
        {
            var logs = await _auditService.GetUserActivityAsync(userId, fromDate, toDate);
            var dtos = logs.Select(MapToDto);
            return Ok(dtos);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取用户操作历史失败: {UserId}", userId);
            return StatusCode(500, "获取用户操作历史失败");
        }
    }

    /// <summary>
    /// 获取组织单位的操作历史
    /// </summary>
    [HttpGet("unit/{unitId}")]
    [Authorize(Policy = "RegimentLevel")]
    public async Task<ActionResult<IEnumerable<AuditLogDto>>> GetOrganizationalUnitActivity(
        int unitId, 
        [FromQuery] DateTime? fromDate = null, 
        [FromQuery] DateTime? toDate = null)
    {
        try
        {
            // 验证用户是否有权限查看该单位的审计日志
            var currentUnitId = GetCurrentUnitId();
            if (currentUnitId == null)
            {
                return Unauthorized("无法获取当前用户的组织单位");
            }

            var logs = await _auditService.GetOrganizationalUnitActivityAsync(unitId, fromDate, toDate);
            var dtos = logs.Select(MapToDto);
            return Ok(dtos);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取组织单位操作历史失败: {UnitId}", unitId);
            return StatusCode(500, "获取组织单位操作历史失败");
        }
    }

    /// <summary>
    /// 获取审计日志统计
    /// </summary>
    [HttpGet("statistics")]
    [Authorize(Policy = "DivisionLevel")]
    public async Task<ActionResult<AuditLogStatisticsDto>> GetStatistics(
        [FromQuery] DateTime? fromDate = null, 
        [FromQuery] DateTime? toDate = null)
    {
        try
        {
            var stats = await _auditService.GetStatisticsAsync(fromDate, toDate);
            var dto = new AuditLogStatisticsDto
            {
                TotalLogs = stats.TotalLogs,
                CreateOperations = stats.CreateOperations,
                UpdateOperations = stats.UpdateOperations,
                DeleteOperations = stats.DeleteOperations,
                ApprovalOperations = stats.ApprovalOperations,
                FailedOperations = stats.FailedOperations,
                OperationsByEntityType = stats.OperationsByEntityType,
                OperationsByAction = stats.OperationsByAction
            };
            return Ok(dto);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取审计日志统计失败");
            return StatusCode(500, "获取审计日志统计失败");
        }
    }

    /// <summary>
    /// 映射审计日志到DTO
    /// </summary>
    private static AuditLogDto MapToDto(Models.Entities.AuditLog log)
    {
        return new AuditLogDto
        {
            Id = log.Id,
            EntityType = log.EntityType,
            EntityId = log.EntityId,
            Action = log.Action,
            Description = log.Description,
            OldValues = log.OldValues,
            NewValues = log.NewValues,
            ChangedFields = log.ChangedFields,
            UserId = log.UserId,
            UserName = log.User?.DisplayName,
            OrganizationalUnitId = log.OrganizationalUnitId,
            OrganizationalUnitName = log.OrganizationalUnit?.Name,
            Timestamp = log.Timestamp,
            IpAddress = log.IpAddress,
            RequestPath = log.RequestPath,
            IsSuccess = log.IsSuccess,
            ErrorMessage = log.ErrorMessage
        };
    }
}
