using Fengling.AuthService.Data;
using Fengling.AuthService.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Fengling.AuthService.Controllers;

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class AuditLogsController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly ILogger<AuditLogsController> _logger;

    public AuditLogsController(
        ApplicationDbContext context,
        ILogger<AuditLogsController> logger)
    {
        _context = context;
        _logger = logger;
    }

    [HttpGet]
    public async Task<ActionResult<object>> GetAuditLogs(
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        [FromQuery] string? operatorName = null,
        [FromQuery] string? tenantId = null,
        [FromQuery] string? operation = null,
        [FromQuery] string? action = null,
        [FromQuery] DateTime? startTime = null,
        [FromQuery] DateTime? endTime = null)
    {
        var query = _context.AuditLogs.AsQueryable();

        if (!string.IsNullOrEmpty(operatorName))
        {
            query = query.Where(l => l.Operator.Contains(operatorName));
        }

        if (!string.IsNullOrEmpty(tenantId))
        {
            query = query.Where(l => l.TenantId == tenantId);
        }

        if (!string.IsNullOrEmpty(operation))
        {
            query = query.Where(l => l.Operation == operation);
        }

        if (!string.IsNullOrEmpty(action))
        {
            query = query.Where(l => l.Action == action);
        }

        if (startTime.HasValue)
        {
            query = query.Where(l => l.CreatedAt >= startTime.Value);
        }

        if (endTime.HasValue)
        {
            query = query.Where(l => l.CreatedAt <= endTime.Value);
        }

        var totalCount = await query.CountAsync();
        var logs = await query
            .OrderByDescending(l => l.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToListAsync();

        var result = logs.Select(l => new
        {
            id = l.Id,
            @operator = l.Operator,
            tenantId = l.TenantId,
            operation = l.Operation,
            action = l.Action,
            targetType = l.TargetType,
            targetId = l.TargetId,
            targetName = l.TargetName,
            ipAddress = l.IpAddress,
            description = l.Description,
            oldValue = l.OldValue,
            newValue = l.NewValue,
            errorMessage = l.ErrorMessage,
            status = l.Status,
            createdAt = l.CreatedAt,
        });

        return Ok(new
        {
            items = result,
            totalCount,
            page,
            pageSize
        });
    }

    [HttpGet("export")]
    public async Task<IActionResult> ExportAuditLogs(
        [FromQuery] string? operatorName = null,
        [FromQuery] string? tenantId = null,
        [FromQuery] string? operation = null,
        [FromQuery] string? action = null,
        [FromQuery] DateTime? startTime = null,
        [FromQuery] DateTime? endTime = null)
    {
        var query = _context.AuditLogs.AsQueryable();

        if (!string.IsNullOrEmpty(operatorName))
        {
            query = query.Where(l => l.Operator.Contains(operatorName));
        }

        if (!string.IsNullOrEmpty(tenantId))
        {
            query = query.Where(l => l.TenantId == tenantId);
        }

        if (!string.IsNullOrEmpty(operation))
        {
            query = query.Where(l => l.Operation == operation);
        }

        if (!string.IsNullOrEmpty(action))
        {
            query = query.Where(l => l.Action == action);
        }

        if (startTime.HasValue)
        {
            query = query.Where(l => l.CreatedAt >= startTime.Value);
        }

        if (endTime.HasValue)
        {
            query = query.Where(l => l.CreatedAt <= endTime.Value);
        }

        var logs = await query
            .OrderByDescending(l => l.CreatedAt)
            .Take(10000)
            .ToListAsync();

        var csv = new System.Text.StringBuilder();
        csv.AppendLine("ID,Operator,TenantId,Operation,Action,TargetType,TargetId,TargetName,IpAddress,Description,Status,CreatedAt");

        foreach (var log in logs)
        {
            csv.AppendLine($"{log.Id},{log.Operator},{log.TenantId},{log.Operation},{log.Action},{log.TargetType},{log.TargetId},{log.TargetName},{log.IpAddress},\"{log.Description}\",{log.Status},{log.CreatedAt:yyyy-MM-dd HH:mm:ss}");
        }

        return File(System.Text.Encoding.UTF8.GetBytes(csv.ToString()), "text/csv", $"audit-logs-{DateTime.UtcNow:yyyyMMdd}.csv");
    }
}
