package com.zioinfo.mall.loyalty;

import com.zioinfo.mall.admin.AuditService;
import com.zioinfo.mall.common.ApiResponse;
import com.zioinfo.mall.loyalty.mapper.LoyaltyMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 등급별 고객관리 API — /api/mall/loyalty.
 *
 * <ul>
 *   <li>내 등급/혜택/포인트 조회·사용 — 인증 고객</li>
 *   <li>등급 기준·혜택 정의 CRUD, 등급 재산정, 포인트 조정 — ADMIN</li>
 *   <li>등급별 매출 — MANAGER+</li>
 * </ul>
 * 등급 혜택 목록(GET /tiers)은 스토어프론트 노출을 위해 공개(SecurityConfig 화이트리스트).
 */
@RestController
@RequestMapping("/api/mall/loyalty")
@RequiredArgsConstructor
public class LoyaltyController {

    private final LoyaltyService service;
    private final LoyaltyMapper mapper;

    // ---------- 등급 혜택 정의 ----------
    /** 등급 혜택 목록 — 공개(스토어프론트 등급 안내). */
    @GetMapping("/tiers")
    public ApiResponse<List<MallTierBenefit>> tiers(@RequestParam(defaultValue = "true") boolean activeOnly) {
        return ApiResponse.ok(service.tiers(activeOnly));
    }

    @GetMapping("/tiers/{code}")
    public ApiResponse<MallTierBenefit> tier(@PathVariable String code) {
        return ApiResponse.ok(service.tierByCode(code));
    }

    @PostMapping("/tiers")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<MallTierBenefit> createTier(@RequestBody MallTierBenefit t) {
        mapper.insertTier(t);
        return ApiResponse.ok(mapper.findTierById(t.getId()));
    }

    @PutMapping("/tiers/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<MallTierBenefit> updateTier(@PathVariable Long id, @RequestBody MallTierBenefit t) {
        t.setId(id);
        mapper.updateTier(t);
        return ApiResponse.ok(mapper.findTierById(id));
    }

    @DeleteMapping("/tiers/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Void> deleteTier(@PathVariable Long id) {
        mapper.deleteTier(id);
        return ApiResponse.ok(null);
    }

    // ---------- 내 등급 ----------
    /** 내 등급/혜택/누적/포인트 통합 조회. */
    @GetMapping("/me")
    public ApiResponse<Map<String, Object>> me(Authentication auth) {
        return ApiResponse.ok(service.myStatus(auth.getName()));
    }

    // ---------- 포인트 ----------
    @GetMapping("/points/balance")
    public ApiResponse<Map<String, Object>> balance(Authentication auth) {
        return ApiResponse.ok(Map.of("owner", auth.getName(), "balance", service.balance(auth.getName())));
    }

    @GetMapping("/points/history")
    public ApiResponse<List<MallPointLedger>> history(
            @RequestParam(defaultValue = "100") int limit, Authentication auth) {
        return ApiResponse.ok(service.history(auth.getName(), limit));
    }

    /** 포인트 사용(결제 시 차감). */
    @PostMapping("/points/use")
    public ApiResponse<Map<String, Object>> use(@RequestBody UsePointRequest req, Authentication auth) {
        return ApiResponse.ok(service.usePoints(auth.getName(), req.points(), req.orderNo()));
    }

    /** 관리자 포인트 조정(가감). */
    @PostMapping("/points/adjust")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Map<String, Object>> adjust(@RequestBody AdjustRequest req, Authentication auth) {
        return ApiResponse.ok(service.adjust(req.owner(), req.points(), req.reason(), auth.getName()));
    }

    // ---------- 등급 재산정 ----------
    /** 단일 고객 등급 재산정 (본인 또는 ADMIN). */
    @PostMapping("/recalc")
    public ApiResponse<Map<String, Object>> recalc(@RequestParam(required = false) String owner,
                                                   Authentication auth) {
        boolean admin = auth.getAuthorities().stream()
                .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"));
        String target = (admin && owner != null && !owner.isBlank()) ? owner : auth.getName();
        return ApiResponse.ok(service.recalcOne(target));
    }

    /** 전체 회원 등급 일괄 재산정(배치성) — ADMIN. */
    @PostMapping("/recalc-all")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Map<String, Object>> recalcAll() {
        return ApiResponse.ok(service.recalcAll());
    }

    // ---------- 등급별 매출 ----------
    @GetMapping("/analytics/by-tier")
    @PreAuthorize("hasAnyRole('ADMIN','MANAGER')")
    public ApiResponse<List<Map<String, Object>>> byTier(@RequestParam(defaultValue = "30") int days) {
        return ApiResponse.ok(service.salesByTier(days));
    }

    public record UsePointRequest(int points, String orderNo) {}
    public record AdjustRequest(String owner, int points, String reason) {}
}
