using FastEndpoints;
using FluentValidation;
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 PasswordRedirectRequest
{
    public string Slug { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
}

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

public class PasswordRedirectValidator : Validator<PasswordRedirectRequest>
{
    public PasswordRedirectValidator()
    {
        RuleFor(x => x.Password)
            .NotEmpty().WithMessage("Password is required");
    }
}

public class PasswordRedirectEndpoint(AppDbContext db, IEventTrackingService eventTracking)
    : Endpoint<PasswordRedirectRequest, PasswordRedirectResponse>
{
    public override void Configure()
    {
        Post("/{Slug}");
        AllowAnonymous();
    }

    public override async Task HandleAsync(PasswordRedirectRequest req, CancellationToken ct)
    {
        // Look up the short link by slug
        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 not password protected - just redirect
        if (string.IsNullOrEmpty(link.PasswordHash))
        {
            // Track click event
            await eventTracking.TrackClickAsync(link.WorkspaceId, link.Id, HttpContext);

            HttpContext.Response.StatusCode = StatusCodes.Status302Found;
            HttpContext.Response.Headers.Location = link.DestinationUrl;
            await HttpContext.Response.StartAsync(ct);
            return;
        }

        // Verify password
        if (!BCrypt.Net.BCrypt.Verify(req.Password, link.PasswordHash))
        {
            await HttpContext.Response.SendAsync(new MessageResponse("Invalid password"), 401, cancellation: ct);
            return;
        }

        // Track click event
        await eventTracking.TrackClickAsync(link.WorkspaceId, link.Id, HttpContext);

        // Password correct - redirect
        HttpContext.Response.StatusCode = StatusCodes.Status302Found;
        HttpContext.Response.Headers.Location = link.DestinationUrl;
        await HttpContext.Response.StartAsync(ct);
    }
}