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

import cn.novalon.gym.manage.groupcourse.converter.GroupCourseConverter;
import cn.novalon.gym.manage.groupcourse.dao.GroupCourseTypeDao;
import cn.novalon.gym.manage.groupcourse.domain.GroupCourseType;
import cn.novalon.gym.manage.groupcourse.entity.GroupCourseTypeEntity;
import cn.novalon.gym.manage.groupcourse.repository.IGroupCourseTypeRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;

@Repository
@Transactional
public class GroupCourseTypeRepository implements IGroupCourseTypeRepository {

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

    private final GroupCourseTypeDao groupCourseTypeDao;
    private final GroupCourseConverter converter;

    public GroupCourseTypeRepository(GroupCourseTypeDao groupCourseTypeDao, GroupCourseConverter converter) {
        this.groupCourseTypeDao = groupCourseTypeDao;
        this.converter = converter;
    }

    @Override
    public Mono<GroupCourseType> findById(Long id) {
        return groupCourseTypeDao.findByIdIsAndDeletedAtIsNull(id)
                .map(converter::toGroupCourseType);
    }

    @Override
    public Flux<GroupCourseType> findAll() {
        return groupCourseTypeDao.findAll()
                .map(converter::toGroupCourseType);
    }

    @Override
    public Flux<GroupCourseType> findAll(boolean includeDeleted) {
        if (includeDeleted) {
            return groupCourseTypeDao.findAll()
                    .map(converter::toGroupCourseType);
        } else {
            return groupCourseTypeDao.findAllByDeletedAtIsNull()
                    .map(converter::toGroupCourseType);
        }
    }

    @Override
    public Flux<GroupCourseType> findByKeyword(String keyword) {
        if (keyword == null || keyword.isEmpty()) {
            return findAll(false);
        }
        return groupCourseTypeDao.findByTypeNameContainingAndDeletedAtIsNull(keyword)
                .map(converter::toGroupCourseType);
    }

    @Override
    public Flux<GroupCourseType> findByCategory(String category) {
        if (category == null || category.isEmpty()) {
            return findAll(false);
        }
        return groupCourseTypeDao.findByCategoryAndDeletedAtIsNull(category)
                .map(converter::toGroupCourseType);
    }

    @Override
    public Flux<GroupCourseType> findByCategoryAndKeyword(String category, String keyword) {
        Flux<GroupCourseType> result;
        
        if (category != null && !category.isEmpty()) {
            result = findByCategory(category);
        } else {
            result = findAll(false);
        }
        
        if (keyword != null && !keyword.isEmpty()) {
            result = result.filter(type -> type.getTypeName() != null && 
                    type.getTypeName().toLowerCase().contains(keyword.toLowerCase()));
        }
        
        return result;
    }

    @Override
    public Mono<GroupCourseType> findByTypeName(String typeName) {
        return groupCourseTypeDao.findByTypeNameAndDeletedAtIsNull(typeName)
                .map(converter::toGroupCourseType);
    }

    @Override
    public Mono<GroupCourseType> save(GroupCourseType groupCourseType) {
        GroupCourseTypeEntity entity = converter.toGroupCourseTypeEntity(groupCourseType);
        return groupCourseTypeDao.save(entity)
                .map(converter::toGroupCourseType);
    }

    @Override
    public Mono<GroupCourseType> update(GroupCourseType groupCourseType) {
        return groupCourseTypeDao.findByIdIsAndDeletedAtIsNull(groupCourseType.getId())
                .switchIfEmpty(Mono.error(new RuntimeException("团课类型不存在")))
                .flatMap(existing -> {
                    existing.markNotNew();
                    if (groupCourseType.getTypeName() != null) {
                        existing.setTypeName(groupCourseType.getTypeName());
                    }
                    if (groupCourseType.getBaseDifficulty() != null) {
                        existing.setBaseDifficulty(groupCourseType.getBaseDifficulty());
                    }
                    if (groupCourseType.getDescription() != null) {
                        existing.setDescription(groupCourseType.getDescription());
                    }
                    if (groupCourseType.getCategory() != null) {
                        existing.setCategory(groupCourseType.getCategory());
                    }
                    existing.setUpdatedAt(LocalDateTime.now());
                    return groupCourseTypeDao.save(existing);
                })
                .map(converter::toGroupCourseType);
    }

    @Override
    public Mono<Void> deleteById(Long id) {
        return groupCourseTypeDao.softDelete(id, LocalDateTime.now())
                .then();
    }
}