package handlers

import (
	"net/http"

	"github.com/labstack/echo/v4"

	"github.com/treytartt/honeydue-api/internal/apperrors"
	"github.com/treytartt/honeydue-api/internal/i18n"
	"github.com/treytartt/honeydue-api/internal/middleware"
	"github.com/treytartt/honeydue-api/internal/services"
)

// SubscriptionHandler handles subscription-related HTTP requests
type SubscriptionHandler struct {
	subscriptionService *services.SubscriptionService
	stripeService       *services.StripeService
}

// NewSubscriptionHandler creates a new subscription handler
func NewSubscriptionHandler(subscriptionService *services.SubscriptionService, stripeService *services.StripeService) *SubscriptionHandler {
	return &SubscriptionHandler{
		subscriptionService: subscriptionService,
		stripeService:       stripeService,
	}
}

// GetSubscription handles GET /api/subscription/
func (h *SubscriptionHandler) GetSubscription(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	subscription, err := h.subscriptionService.GetSubscription(user.ID)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, subscription)
}

// GetSubscriptionStatus handles GET /api/subscription/status/
func (h *SubscriptionHandler) GetSubscriptionStatus(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	status, err := h.subscriptionService.GetSubscriptionStatus(user.ID)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, status)
}

// GetUpgradeTrigger handles GET /api/subscription/upgrade-trigger/:key/
func (h *SubscriptionHandler) GetUpgradeTrigger(c echo.Context) error {
	key := c.Param("key")

	trigger, err := h.subscriptionService.GetUpgradeTrigger(key)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, trigger)
}

// GetAllUpgradeTriggers handles GET /api/subscription/upgrade-triggers/
func (h *SubscriptionHandler) GetAllUpgradeTriggers(c echo.Context) error {
	triggers, err := h.subscriptionService.GetAllUpgradeTriggers()
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, triggers)
}

// GetFeatureBenefits handles GET /api/subscription/features/
func (h *SubscriptionHandler) GetFeatureBenefits(c echo.Context) error {
	benefits, err := h.subscriptionService.GetFeatureBenefits()
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, benefits)
}

// GetPromotions handles GET /api/subscription/promotions/
func (h *SubscriptionHandler) GetPromotions(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	promotions, err := h.subscriptionService.GetActivePromotions(user.ID)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, promotions)
}

// ProcessPurchase handles POST /api/subscription/purchase/
func (h *SubscriptionHandler) ProcessPurchase(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	var req services.ProcessPurchaseRequest
	if err := c.Bind(&req); err != nil {
		return apperrors.BadRequest("error.invalid_request")
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	var subscription *services.SubscriptionResponse

	switch req.Platform {
	case "ios":
		// StoreKit 2 uses transaction_id, StoreKit 1 uses receipt_data
		if req.TransactionID == "" && req.ReceiptData == "" {
			return apperrors.BadRequest("error.receipt_data_required")
		}
		subscription, err = h.subscriptionService.ProcessApplePurchase(user.ID, req.ReceiptData, req.TransactionID)
	case "android":
		if req.PurchaseToken == "" {
			return apperrors.BadRequest("error.purchase_token_required")
		}
		subscription, err = h.subscriptionService.ProcessGooglePurchase(user.ID, req.PurchaseToken, req.ProductID)
	default:
		return apperrors.BadRequest("error.invalid_platform")
	}

	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"message":      i18n.LocalizedMessage(c, "message.subscription_upgraded"),
		"subscription": subscription,
	})
}

// CancelSubscription handles POST /api/subscription/cancel/
func (h *SubscriptionHandler) CancelSubscription(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	subscription, err := h.subscriptionService.CancelSubscription(user.ID)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"message":      i18n.LocalizedMessage(c, "message.subscription_cancelled"),
		"subscription": subscription,
	})
}

// RestoreSubscription handles POST /api/subscription/restore/
func (h *SubscriptionHandler) RestoreSubscription(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	var req services.ProcessPurchaseRequest
	if err := c.Bind(&req); err != nil {
		return apperrors.BadRequest("error.invalid_request")
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	// Same logic as ProcessPurchase - validates receipt/token and restores
	var subscription *services.SubscriptionResponse

	switch req.Platform {
	case "ios":
		// B-14: Validate that at least one of receipt_data or transaction_id is provided
		if req.ReceiptData == "" && req.TransactionID == "" {
			return apperrors.BadRequest("error.receipt_data_required")
		}
		subscription, err = h.subscriptionService.ProcessApplePurchase(user.ID, req.ReceiptData, req.TransactionID)
	case "android":
		if req.PurchaseToken == "" {
			return apperrors.BadRequest("error.purchase_token_required")
		}
		subscription, err = h.subscriptionService.ProcessGooglePurchase(user.ID, req.PurchaseToken, req.ProductID)
	default:
		return apperrors.BadRequest("error.invalid_platform")
	}

	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"message":      i18n.LocalizedMessage(c, "message.subscription_restored"),
		"subscription": subscription,
	})
}

// CreateCheckoutSession handles POST /api/subscription/checkout/
// Creates a Stripe Checkout Session for web subscription purchases
func (h *SubscriptionHandler) CreateCheckoutSession(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	if h.stripeService == nil {
		return apperrors.BadRequest("error.stripe_not_configured")
	}

	// Check if already Pro from another platform
	alreadyPro, existingPlatform, err := h.subscriptionService.IsAlreadyProFromOtherPlatform(user.ID, "stripe")
	if err != nil {
		return err
	}
	if alreadyPro {
		return c.JSON(http.StatusConflict, map[string]interface{}{
			"error":             "error.already_subscribed_other_platform",
			"existing_platform": existingPlatform,
			"message":           "You already have an active Pro subscription via " + existingPlatform + ". Manage it there to avoid double billing.",
		})
	}

	var req struct {
		PriceID    string `json:"price_id" validate:"required"`
		SuccessURL string `json:"success_url" validate:"required,url"`
		CancelURL  string `json:"cancel_url" validate:"required,url"`
	}
	if err := c.Bind(&req); err != nil {
		return apperrors.BadRequest("error.invalid_request")
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	sessionURL, err := h.stripeService.CreateCheckoutSession(user.ID, req.PriceID, req.SuccessURL, req.CancelURL)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"checkout_url": sessionURL,
	})
}

// CreatePortalSession handles POST /api/subscription/portal/
// Creates a Stripe Customer Portal session for managing web subscriptions
func (h *SubscriptionHandler) CreatePortalSession(c echo.Context) error {
	user, err := middleware.MustGetAuthUser(c)
	if err != nil {
		return err
	}

	if h.stripeService == nil {
		return apperrors.BadRequest("error.stripe_not_configured")
	}

	var req struct {
		ReturnURL string `json:"return_url" validate:"required,url"`
	}
	if err := c.Bind(&req); err != nil {
		return apperrors.BadRequest("error.invalid_request")
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	portalURL, err := h.stripeService.CreatePortalSession(user.ID, req.ReturnURL)
	if err != nil {
		return err
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"portal_url": portalURL,
	})
}
