package com.zioinfo.kintex.boothsales;

import com.zioinfo.kintex.auth.EventAccessGuard;
import com.zioinfo.kintex.auth.KintexPrincipal;
import com.zioinfo.kintex.boothsales.dto.BoothSalesDtos.*;
import com.zioinfo.kintex.common.ApiResponse;
import com.zioinfo.kintex.common.audit.Audited;
import com.zioinfo.kintex.settlement.dto.SettlementDtos.GenerateResult;
import jakarta.validation.Valid;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

/**
 * F005/F006 부스 판매 인벤토리·온라인 셀프 판매 API (SCR /booth-sales).
 * <ul>
 *   <li>조회(인벤토리): 행사 접근 권한(참가업체는 available+본인 hold, 매니저는 전 상태).</li>
 *   <li>hold·구매 확정·본인 hold 해제: 행사 멤버(참가업체 포함).</li>
 *   <li>blocked 전환·판매가 override·정산 연계: 매니저 이상(주최자/홀매니저) + {@link Audited}.</li>
 * </ul>
 * 이중 hold·만료 hold 구매 시도는 409(CONFLICT). 금액은 서버 계산 권위.
 */
@RestController
@RequestMapping("/api/booth-sales")
public class BoothSalesController {

    private final BoothSalesService service;
    private final EventAccessGuard guard;

    public BoothSalesController(BoothSalesService service, EventAccessGuard guard) {
        this.service = service;
        this.guard = guard;
    }

    /** GET /api/booth-sales/inventory?eventId=&hallId= — 판매 인벤토리(상태·가격 오버레이). */
    @GetMapping("/inventory")
    public ApiResponse<InventoryResponse> inventory(@AuthenticationPrincipal KintexPrincipal principal,
                                                    @RequestParam String eventId,
                                                    @RequestParam(required = false) String hallId) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.inventory(eventId, hallId, principal));
    }

    /** POST /api/booth-sales/hold — 부스 선점(참가업체 셀프 선택). 이중 hold 409. */
    @Audited(action = "BOOTH_SALE_HOLD", targetType = "booth_sale")
    @PostMapping("/hold")
    public ApiResponse<BoothSaleResult> hold(@AuthenticationPrincipal KintexPrincipal principal,
                                             @Valid @RequestBody HoldRequest req) {
        guard.requireEventAccess(principal, req.eventId());
        return ApiResponse.ok(service.hold(req, principal));
    }

    /** POST /api/booth-sales/purchase — 구매 확정(hold→sold). 만료·미보유 시 409. */
    @Audited(action = "BOOTH_SALE_PURCHASE", targetType = "booth_sale")
    @PostMapping("/purchase")
    public ApiResponse<BoothSaleResult> purchase(@AuthenticationPrincipal KintexPrincipal principal,
                                                 @Valid @RequestBody PurchaseRequest req) {
        guard.requireEventAccess(principal, req.eventId());
        return ApiResponse.ok(service.purchase(req, principal));
    }

    /** POST /api/booth-sales/release — 본인 hold 해제(available 복원). */
    @Audited(action = "BOOTH_SALE_RELEASE", targetType = "booth_sale")
    @PostMapping("/release")
    public ApiResponse<BoothSaleResult> release(@AuthenticationPrincipal KintexPrincipal principal,
                                                @Valid @RequestBody HoldRequest req) {
        guard.requireEventAccess(principal, req.eventId());
        return ApiResponse.ok(service.release(req, principal));
    }

    /** POST /api/booth-sales/block — blocked/available 전환(매니저 이상). sold 차단 불가 409. */
    @Audited(action = "BOOTH_SALE_BLOCK", targetType = "booth_sale")
    @PostMapping("/block")
    public ApiResponse<BoothSaleResult> block(@AuthenticationPrincipal KintexPrincipal principal,
                                              @Valid @RequestBody BlockRequest req) {
        guard.requireEventAccess(principal, req.eventId());
        return ApiResponse.ok(service.setBlocked(req, principal));
    }

    /** POST /api/booth-sales/price — 판매가 override(매니저 이상, null=면적×요율 파생 복원). */
    @Audited(action = "BOOTH_SALE_PRICE", targetType = "booth_sale")
    @PostMapping("/price")
    public ApiResponse<BoothSaleResult> price(@AuthenticationPrincipal KintexPrincipal principal,
                                              @Valid @RequestBody PriceRequest req) {
        guard.requireEventAccess(principal, req.eventId());
        return ApiResponse.ok(service.setPrice(req, principal));
    }

    /** POST /api/booth-sales/settle?eventId= — M9 청구서 집계 트리거(매니저 이상, settlement 생성 연계). */
    @Audited(action = "BOOTH_SALE_SETTLE", targetType = "invoice")
    @PostMapping("/settle")
    public ApiResponse<GenerateResult> settle(@AuthenticationPrincipal KintexPrincipal principal,
                                              @RequestParam String eventId) {
        guard.requireEventAccess(principal, eventId);
        return ApiResponse.ok(service.settle(eventId, principal));
    }
}
