using System.Security.Claims;
using AiLogia.Web.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace AiLogia.Web.Controllers;

public class AuthController : Controller
{
    private readonly IAuthLinksClient _authLinks;
    public AuthController(IAuthLinksClient authLinks) => _authLinks = authLinks;

    const bool enableTelegramProcessing = false;

    // Экран логина (кнопка "Войти через Telegram")
    [HttpGet]
    [AllowAnonymous]
    public IActionResult Login(string? returnUrl = null)
    {
        if (User?.Identity?.IsAuthenticated == true)
            return Redirect(string.IsNullOrWhiteSpace(returnUrl) ? "/account/overview" : returnUrl);

        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

    // 1) Точка входа из Телеграма
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> Tg(string token, string? returnUrl = null, CancellationToken ct = default)
    {
        if (string.IsNullOrWhiteSpace(token)) return BadRequest("missing token");

        var (valid, reason, userId, tgId, username, fullName, expUtc) = await _authLinks.ValidateAsync(token, ct);
        if (!valid)
        {
            TempData["AuthError"] = ReasonToMessage(reason, expUtc);
            return RedirectToAction(nameof(Login), new { returnUrl });
        }

        if (enableTelegramProcessing)
        {            // если это Telegram webview — предложим вынести наружу
            if (IsTelegramWebView(Request))
            {
                // создадим новый магик-токен для внешнего браузера
                var created = await _authLinks.CreateAsync(tgId, username, fullName, 15, ct);
                if (created is null)
                {
                    TempData["AuthError"] = "Не удалось подготовить ссылку. Попробуйте ещё раз.";
                    return RedirectToAction(nameof(Login), new { returnUrl });
                }

                // Сформируем внешнюю ссылку (откроется где угодно — можно скопировать/QR и т.п.)
                var externalUrl = Url.Action(nameof(Tg), "Auth",
                    new { token = created.Value.token, returnUrl },
                    protocol: Request.Scheme, host: Request.Host.ToString());

                // Покажем экран с двумя вариантами
                ViewBag.ExternalUrl = externalUrl;
                ViewBag.ConsumeHereUrl = Url.Action(nameof(TgConsume), "Auth", new { token, returnUrl });
                return View("OpenExternally");
            }
        }

        // не Telegram — логиним сразу (consume)
        var consumed = await _authLinks.ConsumeAsync(token, ct);
        if (!consumed)
        {
            TempData["AuthError"] = "Ссылка уже использована. Запросите новую в боте.";
            return RedirectToAction(nameof(Login), new { returnUrl });
        }

        await SignInAsync(userId, tgId, username, fullName);
        var target = Url.IsLocalUrl(returnUrl) ? returnUrl : "/account/overview";
        return Redirect(target);
    }

    // 2) Войти прямо в Telegram-webview (потребляем исходный токен)
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> TgConsume(string token, string? returnUrl = null, CancellationToken ct = default)
    {
        if (string.IsNullOrWhiteSpace(token)) return BadRequest("missing token");
        var (valid, reason, userId, tgId, username, fullName, expUtc) = await _authLinks.ValidateAsync(token, ct);
        if (!valid)
        {
            TempData["AuthError"] = ReasonToMessage(reason, expUtc);
            return RedirectToAction(nameof(Login), new { returnUrl });
        }

        var consumed = await _authLinks.ConsumeAsync(token, ct);
        if (!consumed)
        {
            TempData["AuthError"] = "Ссылка уже использована. Запросите новую в боте.";
            return RedirectToAction(nameof(Login), new { returnUrl });
        }

        await SignInAsync(userId, tgId, username, fullName);
        var target = Url.IsLocalUrl(returnUrl) ? returnUrl : "/account/overview";
        return Redirect(target);
    }

    private async Task SignInAsync(long userId, long tgId, string? username, string? fullName)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, userId.ToString()),
            new Claim("tg_id", tgId.ToString()),
            new Claim("tg_username", username ?? string.Empty),
            new Claim("tg_fullname", fullName ?? string.Empty),
            new Claim(ClaimTypes.Name, fullName ?? username ?? $"tg:{tgId}")
        };
        var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "AppCookie"));
        await HttpContext.SignInAsync("AppCookie", principal);
    }

    private static bool IsTelegramWebView(HttpRequest req)
    {
        // 1) Явный маркер из бота: ?s=b
        if (req.Query.TryGetValue("s", out var s) &&
            s.ToString().Equals("b", StringComparison.OrdinalIgnoreCase))
            return true;

        return false;
    }


    private static string ReasonToMessage(string? reason, DateTime? expiresUtc)
            => reason switch
            {
                "invalid" => "Ссылка недействительна. Запросите новую в боте.",
                "used" => "Ссылка уже использована. Запросите новую в боте.",
                "expired" => expiresUtc is DateTime dt
                    ? $"Срок действия ссылки истёк ({dt:u}). Запросите новую в боте."
                    : "Срок действия ссылки истёк. Запросите новую в боте.",
                _ => "Не удалось проверить ссылку. Попробуйте ещё раз."
            };

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout(string? returnUrl = null)
    {
        await HttpContext.SignOutAsync("AppCookie");
        return Redirect(string.IsNullOrWhiteSpace(returnUrl) ? "/" : returnUrl);
    }

    [HttpGet]
    [AllowAnonymous]
    public IActionResult Denied() => View(); // при желании отрендери красивую страницу 403
}