using FastEndpoints;
using Microsoft.EntityFrameworkCore;
using TrackQrApi.Data;
using TrackQrApi.Features.Auth.Common;
using TrackQrApi.Features.Events.Services;
using TrackQrApi.Models;

namespace TrackQrApi.Features.Redirect.Endpoints;

public class RedirectRequest
{
    public string Slug { get; set; } = string.Empty;
    public Guid? Qr { get; set; }
}

public class RedirectResponse
{
    public string Location { get; set; } = string.Empty;
}

public class RedirectEndpoint(AppDbContext db, IEventTrackingService eventTracking)
    : Endpoint<RedirectRequest, RedirectResponse>
{
    public override void Configure()
    {
        Get("/{Slug}");
        AllowAnonymous();
        Options(x => x.RequireRateLimiting("redirect"));
    }

    public override async Task HandleAsync(RedirectRequest req, CancellationToken ct)
    {
        // Look up the short link by slug (default domain = null for now)
        var link = await db.ShortLinks
            .Where(l => l.Slug == req.Slug && l.DomainId == null)
            .Select(l => new
            {
                l.Id,
                l.DestinationUrl,
                l.Status,
                l.ExpiresAt,
                l.PasswordHash,
                l.WorkspaceId
            })
            .FirstOrDefaultAsync(ct);

        // Link not found
        if (link is null)
        {
            await HttpContext.Response.SendAsync(new MessageResponse("Link not found"), 404, cancellation: ct);
            return;
        }

        // Link is disabled
        if (link.Status == ShortLinkStatus.Disabled)
        {
            await HttpContext.Response.SendAsync(new MessageResponse("Link not found"), 404, cancellation: ct);
            return;
        }

        // Link has expired
        if (link.ExpiresAt.HasValue && link.ExpiresAt.Value < DateTime.UtcNow)
        {
            await HttpContext.Response.SendAsync(new MessageResponse("Link has expired"), 410, cancellation: ct);
            return;
        }

        // Link is password protected
        if (!string.IsNullOrEmpty(link.PasswordHash))
        {
            // Return 401 with a hint that password is required
            // Frontend/client would need to POST the password to verify
            HttpContext.Response.Headers["X-Password-Required"] = "true";
            await HttpContext.Response.SendAsync(new MessageResponse("Password required"), 401, cancellation: ct);
            return;
        }

        // Track event asynchronously (fire and forget)
        // If qr parameter is present, track as scan; otherwise track as click
        if (req.Qr.HasValue)
            await eventTracking.TrackScanAsync(link.WorkspaceId, link.Id, req.Qr.Value, HttpContext);
        else
            await eventTracking.TrackClickAsync(link.WorkspaceId, link.Id, HttpContext);

        // Redirect to destination (302 Found)
        HttpContext.Response.StatusCode = StatusCodes.Status302Found;
        HttpContext.Response.Headers.Location = link.DestinationUrl;
        await HttpContext.Response.StartAsync(ct);
    }
}