package com.storlead.framework.mybatis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.storlead.framework.common.constant.CommonConstant;
import com.storlead.framework.common.util.DateUtils;
import com.storlead.framework.common.util.SpringContextUtils;
import com.storlead.framework.mybatis.entity.SysBaseField;
import com.storlead.framework.mybatis.mapper.MyBaseMapper;
import com.storlead.framework.mybatis.query.QueryBaseEntity;
import com.storlead.framework.mybatis.service.MyBaseService;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


/**
 * @program: sp-sales-platform
 * @description:
 * @author: chenkq
 * @create: 2024-04-02 15:31
 */
public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T extends SysBaseField> extends ServiceImpl<M, T> implements MyBaseService<T> {
    @Override
    public <R extends SysBaseField, E extends QueryBaseEntity> List<R> listWithScopeVo(IPage page, E e) {
        assemblyDataSource(e);
        return this.baseMapper.list(page,e);
    }

    @Override
    public List<T> listWith(IPage page, LambdaQueryWrapper<T> wrapper) {
        return this.baseMapper.list(page,wrapper);
    }

    @Override
    public <R extends SysBaseField, E extends QueryBaseEntity> List<R> listWithScopeVo(IPage page, LambdaQueryWrapper<T> wrapper,E e) {
        assemblyDataSource(wrapper,e,"");
        return this.baseMapper.list(page,wrapper);
    }

    @Override
    public <R extends SysBaseField, E extends QueryBaseEntity> List<R> pageWithScopelist(IPage page, LambdaQueryWrapper<T> wrapper) {
        assemblyDataOnlySource(wrapper,"");
        return this.baseMapper.list(page,wrapper);
    }

    @Override
    public <R extends SysBaseField, E extends QueryBaseEntity> List<R> pageWithScopelist(IPage page, LambdaQueryWrapper<T> wrapper,String mergeSql) {
        assemblyDataOnlySource(wrapper,mergeSql);
        return this.baseMapper.list(page,wrapper);
    }

    @Override
    public <R extends SysBaseField> List<R> listWithScopeVo(LambdaQueryWrapper<T> wrapper) {
        assemblyDataOnlySource(wrapper,"");
        return this.baseMapper.list(wrapper);
    }



    @Override
    public  List<T> listWithScope(LambdaQueryWrapper<T> wrapper) {
        assemblyDataOnlySource(wrapper,"");
        return this.baseMapper.selectList(wrapper);
    }
    @Override
    public  List<T> listWithScope(LambdaQueryWrapper<T> wrapper,String mergeSql) {
        assemblyDataOnlySource(wrapper,mergeSql);
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public  <R extends SysBaseField> IPage<R> listWithScopeVo(IPage page, LambdaQueryWrapper<T> wrapper) {
        assemblyDataOnlySource(wrapper,"");
        return this.baseMapper.selectPage(page,wrapper);
    }

    @Override
    public  IPage<T> pageWithScope(IPage page, LambdaQueryWrapper<T> wrapper) {
        assemblyDataOnlySource(wrapper,"");
        return this.baseMapper.selectPage(page,wrapper);
    }

    @Override
    public  IPage pageWithScope(IPage page, LambdaQueryWrapper<T> wrapper,String mergeSql) {
        assemblyDataOnlySource(wrapper,mergeSql);
        return this.baseMapper.selectPage(page,wrapper);
    }

    @Override
    public  <E extends QueryBaseEntity> IPage<T> pageWithScope(IPage page, LambdaQueryWrapper<T> wrapper, E e, String mergeSql) {
        assemblyDataSource(wrapper, e,mergeSql);
        return this.baseMapper.selectPage(page,wrapper);
    }

    @Override
    public <E extends QueryBaseEntity> List<T> listWithScope(LambdaQueryWrapper<T> wrapper,E e,String mergeSql) {
        assemblyDataSource(wrapper,e,mergeSql);
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public  <E extends QueryBaseEntity> Integer selectCount(LambdaQueryWrapper<T> wrapper,E e,String mergeSql) {
        assemblyDataSource(wrapper, e,mergeSql);
        return this.baseMapper.selectCount(wrapper);
    }

    @Override
    public  Integer selectCount(LambdaQueryWrapper<T> wrapper,String mergeSql) {
        assemblyDataOnlySource(wrapper,mergeSql);
        return this.baseMapper.selectCount(wrapper);
    }

    @Override
    public Boolean lgDelete(Long id) {
        if (Objects.isNull(id)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",id);
        updateWrapper.set("is_delete", CommonConstant.DEL_FLAG_1);
        updateWrapper.set("update_time", DateUtils.now());
        return this.update(updateWrapper);
    }

    @Override
    public Boolean lgCustomerDelete(Long customerId) {
        if (Objects.isNull(customerId)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("customer_id",customerId);
        updateWrapper.set("is_delete",CommonConstant.DEL_FLAG_1);
        updateWrapper.set("update_time", DateUtils.now());
        return this.update(updateWrapper);
    }

    @Override
    public Boolean lgCustomerListDelete(List<Long> customerIdList) {
        if (CollectionUtils.isEmpty(customerIdList)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("customer_id",customerIdList);
        updateWrapper.set("is_delete",CommonConstant.DEL_FLAG_1);
        updateWrapper.set("update_time",DateUtils.now());
        return this.update(updateWrapper);
    }

    @Override
    public Boolean lgDelete(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",ids);
        updateWrapper.set("is_delete",CommonConstant.DEL_FLAG_1);
        return this.update(updateWrapper);
    }

    @Override
    public List<T> listByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return null;
        }
        QueryWrapper query = new QueryWrapper<>();
        query.in("id",ids);
        return this.list(query);
    }

    @Override
    public Boolean changeCustomerId(Long fromId, Long customerId) {
        if (Objects.isNull(customerId) || Objects.isNull(fromId)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("customer_id",fromId);
        updateWrapper.set("customer_id",customerId);
        return this.update(updateWrapper);
    }

    @Override
    public boolean changeResourceTypeId(String resourceType, Long fromId, Long id) {
        if (Objects.isNull(id) || Objects.isNull(fromId)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("resource_type",resourceType);
        updateWrapper.eq("resource_type_id",fromId);
        updateWrapper.set("resource_type_id",id);
        return this.update(updateWrapper);
    }

    @Override
    public boolean deleteByResourceId(String resourceType, Long resourceTypeId) {
        if (Objects.isNull(resourceTypeId)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("resource_type",resourceType);
        updateWrapper.eq("resource_type_id",resourceTypeId);
        updateWrapper.set("is_delete",CommonConstant.DEL_FLAG_1);
        return this.update(updateWrapper);
    }

    @Override
    public boolean deleteByResourceIds(String resourceType, List<Long> resourceTypeIds) {
        if (CollectionUtils.isEmpty(resourceTypeIds)) {
            return false;
        }
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("resource_type",resourceType);
        updateWrapper.in("resource_type_id",resourceTypeIds);
        updateWrapper.set("is_delete",CommonConstant.DEL_FLAG_1);
        return this.update(updateWrapper);
    }

    @Override
    public List<T> listByResourceId(String resourceType, Long resourceTypeId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("resource_type",resourceType);
        wrapper.eq("resource_type_id",resourceTypeId);
        return this.baseMapper.selectList(wrapper);
    }

    @Override
    public List<T> listByResourceIds(String resourceType, List<Long> resourceTypeIds) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("resource_type",resourceType);
        wrapper.in("resource_type_id",resourceTypeIds);
        return this.baseMapper.selectList(wrapper);
    }

    private <E extends QueryBaseEntity> void assemblyDataSource(LambdaQueryWrapper<T> wrapper,E e,String mergeSql) {
        try {
            log.error("进入assemblyDataSource---LambdaQueryWrapper");
            Object myClassInstance = SpringContextUtils.getBean("dataScope");
            Class<?> clazz = myClassInstance.getClass();
            Method method = clazz.getMethod("assemblyDataWrapperPurview", LambdaQueryWrapper.class,QueryBaseEntity.class,String.class);
            // 调用未编写的方法
            method.invoke(myClassInstance,wrapper,e,mergeSql);
        } catch (Exception e1) {
            log.error("方法不存在",e1);
        }
    }

    private <E extends QueryBaseEntity> void assemblyDataOnlySource(LambdaQueryWrapper<T> wrapper,String mergeSql) {
        try {
            log.error("进入assemblyDataSource---LambdaQueryWrapper");
            Object myClassInstance = SpringContextUtils.getBean("dataScope");
            Class<?> clazz = myClassInstance.getClass();
            Method method = clazz.getMethod("assemblyDataOnlyWrapper", LambdaQueryWrapper.class,String.class);
            // 调用未编写的方法
            method.invoke(myClassInstance,wrapper,mergeSql);
        } catch (Exception e1) {
            log.error("方法不存在",e1);
        }
    }

    private <E extends QueryBaseEntity> void assemblyDataSource(E e) {
        try {
            log.error("assemblyDataSource---QueryBaseEntity");

            // 假设我们有一个类名为"MyClass"但没有编写该类的实例
            Class<?> clazz = Class.forName("DataScope");
            // 使用反射创建一个实例
            Object myClassInstance = clazz.newInstance();
            // 使用反射获取方法
            Method method = clazz.getMethod("assemblyDataEntityPurview", QueryBaseEntity.class);
            // 调用未编写的方法
            method.invoke(myClassInstance, e);
        } catch (Exception e1) {
            log.error("方法不存在",e1);
        }
    }

    @Override
    public T getNextById(Serializable currentId, LambdaQueryWrapper<T> queryWrapper) {
        return findAdjacentById(currentId, queryWrapper, true);
    }

    @Override
    public T getPreviousById(Serializable currentId, LambdaQueryWrapper<T> queryWrapper) {
        return findAdjacentById(currentId, queryWrapper, false);
    }

    private T findAdjacentById(Serializable currentId, LambdaQueryWrapper<T> queryWrapper, boolean isNext) {
        // 确保ID字段被正确排序
//        LambdaQueryWrapper.orderByAsc("id");

        try {
            // 获取所有满足条件的数据
            List<T> allData = listWithScope(queryWrapper);

            // 查找目标ID的索引
//            int index = allData.indexOf(allData.stream().filter(record -> currentId.equals(getIdFromRecord(record))).findFirst().orElseThrow());
//
//            // 检查索引是否有效
//            if (index < 0 || index >= allData.size()) {
//                return null;
//            }
            if(CollectionUtils.isEmpty(allData) || allData.size()==1){
                return null;
            }
            return allData.get(1);

            // 获取前一个和后一个元素（如果存在）
//            if (isNext && index < allData.size() - 1){
//                return allData.get(index + 1);
//            }else if (!isNext && index > 0){
//                return allData.get(index - 1);
//            }
//            return null;

        }catch (Exception e){
            return null;
//            throw new IllegalStateException("Unexpected condition encountered while finding adjacent ID.");
        }

    }

    // 假设所有实体类都有一个名为"id"的属性来获取ID，这里简化处理
    private Serializable getIdFromRecord(T record) {
        try {
            return (Serializable) record.getClass().getMethod("getId").invoke(record);
        } catch (Exception e) {
            throw new RuntimeException("Unable to get ID from record", e);
        }
    }

//    public T getOldEntityById(Class<T> clazz, Long id) {
//        return getById(id);
//    }

    public Class<T> getEntityClass(){
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];

    }
}
