package cn.novalon.gym.manage.groupcourse.service.impl;

import cn.novalon.gym.manage.groupcourse.domain.GroupCourse;
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseRecommend;
import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRecommendRepository;
import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseRepository;
import cn.novalon.gym.manage.groupcourse.service.IGroupCourseRecommendService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class GroupCourseRecommendService implements IGroupCourseRecommendService {

    private static final Logger logger = LoggerFactory.getLogger(GroupCourseRecommendService.class);

    private final IGroupCourseRecommendRepository recommendRepository;
    private final IGroupCourseRepository groupCourseRepository;

    public GroupCourseRecommendService(IGroupCourseRecommendRepository recommendRepository,
                                       IGroupCourseRepository groupCourseRepository) {
        this.recommendRepository = recommendRepository;
        this.groupCourseRepository = groupCourseRepository;
    }

    @Override
    public Mono<GroupCourseRecommend> findById(Long id) {
        return recommendRepository.findById(id)
                .flatMap(this::fillGroupCourseInfo);
    }

    @Override
    public Flux<GroupCourseRecommend> findAll() {
        return recommendRepository.findAll()
                .flatMap(this::fillGroupCourseInfo);
    }

    @Override
    public Flux<GroupCourseRecommend> findAll(String sortBy, String sortOrder) {
        return recommendRepository.findAll(sortBy, sortOrder)
                .flatMap(this::fillGroupCourseInfo);
    }

    @Override
    public Flux<GroupCourseRecommend> findAllActive() {
        return recommendRepository.findAllActive()
                .flatMap(this::fillGroupCourseInfo);
    }

    @Override
    public Flux<GroupCourseRecommend> findByCourseId(Long courseId) {
        return recommendRepository.findByCourseId(courseId)
                .flatMap(this::fillGroupCourseInfo);
    }

    @Override
    public Mono<GroupCourseRecommend> create(GroupCourseRecommend recommend) {
        if (recommend.getCourseId() == null) {
            return Mono.error(new RuntimeException("团课ID不能为空"));
        }

        return groupCourseRepository.findByIdAndDeletedAtIsNull(recommend.getCourseId())
                .switchIfEmpty(Mono.error(new RuntimeException("团课不存在")))
                .flatMap(course -> {
                    return recommendRepository.save(recommend)
                            .doOnSuccess(r -> logger.info("团课推荐创建成功 - id={}, courseId={}", r.getId(), r.getCourseId()))
                            .doOnError(error -> logger.error("团课推荐创建失败 - error: {}", error.getMessage()));
                });
    }

    @Override
    public Mono<GroupCourseRecommend> update(Long id, GroupCourseRecommend recommend) {
        return recommendRepository.findById(id)
                .switchIfEmpty(Mono.error(new RuntimeException("团课推荐不存在")))
                .flatMap(existing -> {
                    if (recommend.getRecommendTitle() != null) {
                        existing.setRecommendTitle(recommend.getRecommendTitle());
                    }
                    if (recommend.getRecommendContent() != null) {
                        existing.setRecommendContent(recommend.getRecommendContent());
                    }
                    if (recommend.getRecommendReason() != null) {
                        existing.setRecommendReason(recommend.getRecommendReason());
                    }
                    if (recommend.getPriority() != null) {
                        existing.setPriority(recommend.getPriority());
                    }
                    if (recommend.getIsActive() != null) {
                        existing.setIsActive(recommend.getIsActive());
                    }
                    if (recommend.getCourseId() != null) {
                        existing.setCourseId(recommend.getCourseId());
                    }

                    return recommendRepository.update(existing);
                })
                .doOnSuccess(r -> logger.info("团课推荐更新成功 - id={}", id))
                .doOnError(error -> logger.error("团课推荐更新失败 - id={}, error: {}", id, error.getMessage()));
    }

    @Override
    public Mono<Void> delete(Long id) {
        return recommendRepository.findById(id)
                .switchIfEmpty(Mono.error(new RuntimeException("团课推荐不存在")))
                .flatMap(recommend -> {
                    return recommendRepository.deleteById(id)
                            .doOnSuccess(v -> logger.info("团课推荐删除成功 - id={}", id))
                            .doOnError(error -> logger.error("团课推荐删除失败 - id={}, error: {}", id, error.getMessage()));
                });
    }

    @Override
    public Mono<GroupCourseRecommend> enable(Long id) {
        return recommendRepository.updateActiveStatus(id, true)
                .switchIfEmpty(Mono.error(new RuntimeException("团课推荐不存在")))
                .doOnSuccess(r -> logger.info("团课推荐启用成功 - id={}", id))
                .doOnError(error -> logger.error("团课推荐启用失败 - id={}, error: {}", id, error.getMessage()));
    }

    @Override
    public Mono<GroupCourseRecommend> disable(Long id) {
        return recommendRepository.updateActiveStatus(id, false)
                .switchIfEmpty(Mono.error(new RuntimeException("团课推荐不存在")))
                .doOnSuccess(r -> logger.info("团课推荐禁用成功 - id={}", id))
                .doOnError(error -> logger.error("团课推荐禁用失败 - id={}, error: {}", id, error.getMessage()));
    }

    private Mono<GroupCourseRecommend> fillGroupCourseInfo(GroupCourseRecommend recommend) {
        if (recommend.getCourseId() == null) {
            return Mono.just(recommend);
        }

        return groupCourseRepository.findByIdAndDeletedAtIsNull(recommend.getCourseId())
                .map(course -> {
                    recommend.setGroupCourse(course);
                    return recommend;
                })
                .defaultIfEmpty(recommend);
    }
}