package com.saas.subscription.controller;

import com.saas.shared.core.TenantContext;
import com.saas.subscription.entity.SubscriptionPlan;
import com.saas.subscription.entity.TenantSubscription;
import com.saas.subscription.repository.SubscriptionPlanRepository;
import com.saas.subscription.repository.SubscriptionRepository;
import com.saas.subscription.service.StripeService;
import com.saas.shared.exception.BusinessException;
import com.saas.shared.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/tenant/stripe")
@RequiredArgsConstructor
@Slf4j
@PreAuthorize("hasRole('TENANT_ADMIN')")
public class StripeController {

    private final StripeService stripeService;
    private final SubscriptionRepository subscriptionRepository;
    private final SubscriptionPlanRepository planRepository;
    private final com.saas.subscription.service.SubscriptionService subscriptionService;

    @PostMapping("/checkout")
    public ResponseEntity<Map<String, String>> createCheckoutSession(
            @RequestParam Long planId,
            @RequestParam String successUrl,
            @RequestParam String cancelUrl) {

        String tenantId = TenantContext.getTenantId();
        log.info("Creating checkout session for tenant: {}, plan: {}", tenantId, planId);

        TenantSubscription subscription = subscriptionRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new BusinessException(ErrorCode.INTERNAL_ERROR, "Subscription not found"));

        SubscriptionPlan plan = planRepository.findById(planId)
                .orElseThrow(() -> new BusinessException(ErrorCode.INVALID_INPUT, "Plan not found"));

        if (plan.getStripePriceId() == null) {
            throw new BusinessException(ErrorCode.INVALID_INPUT, "Plan is not configured for Stripe");
        }

        // Ensure customer exists
        if (subscription.getStripeCustomerId() == null) {
            // In a real app, we'd fetch tenant details (email, name) from TenantService or
            // UserContext
            // For now, we'll use placeholders or need to inject TenantService
            String customerId = stripeService.createCustomer(tenantId, "tenant@example.com", "Tenant " + tenantId);
            subscription.setStripeCustomerId(customerId);
            subscriptionRepository.save(subscription);
        }

        String checkoutUrl = stripeService.createCheckoutSession(
                tenantId,
                subscription.getStripeCustomerId(),
                plan.getStripePriceId(),
                successUrl,
                cancelUrl);

        return ResponseEntity.ok(Map.of("url", checkoutUrl));
    }

    @PostMapping("/portal")
    public ResponseEntity<Map<String, String>> createPortalSession(@RequestParam String returnUrl) {
        String tenantId = TenantContext.getTenantId();
        log.info("Creating portal session for tenant: {}", tenantId);

        TenantSubscription subscription = subscriptionRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new BusinessException(ErrorCode.INTERNAL_ERROR, "Subscription not found"));

        if (subscription.getStripeCustomerId() == null) {
            throw new BusinessException(ErrorCode.INVALID_INPUT, "No Stripe customer found for this tenant");
        }

        String portalUrl = stripeService.createCustomerPortalSession(
                subscription.getStripeCustomerId(),
                returnUrl);

        return ResponseEntity.ok(Map.of("url", portalUrl));
    }

    @GetMapping("/history")
    public ResponseEntity<java.util.List<com.saas.subscription.entity.PaymentRecord>> getPaymentHistory() {
        String tenantId = TenantContext.getTenantId();
        return ResponseEntity.ok(subscriptionService.getTenantPayments(tenantId));
    }
}
