package cn.ibizlab.core.lite.extensions.service;

import cn.ibizlab.core.extensions.mapper.DbEntityMapper;
import cn.ibizlab.core.extensions.service.DstDataSourceExService;
import cn.ibizlab.core.lite.extensions.domain.EntityModel;
import cn.ibizlab.core.lite.extensions.domain.EntityObj;
import cn.ibizlab.core.lite.extensions.domain.FieldModel;
import cn.ibizlab.core.lite.extensions.domain.ModelObj;
import cn.ibizlab.core.lite.extensions.filter.DbEntitySearchContext;
import cn.ibizlab.core.lite.extensions.model.DataModel;
import cn.ibizlab.util.filter.QueryFilter;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisCursorItemReader;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.Reader;
import java.sql.Timestamp;
import java.util.*;

@Service
@Primary
@Slf4j
public class DbEntityService extends ServiceImpl<DbEntityMapper, EntityObj> implements CommonEntityService {



    @Autowired
    private DstDataSourceExService dstDataSourceService;



    @Override
    public List<EntityObj> selectBase(EntityModel entityModel, QueryFilter filter) {
        return search("BASE", entityModel, filter);
    }

    @Override
    public List<EntityObj> selectCore(EntityModel entityModel, QueryFilter filter) {
        return search("CORE", entityModel, filter);
    }

    @Override
    public Integer selectCount(EntityModel entityModel, QueryFilter filter) {
        String sql = entityModel.getSqlSegment("COUNT");
        String dsName = entityModel.getDsName();
        try {
            dstDataSourceService.initDataSource(dsName);
            DynamicDataSourceContextHolder.push(dsName);
            DbEntitySearchContext context = new DbEntitySearchContext();
            context.setFilter(filter);
            QueryWrapper qw = context.getSelectCond();
            if (!StringUtils.isEmpty(filter.getCustSqlSegment()))
                qw.apply(filter.getCustSqlSegment());

            Integer count = baseMapper.searchCount(sql, qw);

            return count;
        } catch (Exception ex) {
            log.error("详细错误信息：" + ex.getMessage() + ", 执行sql：" + sql);
            return null;
        } finally {
            DynamicDataSourceContextHolder.poll();
        }
    }

    @Override
    public List<EntityObj> search(String dataSet, EntityModel entityModel, QueryFilter filter) {

        String sql = entityModel.getSqlSegment(dataSet);
        if (StringUtils.isEmpty(sql))
            return new ArrayList<>();
        else
            return search(entityModel.getDsName(), sql, filter);
    }

    @Override
    public List<EntityObj> search(String dsName, String sql, QueryFilter filter) {
        try {
            dstDataSourceService.initDataSource(dsName);
            DynamicDataSourceContextHolder.push(dsName);
            DbEntitySearchContext context = new DbEntitySearchContext();
            context.setFilter(filter);
            QueryWrapper qw = context.getSelectCond();
            if (!StringUtils.isEmpty(filter.getCustSqlSegment()))
                qw.apply(filter.getCustSqlSegment());

            List<EntityObj> list = baseMapper.search(sql, qw);
            list.forEach(entityObj -> {
                entityObj.keySet().forEach(key -> {

                    Object value = entityObj.get(key);
                    if (value != null && value instanceof java.sql.Clob) {
                        // Clob类型 转String
                        BufferedReader br = null;
                        Reader is = null;
                        try {
                            String reString = "";
                            is = ((java.sql.Clob) value).getCharacterStream();
                            br = new BufferedReader(is);
                            String s = br.readLine();
                            StringBuffer sb = new StringBuffer();
                            while (s != null) {
                                sb.append(s);
                                s = br.readLine();
                            }
                            reString = sb.toString();

                            entityObj.put(key, reString);
                        } catch (Exception ex) {

                        } finally {
                            try {
                                if (br != null) {
                                    br.close();
                                }
                            } catch (Exception ex) {
                            }
                            try {
                                if (is != null) {
                                    is.close();
                                }
                            } catch (Exception ex) {
                            }

                        }

                    }
                });
            });
            return list;
        } catch (Exception ex) {
            log.error("详细错误信息：" + ex.getMessage() + ", 执行sql：" + sql);
            return null;
        } finally {
            DynamicDataSourceContextHolder.poll();
        }
    }





    @Autowired
    @Lazy
    private SqlSessionFactory sqlSessionFactory;
    private int processSize = 500;
    @Override
    public void processList(DataModel dataModel,Timestamp lastModify,LiteDataCallback callback)
    {
        EntityModel entityModel=dataModel.getFactEntityModel();
        FieldModel lastModifyField=entityModel.getLastModifyField();
        QueryFilter filter=new QueryFilter();
        if(lastModifyField!=null)
            filter.ge(lastModifyField.getColumnName(), lastModify);

        //记录处理的总业务数据量
        String sql=entityModel.getSqlSegment("CORE");
        Integer total = this.selectCount(entityModel, filter);

        callback.total(total);


        MyBatisCursorItemReader myMyBatisCursorItemReader =new MyBatisCursorItemReader();
        try{
            myMyBatisCursorItemReader.setSqlSessionFactory(sqlSessionFactory);
            myMyBatisCursorItemReader.setQueryId("cn.ibizlab.core.extensions.mapper.DbEntityMapper.search");

            DbEntitySearchContext context=new DbEntitySearchContext();
            context.setFilter(filter);
            QueryWrapper qw=context.getSelectCond();
            if(!StringUtils.isEmpty(filter.getCustSqlSegment()))
                qw.apply(filter.getCustSqlSegment());

            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("sql", sql);
            paramsMap.put("ew", qw);
            myMyBatisCursorItemReader.setParameterValues(paramsMap);// 设置sql传入参数

            dstDataSourceService.initDataSource(entityModel.getDsName());
            DynamicDataSourceContextHolder.push(entityModel.getDsName());
            myMyBatisCursorItemReader.open(new ExecutionContext()); // 开启游标
            DynamicDataSourceContextHolder.poll();
            List<EntityObj> datas = new ArrayList<>();
            EntityObj rowdata;
            while ((rowdata = (EntityObj) myMyBatisCursorItemReader.read()) != null) {
                datas.add(rowdata);
                if(datas.size() >= processSize){
                    boolean rt=callback.processData(datas);
                    datas.clear();
                    if(!rt)
                        break;
                }
            }
            if(datas.size() > 0){
                callback.processData(datas);
                datas.clear();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                myMyBatisCursorItemReader.close();// 关闭游标
            } catch (Exception ex) {
                //log.error(ex.getMessage());
            }
            DynamicDataSourceContextHolder.poll();
        }
    }


}
