package handlers

import (
	"io"
	"log"
	"net/http"

	"github.com/breakpilot/billing-service/internal/database"
	"github.com/breakpilot/billing-service/internal/services"
	"github.com/gin-gonic/gin"
	"github.com/stripe/stripe-go/v76/webhook"
)

// WebhookHandler handles Stripe webhook events
type WebhookHandler struct {
	db                  *database.DB
	webhookSecret       string
	subscriptionService *services.SubscriptionService
	entitlementService  *services.EntitlementService
}

// NewWebhookHandler creates a new WebhookHandler
func NewWebhookHandler(
	db *database.DB,
	webhookSecret string,
	subscriptionService *services.SubscriptionService,
	entitlementService *services.EntitlementService,
) *WebhookHandler {
	return &WebhookHandler{
		db:                  db,
		webhookSecret:       webhookSecret,
		subscriptionService: subscriptionService,
		entitlementService:  entitlementService,
	}
}

// HandleStripeWebhook handles incoming Stripe webhook events
// POST /api/v1/billing/webhook
func (h *WebhookHandler) HandleStripeWebhook(c *gin.Context) {
	// Read the request body
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		log.Printf("Webhook: Error reading body: %v", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "cannot read body"})
		return
	}

	// Get the Stripe signature header
	sigHeader := c.GetHeader("Stripe-Signature")
	if sigHeader == "" {
		log.Printf("Webhook: Missing Stripe-Signature header")
		c.JSON(http.StatusBadRequest, gin.H{"error": "missing signature"})
		return
	}

	// Verify the webhook signature
	event, err := webhook.ConstructEvent(body, sigHeader, h.webhookSecret)
	if err != nil {
		log.Printf("Webhook: Signature verification failed: %v", err)
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid signature"})
		return
	}

	ctx := c.Request.Context()

	// Check if we've already processed this event (idempotency)
	processed, err := h.subscriptionService.IsEventProcessed(ctx, event.ID)
	if err != nil {
		log.Printf("Webhook: Error checking event: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error"})
		return
	}
	if processed {
		log.Printf("Webhook: Event %s already processed", event.ID)
		c.JSON(http.StatusOK, gin.H{"status": "already_processed"})
		return
	}

	// Mark event as being processed
	if err := h.subscriptionService.MarkEventProcessing(ctx, event.ID, string(event.Type)); err != nil {
		log.Printf("Webhook: Error marking event: %v", err)
	}

	// Handle the event based on type
	var handleErr error
	switch event.Type {
	case "checkout.session.completed":
		handleErr = h.handleCheckoutSessionCompleted(ctx, event.Data.Raw)

	case "customer.subscription.created":
		handleErr = h.handleSubscriptionCreated(ctx, event.Data.Raw)

	case "customer.subscription.updated":
		handleErr = h.handleSubscriptionUpdated(ctx, event.Data.Raw)

	case "customer.subscription.deleted":
		handleErr = h.handleSubscriptionDeleted(ctx, event.Data.Raw)

	case "invoice.paid":
		handleErr = h.handleInvoicePaid(ctx, event.Data.Raw)

	case "invoice.payment_failed":
		handleErr = h.handleInvoicePaymentFailed(ctx, event.Data.Raw)

	case "customer.created":
		log.Printf("Webhook: Customer created - %s", event.ID)

	default:
		log.Printf("Webhook: Unhandled event type: %s", event.Type)
	}

	if handleErr != nil {
		log.Printf("Webhook: Error handling %s: %v", event.Type, handleErr)
		// Mark event as failed
		h.subscriptionService.MarkEventFailed(ctx, event.ID, handleErr.Error())
		c.JSON(http.StatusInternalServerError, gin.H{"error": "handler error"})
		return
	}

	// Mark event as processed
	if err := h.subscriptionService.MarkEventProcessed(ctx, event.ID); err != nil {
		log.Printf("Webhook: Error marking event processed: %v", err)
	}

	c.JSON(http.StatusOK, gin.H{"status": "processed"})
}

// handleCheckoutSessionCompleted handles successful checkout
func (h *WebhookHandler) handleCheckoutSessionCompleted(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing checkout.session.completed")

	// Parse checkout session from data
	// The actual implementation will parse the JSON and create/update subscription

	// TODO: Implementation
	// 1. Parse checkout session data
	// 2. Extract customer_id, subscription_id, user_id (from metadata)
	// 3. Create or update subscription record
	// 4. Update entitlements

	return nil
}

// handleSubscriptionCreated handles new subscription creation
func (h *WebhookHandler) handleSubscriptionCreated(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing customer.subscription.created")

	// TODO: Implementation
	// 1. Parse subscription data
	// 2. Extract status, plan, trial_end, etc.
	// 3. Create subscription record
	// 4. Set up initial entitlements

	return nil
}

// handleSubscriptionUpdated handles subscription updates
func (h *WebhookHandler) handleSubscriptionUpdated(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing customer.subscription.updated")

	// TODO: Implementation
	// 1. Parse subscription data
	// 2. Update subscription record (status, plan, cancel_at_period_end, etc.)
	// 3. Update entitlements if plan changed

	return nil
}

// handleSubscriptionDeleted handles subscription cancellation
func (h *WebhookHandler) handleSubscriptionDeleted(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing customer.subscription.deleted")

	// TODO: Implementation
	// 1. Parse subscription data
	// 2. Update subscription status to canceled/expired
	// 3. Remove or downgrade entitlements

	return nil
}

// handleInvoicePaid handles successful invoice payment
func (h *WebhookHandler) handleInvoicePaid(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing invoice.paid")

	// TODO: Implementation
	// 1. Parse invoice data
	// 2. Update subscription period
	// 3. Reset usage counters for new period
	// 4. Store invoice record

	return nil
}

// handleInvoicePaymentFailed handles failed invoice payment
func (h *WebhookHandler) handleInvoicePaymentFailed(ctx interface{}, data []byte) error {
	log.Printf("Webhook: Processing invoice.payment_failed")

	// TODO: Implementation
	// 1. Parse invoice data
	// 2. Update subscription status to past_due
	// 3. Send notification to user
	// 4. Possibly restrict access

	return nil
}
