using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PlotLine.Data;
using PlotLine.Models;
using PlotLine.Services;
using PlotLine.ViewModels;

namespace PlotLine.Controllers;

[AllowAnonymous]
public sealed class PricingController(
    ICurrentUserService currentUser,
    IUserRepository users,
    ISubscriptionService subscriptions,
    IStripeBillingService stripeBilling,
    IConfiguration configuration) : Controller
{
    [HttpGet("pricing", Name = PublicRouteNames.Pricing)]
    public async Task<IActionResult> Index()
    {
        const string description = "Compare PlotDirector plans and choose the right subscription for organising your novel, series, characters, plot threads, timelines, and story details.";
        PublicSeo.Apply(ViewData, configuration, new SeoMetadata
        {
            Title = "Pricing",
            Description = description,
            Keywords = "PlotDirector pricing, novel planning software pricing, writing software plans, author tools subscription",
            CanonicalPath = "/pricing",
            JsonLd =
            [
                PublicSeo.WebPageJsonLd(configuration, "WebPage", "Pricing", "/pricing", description),
                PublicSeo.JsonLd(new Dictionary<string, object?>
                {
                    ["@context"] = "https://schema.org",
                    ["@type"] = "FAQPage",
                    ["mainEntity"] = new[]
                    {
                        new Dictionary<string, object?>
                        {
                            ["@type"] = "Question",
                            ["name"] = "Can I start with a free trial?",
                            ["acceptedAnswer"] = new Dictionary<string, object?>
                            {
                                ["@type"] = "Answer",
                                ["text"] = "Yes. Creating an account starts a 30-day Draft Desk trial immediately."
                            }
                        },
                        new Dictionary<string, object?>
                        {
                            ["@type"] = "Question",
                            ["name"] = "Do I need a credit card for the trial?",
                            ["acceptedAnswer"] = new Dictionary<string, object?>
                            {
                                ["@type"] = "Answer",
                                ["text"] = "No. Payment details are not required for the free trial."
                            }
                        }
                    }
                })
            ]
        });

        UserSubscriptionDetail? currentSubscription = null;
        if (currentUser.UserId is int userId)
        {
            currentSubscription = await subscriptions.GetCurrentSubscriptionAsync(userId);
        }

        return View(new PricingViewModel
        {
            Plans = await subscriptions.GetActiveSubscriptionLevelsAsync(),
            CurrentSubscriptionLevelID = currentSubscription?.SubscriptionLevelID,
            IsSignedIn = currentUser.UserId.HasValue
        });
    }

    [HttpGet]
    public IActionResult StartTrial()
    {
        if (!currentUser.UserId.HasValue)
        {
            return RedirectToAction("Register", "Account");
        }

        return RedirectToAction("Subscription", "ManageAccount");
    }

    [HttpGet]
    public async Task<IActionResult> Checkout(int id, string billingInterval = "Monthly")
    {
        if (!currentUser.UserId.HasValue)
        {
            var returnUrl = Url.Action(nameof(Checkout), "Pricing", new { id, billingInterval }) ?? "/pricing";
            return RedirectToAction("Login", "Account", new { returnUrl });
        }

        var user = await users.GetByIdAsync(currentUser.UserId.Value);
        if (user is null)
        {
            return RedirectToAction("Login", "Account");
        }

        var request = new StripeCheckoutRequest
        {
            SubscriptionLevelID = id,
            BillingInterval = string.Equals(billingInterval, "Annual", StringComparison.OrdinalIgnoreCase)
                ? "Annual"
                : "Monthly"
        };

        var successUrl = Url.Action("SubscriptionSuccess", "ManageAccount", null, Request.Scheme) ?? string.Empty;
        var cancelUrl = Url.Action(nameof(Index), "Pricing", null, Request.Scheme) ?? string.Empty;
        var result = await stripeBilling.StartCheckoutOrChangePlanAsync(user, request, successUrl, cancelUrl);
        if (result.Succeeded && !string.IsNullOrWhiteSpace(result.RedirectUrl))
        {
            return Redirect(result.RedirectUrl);
        }

        TempData["PricingMessage"] = result.Message;
        return RedirectToAction(nameof(Index));
    }
}
