package com.zioinfo.mall.promotion;

import com.zioinfo.mall.common.ApiResponse;
import com.zioinfo.mall.promotion.mapper.PromotionMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 프로모션 API — /api/mall/promotion. GET 공개(쿠폰/기획전 노출), 변경 MANAGER+.
 *
 * <p>쿠폰 검증/할인 계산은 POST /validate 로 제공(주문 금액 기준).
 */
@RestController
@RequestMapping("/api/mall/promotion")
@RequiredArgsConstructor
public class PromotionController {

    private final PromotionMapper mapper;

    // ---------- 기획전 ----------
    @GetMapping("/featured")
    public ApiResponse<List<MallPromotion>> featured() {
        return ApiResponse.ok(mapper.findPromotions(true));
    }

    @PostMapping("/featured")
    public ApiResponse<MallPromotion> createPromotion(@RequestBody MallPromotion p) {
        mapper.insertPromotion(p);
        return ApiResponse.ok(mapper.findPromotionById(p.getId()));
    }

    @PutMapping("/featured/{id}")
    public ApiResponse<MallPromotion> updatePromotion(@PathVariable Long id, @RequestBody MallPromotion p) {
        p.setId(id);
        mapper.updatePromotion(p);
        return ApiResponse.ok(mapper.findPromotionById(id));
    }

    @DeleteMapping("/featured/{id}")
    public ApiResponse<Void> deletePromotion(@PathVariable Long id) {
        mapper.deletePromotion(id);
        return ApiResponse.ok(null);
    }

    // ---------- 쿠폰 ----------
    @GetMapping("/coupons")
    public ApiResponse<List<MallCoupon>> coupons(@RequestParam(defaultValue = "true") boolean activeOnly) {
        return ApiResponse.ok(mapper.findCoupons(activeOnly));
    }

    @PostMapping("/coupons")
    public ApiResponse<MallCoupon> createCoupon(@RequestBody MallCoupon c) {
        mapper.insertCoupon(c);
        return ApiResponse.ok(mapper.findCouponById(c.getId()));
    }

    @PutMapping("/coupons/{id}")
    public ApiResponse<MallCoupon> updateCoupon(@PathVariable Long id, @RequestBody MallCoupon c) {
        c.setId(id);
        mapper.updateCoupon(c);
        return ApiResponse.ok(mapper.findCouponById(id));
    }

    @DeleteMapping("/coupons/{id}")
    public ApiResponse<Void> deleteCoupon(@PathVariable Long id) {
        mapper.deleteCoupon(id);
        return ApiResponse.ok(null);
    }

    /** 쿠폰 검증 + 할인 금액 계산. */
    @PostMapping("/validate")
    public ApiResponse<Map<String, Object>> validate(@RequestBody ValidateRequest req) {
        MallCoupon c = mapper.findCouponByCode(req.code());
        Map<String, Object> out = new LinkedHashMap<>();
        if (c == null || !Boolean.TRUE.equals(c.getActive())) {
            out.put("valid", false);
            out.put("reason", "존재하지 않거나 비활성 쿠폰");
            return ApiResponse.ok(out);
        }
        LocalDate today = LocalDate.now();
        if ((c.getValidFrom() != null && today.isBefore(c.getValidFrom()))
                || (c.getValidTo() != null && today.isAfter(c.getValidTo()))) {
            out.put("valid", false);
            out.put("reason", "쿠폰 유효기간이 아닙니다");
            return ApiResponse.ok(out);
        }
        BigDecimal amount = req.orderAmount() == null ? BigDecimal.ZERO : req.orderAmount();
        if (c.getMinOrderAmount() != null && amount.compareTo(c.getMinOrderAmount()) < 0) {
            out.put("valid", false);
            out.put("reason", "최소 주문금액 미달 (" + c.getMinOrderAmount() + ")");
            return ApiResponse.ok(out);
        }
        BigDecimal discount;
        if ("RATE".equalsIgnoreCase(c.getDiscountType())) {
            discount = amount.multiply(c.getDiscountValue()).divide(BigDecimal.valueOf(100));
            if (c.getMaxDiscount() != null && discount.compareTo(c.getMaxDiscount()) > 0) {
                discount = c.getMaxDiscount();
            }
        } else {
            discount = c.getDiscountValue();
        }
        discount = discount.min(amount);
        out.put("valid", true);
        out.put("couponId", c.getId());
        out.put("discountAmount", discount);
        out.put("payAmount", amount.subtract(discount).max(BigDecimal.ZERO));
        return ApiResponse.ok(out);
    }

    public record ValidateRequest(String code, BigDecimal orderAmount) {}
}
