package cn.stylefeng.team.project.modular.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.team.project.api.entity.Business;
import cn.stylefeng.team.project.api.entity.BusinessCategory;
import cn.stylefeng.team.project.modular.business.enums.BusinessCategoryExceptionEnum;
import cn.stylefeng.team.project.modular.business.mapper.BusinessCategoryMapper;
import cn.stylefeng.team.project.modular.business.pojo.request.BusinessCategoryRequest;
import cn.stylefeng.team.project.modular.business.service.BusinessCategoryService;
import cn.stylefeng.team.project.modular.business.service.BusinessService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BusinessCategoryServiceImpl extends ServiceImpl<BusinessCategoryMapper, BusinessCategory> implements BusinessCategoryService {

    @Resource
    private BusinessService businessService;

    @Override
    public void add(BusinessCategoryRequest businessCategoryRequest) {
        BusinessCategory businessCategory = new BusinessCategory();
        BeanUtil.copyProperties(businessCategoryRequest, businessCategory);
        this.save(businessCategory);
    }

    @Override
    public void del(BusinessCategoryRequest businessCategoryRequest) {
        BusinessCategory businessCategory = this.queryBusinessCategory(businessCategoryRequest);
        this.removeById(businessCategory.getBusinessCategoryId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDelete(BusinessCategoryRequest businessCategoryRequest) {
        this.removeByIds(businessCategoryRequest.getBatchDeleteIdList());
    }

    @Override
    public void edit(BusinessCategoryRequest businessCategoryRequest) {
        BusinessCategory businessCategory = this.queryBusinessCategory(businessCategoryRequest);
        BeanUtil.copyProperties(businessCategoryRequest, businessCategory);
        this.updateById(businessCategory);
    }

    @Override
    public BusinessCategory detail(BusinessCategoryRequest businessCategoryRequest) {
        return this.queryBusinessCategory(businessCategoryRequest);
    }

    @Override
    public PageResult<BusinessCategory> findPage(BusinessCategoryRequest businessCategoryRequest) {
        LambdaQueryWrapper<BusinessCategory> wrapper = createWrapper(businessCategoryRequest);
        Page<BusinessCategory> pageList = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(pageList);
    }

    @Override
    public List<BusinessCategory> getBusinessTree(BusinessCategoryRequest businessCategoryRequest) {

        String searchText = businessCategoryRequest.getSearchText();

        businessCategoryRequest.setSearchText(null);
        LambdaQueryWrapper<BusinessCategory> queryWrapper = this.createWrapper(businessCategoryRequest);
        queryWrapper.select(BusinessCategory::getBusinessCategoryId, BusinessCategory::getCategoryName);
        queryWrapper.orderByAsc(BusinessCategory::getFldSort);
        List<BusinessCategory> categoryList = this.list(queryWrapper);
        if (ObjectUtil.isEmpty(categoryList)) {
            return new ArrayList<>();
        }

        List<Long> categoryIdList = categoryList.stream().map(BusinessCategory::getBusinessCategoryId).collect(Collectors.toList());
        List<Business> businessList = this.businessService.getCategoryBusinessList(categoryIdList, searchText);

        for (BusinessCategory businessCategory : categoryList) {

            ArrayList<Business> businesses = new ArrayList<>();
            for (Business business : businessList) {
                if (business.getBusinessCategoryId().equals(businessCategory.getBusinessCategoryId())) {
                    businesses.add(business);
                }
            }

            businessCategory.setBusinessList(businesses);
        }

        return categoryList;
    }

    @Override
    public List<BusinessCategory> getTotalBusinessCategory() {

        LambdaQueryWrapper<BusinessCategory> wrapper = new LambdaQueryWrapper<>();

        wrapper.select(BusinessCategory::getCategoryName, BusinessCategory::getBusinessCategoryId);

        return this.list(wrapper);
    }

    @Override
    public List<BusinessCategory> findList(BusinessCategoryRequest businessCategoryRequest) {
        LambdaQueryWrapper<BusinessCategory> wrapper = this.createWrapper(businessCategoryRequest);

        wrapper.select(BusinessCategory::getBusinessCategoryId, BusinessCategory::getCategoryName);

        return this.list(wrapper);
    }

    @Override
    public List<BusinessCategory> getCategoryList(Long businessCategoryId) {

        LambdaQueryWrapper<BusinessCategory> businessCategoryLambdaQueryWrapper = new LambdaQueryWrapper<>();

        if (ObjectUtil.isNotEmpty(businessCategoryId)) {
            businessCategoryLambdaQueryWrapper.eq(BusinessCategory::getBusinessCategoryId, businessCategoryId);
        }

        businessCategoryLambdaQueryWrapper.orderByAsc(BusinessCategory::getFldSort);

        businessCategoryLambdaQueryWrapper.select(BusinessCategory::getBusinessCategoryId, BusinessCategory::getCategoryName,
                BusinessCategory::getCategoryCode);

        return this.list(businessCategoryLambdaQueryWrapper);
    }

    @Override
    public String getCategoryName(Long categoryId) {

        if (ObjectUtil.isEmpty(categoryId)) {
            return null;
        }

        LambdaQueryWrapper<BusinessCategory> businessCategoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        businessCategoryLambdaQueryWrapper.eq(BusinessCategory::getBusinessCategoryId, categoryId);
        businessCategoryLambdaQueryWrapper.select(BusinessCategory::getCategoryName);
        BusinessCategory businessCategory = this.getOne(businessCategoryLambdaQueryWrapper, false);

        if (businessCategory == null) {
            return null;
        }

        return businessCategory.getCategoryName();
    }

    private BusinessCategory queryBusinessCategory(BusinessCategoryRequest businessCategoryRequest) {
        BusinessCategory businessCategory = this.getById(businessCategoryRequest.getBusinessCategoryId());
        if (ObjectUtil.isEmpty(businessCategory)) {
            throw new ServiceException(BusinessCategoryExceptionEnum.BUSINESS_CATEGORY_NOT_EXISTED);
        }
        return businessCategory;
    }

    private LambdaQueryWrapper<BusinessCategory> createWrapper(BusinessCategoryRequest businessCategoryRequest) {
        LambdaQueryWrapper<BusinessCategory> queryWrapper = new LambdaQueryWrapper<>();

        String searchText = businessCategoryRequest.getSearchText();
        if (StrUtil.isNotBlank(searchText)) {
            queryWrapper.like(BusinessCategory::getCategoryName, searchText);
            queryWrapper.or().like(BusinessCategory::getCategoryCode, searchText);
        }

        queryWrapper.orderByAsc(BusinessCategory::getFldSort);

        return queryWrapper;
    }
}
