using System.Text.Json;
using Femto.Api.Auth;
using Femto.Modules.Auth.Application.Dto;
using Femto.Modules.Auth.Models;
using Microsoft.Extensions.Options;

namespace Femto.Api.Sessions;

internal record SessionInfo(string? SessionId, Guid? UserId);

internal static class HttpContextSessionExtensions
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    };

    public static string? GetSessionId(this HttpContext httpContext) =>
        httpContext.Request.Cookies["sid"];

    public static void SetSession(this HttpContext context, Session session, UserInfo user)
    {
        var cookieSettings = context.RequestServices.GetRequiredService<IOptions<CookieSettings>>();

        context.Response.Cookies.Append(
            "sid",
            session.Id,
            new CookieOptions
            {
                Path = "/",
                IsEssential = true,
                Domain = cookieSettings.Value.Domain,
                HttpOnly = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = session.Expires,
            }
        );

        context.Response.Cookies.Append(
            "user",
            JsonSerializer.Serialize(user, JsonOptions),
            new CookieOptions
            {
                Path = "/",
                Domain = cookieSettings.Value.Domain,
                IsEssential = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = session.Expires,
            }
        );
    }

    public static void DeleteSession(this HttpContext httpContext)
    {
        var cookieSettings = httpContext.RequestServices.GetRequiredService<
            IOptions<CookieSettings>
        >();

        httpContext.Response.Cookies.Delete(
            "sid",
            new CookieOptions
            {
                Path = "/",
                HttpOnly = true,
                Domain = cookieSettings.Value.Domain,
                IsEssential = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = DateTimeOffset.UtcNow.AddDays(-1),
            }
        );

        httpContext.Response.Cookies.Delete(
            "user",
            new CookieOptions
            {
                Path = "/",
                Domain = cookieSettings.Value.Domain,
                IsEssential = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = DateTimeOffset.UtcNow.AddDays(-1),
            }
        );
    }
    
    
    public static RememberMeToken? GetRememberMeToken(this HttpContext httpContext) =>
        httpContext.Request.Cookies["rid"] is { } code ? RememberMeToken.FromCode(code) : null;

    public static void SetRememberMeToken(this HttpContext context, NewRememberMeToken token)
    {
        var cookieSettings = context.RequestServices.GetRequiredService<IOptions<CookieSettings>>();

        context.Response.Cookies.Append(
            "rid",
            token.Code,
            new CookieOptions
            {
                Path = "/",
                IsEssential = true,
                Domain = cookieSettings.Value.Domain,
                HttpOnly = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = token.Expires,
            }
        );
    }

    public static void DeleteRememberMeToken(this HttpContext context)
    {
        var cookieSettings = context.RequestServices.GetRequiredService<IOptions<CookieSettings>>();

        context.Response.Cookies.Delete(
            "rid",
            new CookieOptions
            {
                Path = "/",
                HttpOnly = true,
                Domain = cookieSettings.Value.Domain,
                IsEssential = true,
                Secure = cookieSettings.Value.Secure,
                SameSite = cookieSettings.Value.SameSite,
                Expires = DateTimeOffset.UtcNow.AddDays(-1),
            }
        );
    }
}
