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 AccessLogsController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly ILogger<AccessLogsController> _logger;

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

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

        if (!string.IsNullOrEmpty(userName))
        {
            query = query.Where(l => l.UserName != null && l.UserName.Contains(userName));
        }

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

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

        if (!string.IsNullOrEmpty(status))
        {
            query = query.Where(l => l.Status == status);
        }

        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,
            userName = l.UserName,
            tenantId = l.TenantId,
            action = l.Action,
            resource = l.Resource,
            method = l.Method,
            ipAddress = l.IpAddress,
            userAgent = l.UserAgent,
            status = l.Status,
            duration = l.Duration,
            requestData = l.RequestData,
            responseData = l.ResponseData,
            errorMessage = l.ErrorMessage,
            createdAt = l.CreatedAt,
        });

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

    [HttpGet("export")]
    public async Task<IActionResult> ExportAccessLogs(
        [FromQuery] string? userName = null,
        [FromQuery] string? tenantId = null,
        [FromQuery] string? action = null,
        [FromQuery] string? status = null,
        [FromQuery] DateTime? startTime = null,
        [FromQuery] DateTime? endTime = null)
    {
        var query = _context.AccessLogs.AsQueryable();

        if (!string.IsNullOrEmpty(userName))
        {
            query = query.Where(l => l.UserName != null && l.UserName.Contains(userName));
        }

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

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

        if (!string.IsNullOrEmpty(status))
        {
            query = query.Where(l => l.Status == status);
        }

        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,UserName,TenantId,Action,Resource,Method,IpAddress,UserAgent,Status,Duration,CreatedAt");

        foreach (var log in logs)
        {
            csv.AppendLine($"{log.Id},{log.UserName},{log.TenantId},{log.Action},{log.Resource},{log.Method},{log.IpAddress},\"{log.UserAgent}\",{log.Status},{log.Duration},{log.CreatedAt:yyyy-MM-dd HH:mm:ss}");
        }

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