package cn.novalon.gym.manage.member.handler;

import cn.novalon.gym.manage.member.entity.MemberCard;
import cn.novalon.gym.manage.member.service.IMemberCardService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * 会员卡管理处理器
 * 
 * @author 付嘉
 * @date 2026-05-27
 */
@Slf4j
@Component
@Tag(name = "会员卡管理", description = "会员卡类型管理和会员持卡管理")
public class MemberCardHandler {

    private final IMemberCardService memberCardService;

    public MemberCardHandler(IMemberCardService memberCardService) {
        this.memberCardService = memberCardService;
    }

    @Operation(summary = "根据ID查询会员卡类型", description = "查询指定ID的会员卡类型详情")
    public Mono<ServerResponse> getMemberCardById(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return memberCardService.findByMemberCardIdAndDeletedAtIsNull(id)
                .flatMap(card -> ServerResponse.ok().bodyValue(card))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "查询会员卡类型列表", description = "支持分页和条件查询")
    public Mono<ServerResponse> listMemberCards(ServerRequest request) {
        Integer status = request.queryParam("status").map(Integer::valueOf).orElse(null);
        String name = request.queryParam("name").orElse(null);
        String type = request.queryParam("type").orElse(null);
        Double minPrice = request.queryParam("minPrice").map(Double::valueOf).orElse(null);
        Double maxPrice = request.queryParam("maxPrice").map(Double::valueOf).orElse(null);
        int page = request.queryParam("page").map(Integer::valueOf).orElse(0);
        int size = request.queryParam("size").map(Integer::valueOf).orElse(10);

        var pageable = PageRequest.of(page, size);
        return ServerResponse.ok()
                .body(memberCardService.findWithConditions(status, name, type, minPrice, maxPrice, pageable),
                        MemberCard.class);
    }

    @Operation(summary = "创建会员卡类型", description = "创建新的会员卡类型（时长卡、次卡或储值卡）")
    public Mono<ServerResponse> createMemberCard(ServerRequest request) {
        return request.bodyToMono(MemberCard.class)
                .flatMap(memberCardService::save)
                .flatMap(card -> ServerResponse.status(HttpStatus.CREATED).bodyValue(card));
    }

    @Operation(summary = "更新会员卡类型", description = "更新会员卡类型信息")
    public Mono<ServerResponse> updateMemberCard(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return request.bodyToMono(MemberCard.class)
                .flatMap(card -> {
                    card.setMemberCardId(id);
                    return memberCardService.save(card);
                })
                .flatMap(updated -> ServerResponse.ok().bodyValue(updated))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "删除会员卡类型", description = "逻辑删除会员卡类型")
    public Mono<ServerResponse> deleteMemberCard(ServerRequest request) {
        Long id = Long.valueOf(request.pathVariable("id"));
        return memberCardService.logicalDelete(id)
                .flatMap(rows -> {
                    if (rows > 0) {
                        return ServerResponse.noContent().build();
                    }
                    return ServerResponse.notFound().build();
                });
    }

    @Operation(summary = "购买会员卡", description = "会员购买会员卡，生成会员卡记录")
    public Mono<ServerResponse> purchaseCard(ServerRequest request) {
        Long memberId = Long.valueOf(request.queryParam("memberId").orElseThrow());
        Long memberCardId = Long.valueOf(request.queryParam("memberCardId").orElseThrow());
        Long sourceOrderId = request.queryParam("sourceOrderId").map(Long::valueOf).orElse(null);

        return memberCardService.purchaseCard(memberId, memberCardId, sourceOrderId)
                .flatMap(record -> ServerResponse.status(HttpStatus.CREATED).bodyValue(record));
    }

    @Operation(summary = "续费会员卡", description = "为已有会员卡续费")
    public Mono<ServerResponse> renewCard(ServerRequest request) {
        Long recordId = Long.valueOf(request.queryParam("recordId").orElseThrow());
        Integer addTimes = request.queryParam("addTimes").map(Integer::valueOf).orElse(null);
        Double addAmount = request.queryParam("addAmount").map(Double::valueOf).orElse(null);
        Integer addDays = request.queryParam("addDays").map(Integer::valueOf).orElse(null);
        Long sourceOrderId = request.queryParam("sourceOrderId").map(Long::valueOf).orElse(null);

        return memberCardService.renewCard(recordId, addTimes, addAmount, addDays, sourceOrderId)
                .flatMap(record -> ServerResponse.ok().bodyValue(record));
    }

    @Operation(summary = "使用会员卡", description = "扣减会员卡次数或余额")
    public Mono<ServerResponse> useCard(ServerRequest request) {
        Long recordId = Long.valueOf(request.queryParam("recordId").orElseThrow());
        Integer deductTimes = request.queryParam("deductTimes").map(Integer::valueOf).orElse(null);
        Double deductAmount = request.queryParam("deductAmount").map(Double::valueOf).orElse(null);

        return memberCardService.useCard(recordId, deductTimes, deductAmount)
                .flatMap(record -> ServerResponse.ok().bodyValue(record));
    }

    @Operation(summary = "退款会员卡", description = "申请会员卡退款")
    public Mono<ServerResponse> refundCard(ServerRequest request) {
        Long recordId = Long.valueOf(request.queryParam("recordId").orElseThrow());
        return memberCardService.refundCard(recordId)
                .then(ServerResponse.noContent().build());
    }

    @Operation(summary = "查询有效会员卡", description = "查询指定状态的会员卡类型")
    public Mono<ServerResponse> getActiveCards(ServerRequest request) {
        Integer status = request.queryParam("status").map(Integer::valueOf).orElse(1);
        return ServerResponse.ok()
                .body(memberCardService.findActiveCards(status), MemberCard.class);
    }
}
