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

import cn.novalon.gym.manage.checkIn.service.impl.CheckServiceImpl;
import cn.novalon.gym.manage.checkIn.websocket.MyWebSocketHandler;
import cn.novalon.gym.manage.checkIn.vo.SignInRecordVO;
import cn.novalon.gym.manage.checkIn.vo.SignInStatsVO;
import cn.novalon.gym.manage.sys.util.AuthUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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;
import cn.novalon.gym.manage.checkIn.websocket.MyWebSocketHandler;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@Slf4j
@Component
@RequiredArgsConstructor
public class CheckInHandler {

    private final AuthUtil authUtil;
    private final CheckServiceImpl checkService;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 签到
     *
     * POST /api/checkIn
     *
     */
    public Mono<ServerResponse> checkIn(ServerRequest request) {

        Long memberId = authUtil.getMemberIdOrThrow(request);

        return request.bodyToMono(Map.class)
                .flatMap(body -> {
                    String qrContent = (String) body.get("qrContent");
                    log.info("收到签到请求, memberId: {}, qrContent: {}", memberId, qrContent);
                    boolean messageToClient = MyWebSocketHandler.sendMessageToClient(qrContent, "正在进行签到");
                    log.info("WebSocket 推送结果: {}", messageToClient);
                    return checkService.checkIn(memberId, qrContent)
                            .flatMap(result -> ServerResponse.ok()
                                    .contentType(MediaType.APPLICATION_JSON)
                                    .bodyValue(result));
                })
                .onErrorResume(e -> {
                    log.error("签到失败", e);
                    return ServerResponse.status(HttpStatus.BAD_REQUEST)
                            .bodyValue(Map.of("code", 400, "message", e.getMessage()));
                });
    }

    /**
     * 获取二维码
     *
     * GET /api/checkin/qrcode
     *
     */
    public Mono<ServerResponse> getQRCode(ServerRequest request) {

        Long memberId = authUtil.getMemberIdOrThrow(request);

        log.info("收到用户{}获取二维码请求", memberId);

        return checkService.getQRCode(memberId)
                .flatMap(qrCodeVo -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(qrCodeVo));
    }

    /**
     * 查询签到记录列表
     *
     * GET /api/checkIn/records
     *
     * @param request
     * @return
     */
    public Mono<ServerResponse> getSignInRecords(ServerRequest request) {
        Long memberId = authUtil.getMemberIdOrThrow(request);
        
        String startDateStr = request.queryParam("startDate").orElse(null);
        String endDateStr = request.queryParam("endDate").orElse(null);
        
        LocalDate startDate = startDateStr != null ? LocalDate.parse(startDateStr, DATE_FORMATTER) : LocalDate.now().minusDays(30);
        LocalDate endDate = endDateStr != null ? LocalDate.parse(endDateStr, DATE_FORMATTER) : LocalDate.now();
        
        log.info("查询签到记录, memberId: {}, startDate: {}, endDate: {}", memberId, startDate, endDate);
        
        return checkService.getSignInRecords(memberId, startDate, endDate)
                .collectList()
                .flatMap(records -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(Map.of("code", 200, "message", "success", "data", records)));
    }

    /**
     * 查询单条签到记录
     *
     * GET /api/checkIn/records/{id}
     *
     * @param request
     * @return
     */
    public Mono<ServerResponse> getSignInRecordById(ServerRequest request) {
        Long id = Long.parseLong(request.pathVariable("id"));
        
        log.info("查询签到记录详情, id: {}", id);
        
        return checkService.getSignInRecordById(id)
                .flatMap(record -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(Map.of("code", 200, "message", "success", "data", record)))
                .switchIfEmpty(ServerResponse.notFound().build());
    }

    /**
     * 获取签到统计
     *
     * GET /api/checkIn/statistics
     *
     * @param request
     * @return
     */
    public Mono<ServerResponse> getSignInStatistics(ServerRequest request) {
        Long memberId = authUtil.getMemberIdOrThrow(request);
        
        String startDateStr = request.queryParam("startDate").orElse(null);
        String endDateStr = request.queryParam("endDate").orElse(null);
        
        LocalDate startDate = startDateStr != null ? LocalDate.parse(startDateStr, DATE_FORMATTER) : LocalDate.now().minusDays(30);
        LocalDate endDate = endDateStr != null ? LocalDate.parse(endDateStr, DATE_FORMATTER) : LocalDate.now();
        
        log.info("查询签到统计, memberId: {}, startDate: {}, endDate: {}", memberId, startDate, endDate);
        
        return checkService.getSignInStats(memberId, startDate, endDate)
                .flatMap(stats -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(Map.of("code", 200, "message", "success", "data", stats)));
    }

    /**
     * 导出签到记录
     *
     * GET /api/checkIn/records/export
     *
     * @param request
     * @return
     */
    public Mono<ServerResponse> exportSignInRecords(ServerRequest request) {
        Long memberId = authUtil.getMemberIdOrThrow(request);
        
        String startDateStr = request.queryParam("startDate").orElse(null);
        String endDateStr = request.queryParam("endDate").orElse(null);
        
        LocalDate startDate = startDateStr != null ? LocalDate.parse(startDateStr, DATE_FORMATTER) : LocalDate.now().minusDays(30);
        LocalDate endDate = endDateStr != null ? LocalDate.parse(endDateStr, DATE_FORMATTER) : LocalDate.now();
        
        log.info("导出签到记录, memberId: {}, startDate: {}, endDate: {}", memberId, startDate, endDate);
        
        String filename = "签到记录_" + startDateStr + "_" + endDateStr + ".csv";
        
        return checkService.exportSignInRecords(memberId, startDate, endDate)
                .flatMap(bytes -> ServerResponse.ok()
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"")
                        .contentType(MediaType.parseMediaType("text/csv; charset=UTF-8"))
                        .bodyValue(bytes));
    }

    /**
     * 获取每日签到统计
     *
     * GET /api/checkIn/daily-stats
     *
     * @param request
     * @return
     */
    public Mono<ServerResponse> getDailySignInStats(ServerRequest request) {
        String dateStr = request.queryParam("date").orElse(null);
        LocalDate date = dateStr != null ? LocalDate.parse(dateStr, DATE_FORMATTER) : LocalDate.now();
        
        log.info("查询每日签到统计, date: {}", date);
        
        return checkService.getDailySignInStats(date)
                .flatMap(stats -> ServerResponse.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .bodyValue(Map.of("code", 200, "message", "success", "data", stats)));
    }
}
