package de.cannamanage.api.controller;

import com.stripe.exception.StripeException;
import de.cannamanage.api.dto.billing.CheckoutRequest;
import de.cannamanage.api.dto.billing.SubscriptionResponse;
import de.cannamanage.domain.entity.Subscription;
import de.cannamanage.domain.entity.TenantContext;
import de.cannamanage.domain.enums.PlanTier;
import de.cannamanage.service.StripeService;
import de.cannamanage.service.repository.ClubRepository;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
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;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/api/v1/billing")
@RequiredArgsConstructor
@Tag(name = "Billing", description = "Subscription and payment management")
public class SubscriptionController {

    private final StripeService stripeService;
    private final ClubRepository clubRepository;

    @GetMapping("/subscription")
    @Operation(summary = "Get current subscription", description = "Returns the current plan and subscription status")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<SubscriptionResponse> getSubscription() {
        UUID tenantId = TenantContext.getCurrentTenant();
        UUID clubId = clubRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new IllegalStateException("No club for tenant"))
                .getId();

        return stripeService.getSubscription(clubId)
                .map(sub -> ResponseEntity.ok(toResponse(sub)))
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

    @PostMapping("/checkout")
    @Operation(summary = "Create checkout session", description = "Creates a Stripe Checkout session for plan upgrade")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<Map<String, String>> createCheckout(@RequestBody CheckoutRequest request) throws StripeException {
        UUID tenantId = TenantContext.getCurrentTenant();
        UUID clubId = clubRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new IllegalStateException("No club for tenant"))
                .getId();

        PlanTier planTier = PlanTier.valueOf(request.planTier().toUpperCase());
        String checkoutUrl = stripeService.createCheckoutSession(clubId, planTier);
        return ResponseEntity.ok(Map.of("url", checkoutUrl));
    }

    @PostMapping("/portal")
    @Operation(summary = "Create billing portal session", description = "Creates a Stripe Billing Portal session for self-service")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<Map<String, String>> createPortalSession() throws StripeException {
        UUID tenantId = TenantContext.getCurrentTenant();
        UUID clubId = clubRepository.findByTenantId(tenantId)
                .orElseThrow(() -> new IllegalStateException("No club for tenant"))
                .getId();

        String portalUrl = stripeService.createBillingPortalSession(clubId);
        return ResponseEntity.ok(Map.of("url", portalUrl));
    }

    private SubscriptionResponse toResponse(Subscription sub) {
        return new SubscriptionResponse(
                sub.getPlanTier().name(),
                sub.getStatus().name(),
                sub.getMemberLimit(),
                sub.getTrialEndsAt(),
                sub.getCurrentPeriodStart(),
                sub.getCurrentPeriodEnd(),
                sub.getCanceledAt(),
                sub.getStripeSubscriptionId() != null
        );
    }
}
