package com.pictc.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.jdbc.model.QueryParameter;
import com.pictc.utils.CollectionUtils;


public class JdbcTools {
	
	/**
	 * 执行增删改sql
	 * */
	public static int execute(String sql) {
		return execute(sql, null);
	}
	
	/**
	 * 执行增删改sql
	 * */
	public static int execute(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setParams(params);
			return context.executeUpdate();
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 批量操作
	 * */
	public static int executeBatch(String sql,List<List<JdbcParam>> batchParams) {
		return executeBatch(sql,-1, batchParams);
	}
	
	/**
	 * 批量操作
	 * */
	public static int executeBatch(String sql,int step,List<List<JdbcParam>> batchParams){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setBatchParams(batchParams);
			return context.executeBatch(step);
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 查询基础数据类型
	 * */
	public static <T>T queryPrimitive(String sql,Class<T> type,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			while (set.next()) {
				return ResultSetUtils.getObject(set,1,type);
			}
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
		return null;
	}
	
	/**
	 * 查询基础数据类型
	 * */
	public static <T>List<T> queryListPrimitive(String sql,Class<T> type,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			List<T> res = CollectionUtils.newArrayList();
			while (set.next()) {
				res.add(ResultSetUtils.getObject(set,1,type));
			}
			return res;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 查询对象
	 * */
	public static JSONObject queryObj(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			Map<String, String> names = ResultSetUtils.getMapColumns(set);
			while (set.next()) {
				JSONObject obj = new JSONObject();
				for (String key : names.keySet()) {
					obj.put(names.get(key),set.getObject(key));
				}
				return obj;
			}
			return null;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	
	/**
	 * 查询集合
	 * */
	public static JSONArray queryArray(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true,false);
			context.init(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			Map<String, String> names = ResultSetUtils.getMapColumns(set);
			JSONArray result = new JSONArray();
			while (set.next()) {
				JSONObject obj = new JSONObject();
				for (String key : names.keySet()) {
					obj.put(names.get(key),set.getObject(key));
				}
				result.add(obj);
			}
			return result;
		}  catch (SQLException e) {
			throw context.createException(e);
		} finally {
			context.end();
		}
	}
	
	/**
	 * 执行存储过程返回基础数据类型
	 * */
	public static void call(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true);
			context.initCall(sql);
			context.setParams(params);
			context.execute();
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 执行存储过程返回基础数据类型
	 * */
	public static <T>T callPrimitive(String sql,Class<T> type,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true);
			context.initCall(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			while (set.next()) {
				return ResultSetUtils.getObject(set,1,type);
			}
			return null;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 执行存储过程返回基础数据类型
	 * */
	public static <T>List<T> callListPrimitive(String sql,Class<T> type,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true);
			context.initCall(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			List<T> res = CollectionUtils.newArrayList();
			while (set.next()) {
				res.add(ResultSetUtils.getObject(set,1,type));
			}
			return res;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	/**
	 * 执行存储过程返回对象
	 * */
	public static JSONObject callObj(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true);
			context.initCall(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			Map<String, String> names = ResultSetUtils.getMapColumns(set);
			while (set.next()) {
				JSONObject obj = new JSONObject();
				for (String key : names.keySet()) {
					obj.put(names.get(key),set.getObject(key));
				}
				return obj;
			}
			return null;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	
	/**
	 * 执行存储过程，返回集合
	 * */
	public static JSONArray callArray(String sql,List<JdbcParam> params){
		JdbcContext context = null;
		try {
			context = new JdbcContext(true);
			context.initCall(sql);
			context.setParams(params);
			ResultSet set = context.executeQuery();
			Map<String, String> names = ResultSetUtils.getMapColumns(set);
			JSONArray result = new JSONArray();
			while (set.next()) {
				JSONObject obj = new JSONObject();
				for (String key : names.keySet()) {
					obj.put(names.get(key),set.getObject(key));
				}
				result.add(obj);
			}
			return result;
		}  catch (SQLException e) {
			throw context.createException(e);
		}finally {
			context.end();
		}
	}
	
	//IPage<DemoCustomer>
	public static IPage<JSONObject> queryPage(String baseSql,QueryParameter param) {
		SqlBuilder sql = new SqlBuilder();
		sql.append(baseSql);
		List<JdbcParam> params =  QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
		
		SqlBuilder countSql = new SqlBuilder();
		countSql.select().append(" count(*) ").from().leftBracket().append(sql).rightBracket().as().append("TMP_CT");
		Long total = queryPrimitive(countSql.toString(),Long.class,params);
		
		List<JdbcParam> pageParams = CollectionUtils.newArrayList();
		for (JdbcParam item : params) {
			pageParams.add(item);
		}
		
		int start = (param.getIndex()-1)*param.getSize();
		pageParams.add(new JdbcParam().setVal(param.getSize()).setJdbc(Types.INTEGER).setJavaType(Integer.class));
		pageParams.add(new JdbcParam().setVal(start).setJdbc(Types.INTEGER).setJavaType(Integer.class));
		
		QueryParameterUtils.parseOrders(sql, param.getOrders());
		SqlBuilder pageSql = new SqlBuilder();
		pageSql.append(sql.toString());
		pageSql.limitFull();
		
		JSONArray list = queryArray(pageSql.toString(), pageParams);
		List<JSONObject> records = CollectionUtils.newArrayList();
		if(list!=null) {
			for (int i = 0; i < list.size(); i++) {
				records.add(list.getJSONObject(i));
			}
		}
		Page<JSONObject> page = new Page<>(param.getIndex(),param.getSize(),total);
		page.setRecords(records);
		return page;
	}

	public static JSONArray query(String baseSql,QueryParameter param){
		SqlBuilder sql = new SqlBuilder();
		sql.append(baseSql);
		List<JdbcParam> params = QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
		QueryParameterUtils.parseOrders(sql, param.getOrders());
		return queryArray(sql.toString(), params);
	}
	
	
	public static JSONObject queryObj(String baseSql,QueryParameter param){
		SqlBuilder sql = new SqlBuilder();
		sql.append(baseSql);
		List<JdbcParam> params = QueryParameterUtils.toJdbcParams(sql, param.getAllCriterias());
		QueryParameterUtils.parseOrders(sql, param.getOrders());
		return queryObj(sql.toString(), params);
	}

}
