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

import cn.novalon.gym.manage.member.entity.MemberCardRecord;
import cn.novalon.gym.manage.member.service.IMemberCardRecordService;
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.Data;
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
 */
@Component
@Tag(name = "会员卡记录管理", description = "会员卡购买、续费、使用、退款等核心业务")
public class MemberCardRecordHandler {

    private final IMemberCardService memberCardService;
    private final IMemberCardRecordService memberCardRecordService;

    public MemberCardRecordHandler(IMemberCardService memberCardService,
                                   IMemberCardRecordService memberCardRecordService) {
        this.memberCardService = memberCardService;
        this.memberCardRecordService = memberCardRecordService;
    }

    @Operation(summary = "购买会员卡", description = "支持时长卡、次卡、储值卡，自动设置到期提醒")
    public Mono<ServerResponse> purchaseCard(ServerRequest request) {
        
        return request.bodyToMono(PurchaseRequest.class)
                .flatMap(body -> memberCardService.purchaseCard(
                        body.getMemberId(),
                        body.getMemberCardId(),
                        body.getSourceOrderId()))
                .flatMap(record -> ServerResponse.ok().bodyValue(record))
                .onErrorResume(e -> ServerResponse.badRequest().bodyValue("购买失败: " + e.getMessage()));
    }

    @Operation(summary = "续费会员卡", description = "累加剩余次数/余额，顺延到期日期，权益立即生效")
    public Mono<ServerResponse> renewCard(ServerRequest request) {
        Long recordId = Long.parseLong(request.pathVariable("recordId"));
        return request.bodyToMono(RenewRequest.class)
                .flatMap(body -> memberCardService.renewCard(recordId,
                        body.getAddTimes(),
                        body.getAddAmount(),
                        body.getAddDays(),
                        body.getSourceOrderId()))
                .flatMap(record -> ServerResponse.ok().bodyValue(record))
                .onErrorResume(e -> ServerResponse.badRequest().bodyValue("续费失败: " + e.getMessage()));
    }

    @Operation(summary = "使用会员卡", description = "预约团课或私教成功后扣减次数或余额")
    public Mono<ServerResponse> useCard(ServerRequest request) {
        Long recordId = Long.parseLong(request.pathVariable("recordId"));
        return request.bodyToMono(UseCardRequest.class)
                .flatMap(body -> memberCardService.useCard(recordId,
                        body.getDeductTimes(),
                        body.getDeductAmount()))
                .flatMap(record -> ServerResponse.ok().bodyValue(record))
                .onErrorResume(e -> ServerResponse.badRequest().bodyValue("使用失败: " + e.getMessage()));
    }

    @Operation(summary = "退款会员卡", description = "使用Saga模式执行退款流程，保证事务一致性")
    public Mono<ServerResponse> refundCard(ServerRequest request) {
        Long recordId = Long.parseLong(request.pathVariable("recordId"));
        return memberCardService.refundCard(recordId)
                .then(ServerResponse.ok().bodyValue("退款成功"))
                .onErrorResume(e -> ServerResponse.badRequest().bodyValue("退款失败: " + e.getMessage()));
    }

    @Operation(summary = "查询会员卡记录详情", description = "根据记录ID查询详细信息")
    public Mono<ServerResponse> getMemberCardRecordById(ServerRequest request) {
        Long recordId = Long.parseLong(request.pathVariable("recordId"));
        return memberCardRecordService.findById(recordId)
                .flatMap(record -> ServerResponse.ok().bodyValue(record))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    @Operation(summary = "会员我的卡包", description = "查询当前会员的所有有效卡")
    public Mono<ServerResponse> getMyCards(ServerRequest request) {
        Long memberId = Long.parseLong(request.pathVariable("memberId"));
        return ServerResponse.ok().body(
                memberCardRecordService.findActiveCardsByMemberId(memberId),
                MemberCardRecord.class);
    }

    @Operation(summary = "处理过期会员卡", description = "定时任务调用，扫描并更新过期卡状态")
    public Mono<ServerResponse> processExpiredCards(ServerRequest request) {
        return memberCardService.processExpiredCards()
                .flatMap(count -> ServerResponse.ok().bodyValue("处理完成，共处理" + count + "条"));
    }

    @Data
    public static class PurchaseRequest {
        private Long memberId;
        private Long memberCardId;
        private Long sourceOrderId;
    }

    @Data
    public static class UseCardRequest {
        private Integer deductTimes;
        private Double deductAmount;
    }

    @Data
    public static class RenewRequest {
        private Integer addTimes;
        private Double addAmount;
        private Integer addDays;
        private Long sourceOrderId;
    }
}
