package cn.ibizlab.core.data.rest;

import cn.ibizlab.core.data.dto.BaseData;
import cn.ibizlab.core.data.dto.FilterData;
import cn.ibizlab.core.data.model.DSLink;
import cn.ibizlab.core.data.service.IDataService;
import cn.ibizlab.core.data.service.IPersistentService;
import cn.ibizlab.core.data.service.ModelService;
import cn.ibizlab.core.data.service.impl.BaseDataServiceImpl;
import cn.ibizlab.util.errors.BadRequestAlertException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@Slf4j
@Api(tags = {"数据" })
@RestController("api-persistent")
@RequestMapping({"/ibiz-database/{system}/{datasource}"})
public class PersistentResource
{
    @Autowired
	@Lazy
    public ModelService modelService;


    public IPersistentService getService(String datasource)
	{
		return modelService.getProxyService(datasource);
	}


    @ApiOperation(value = "新建数据", tags = {"数据" },  notes = "新建数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}","/{table}/create"})
    public ResponseEntity<BaseData> create(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam(name = "get",required = false) boolean get,
			@Validated @RequestBody BaseData baseData) {
		return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).create(system,table,datasource,baseData,get));
    }

    @ApiOperation(value = "批量新建数据", tags = {"数据" },  notes = "批量新建数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/batch","/{table}/createbatch"})
    public ResponseEntity<List<BaseData>> createBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody List<BaseData> baseDatas) {
        return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).createBatch(system,table,datasource,baseDatas,get));
    }

    @ApiOperation(value = "获取数据", tags = {"数据" },  notes = "获取数据")
	@RequestMapping(method = RequestMethod.GET, value = {"/{table}","/{table}/{key}"})
    public ResponseEntity<BaseData> get(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestParam Map map) {
		BaseData baseData=BaseData.fromContext(map);
        return doGet(system,table,datasource,key,baseData);
    }

	@ApiOperation(value = "获取数据", tags = {"数据" },  notes = "获取数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/get","/{table}/{key}/get"})
	public ResponseEntity<BaseData> doGet(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@Validated @RequestBody(required = false) BaseData baseData) {
		if(baseData==null)
		{
			if(StringUtils.isEmpty(key))
				throw new BadRequestAlertException("未找到要获取的键值信息",table,null);
			baseData=new BaseData();
		}
		return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).getByMap(system,table,datasource,baseData.setKey(key)));
	}

	@ApiOperation(value = "批量删除数据", tags = {"数据" },  notes = "批量删除数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/getbatch"})
	public ResponseEntity<List<BaseData>> getBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestBody List<Object> datas) {
    	if(ObjectUtils.isEmpty(datas))
    		return ResponseEntity.status(HttpStatus.OK).body(new ArrayList<>());
    	else if(datas.get(0) instanceof Map)
    		return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).getByMapBatch(system,table,datasource,(List)datas));
    	else
			return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).getBatch(system,table,datasource,(List)datas));
	}

    @ApiOperation(value = "删除数据", tags = {"数据" },  notes = "删除数据")
	@RequestMapping(method = RequestMethod.DELETE, value = {"/{table}","/{table}/{key}"})
    public ResponseEntity<Boolean> remove(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestParam Map map) {
		BaseData baseData=BaseData.fromContext(map);
		return doRemove(system,table,datasource,key,baseData);
    }

	@ApiOperation(value = "删除数据", tags = {"数据" },  notes = "删除数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/remove","/{table}/{key}/remove"})
	public ResponseEntity<Boolean> doRemove(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestBody(required = false) BaseData baseData) {
		if(baseData==null)
		{
			if(StringUtils.isEmpty(key))
				throw new BadRequestAlertException("未找到要删除的键值信息",table,null);
			baseData=new BaseData();
		}
		return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).removeByMap(system,table,datasource,baseData.setKey(key)));
	}

    @ApiOperation(value = "批量删除数据", tags = {"数据" },  notes = "批量删除数据")
	@RequestMapping(method = RequestMethod.DELETE, value = {"/{table}/batch"})
    public ResponseEntity<Boolean> removeBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestBody List datas) {
        return  doRemoveBatch(system,table,datasource,datas);
    }

	@ApiOperation(value = "批量删除数据", tags = {"数据" },  notes = "批量删除数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/removebatch"})
	public ResponseEntity<Boolean> doRemoveBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestBody List<Object> datas) {
		if(ObjectUtils.isEmpty(datas))
			return ResponseEntity.status(HttpStatus.OK).body(true);
		else if(datas.get(0) instanceof Map)
			return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).removeByMapBatch(system,table,datasource,(List)datas));
		else
			return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).removeBatch(system,table,datasource,(List)datas));
	}

    @ApiOperation(value = "更新数据", tags = {"数据" },  notes = "更新数据")
	@RequestMapping(method = RequestMethod.PUT, value = {"/{table}","/{table}/{key}"})
    public ResponseEntity<BaseData> update(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody BaseData baseData) {
        return doUpdate(system,table,datasource,key,get,baseData);
    }

	@ApiOperation(value = "更新数据", tags = {"数据" },  notes = "更新数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/update","/{table}/{key}/update"})
	public ResponseEntity<BaseData> doUpdate(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody BaseData baseData) {
		return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).update(system,table,datasource,baseData.setKey(key),get));
	}

    @ApiOperation(value = "批量更新数据", tags = {"数据" },  notes = "批量更新数据")
	@RequestMapping(method = RequestMethod.PUT, value = {"/{table}/batch"})
    public ResponseEntity<List<BaseData>> updateBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody List<BaseData> baseDatas) {
        return  doUpdateBatch(system,table,datasource,get,baseDatas);
    }

	@ApiOperation(value = "批量更新数据", tags = {"数据" },  notes = "批量更新数据")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/updatebatch"})
	public ResponseEntity<List<BaseData>> doUpdateBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody List<BaseData> baseDatas) {
		return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).updateBatch(system,table,datasource,baseDatas,get));
	}

    @ApiOperation(value = "检查数据", tags = {"数据" },  notes = "检查数据")
	@RequestMapping(method = {RequestMethod.GET}, value = {"/{table}/checkkey","/{table}/{key}/checkkey"})
    public ResponseEntity<Boolean> checkKey(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestParam Map map) {
		BaseData baseData=BaseData.fromContext(map);
        return  doCheckKey(system,table,datasource,key,baseData);
    }

	@ApiOperation(value = "检查数据", tags = {"数据" },  notes = "检查数据")
	@RequestMapping(method = {RequestMethod.POST}, value = {"/{table}/checkkey","/{table}/{key}/checkkey"})
	public ResponseEntity<Boolean> doCheckKey(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,
			@RequestBody(required = false) BaseData baseData) {
		if(baseData==null)
		{
			if(StringUtils.isEmpty(key))
				throw new BadRequestAlertException("未找到要检查的键值信息",table,null);
			baseData=new BaseData();
		}
		return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).checkKey(system,table,datasource,baseData.setKey(key)));
	}




    @ApiOperation(value = "保存数据", tags = {"数据" },  notes = "保存数据，自动判断插入和更新")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/save","/{table}/{key}/save"})
    public ResponseEntity<BaseData> save(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "key",required = false) String key,@RequestParam(name = "get",required = false) boolean get,
			@RequestBody BaseData baseData) {
        return ResponseEntity.status(HttpStatus.OK).body(getService(datasource).save(system,table,datasource,baseData.setKey(key),get));
    }

    @ApiOperation(value = "批量保存数据", tags = {"数据" },  notes = "批量保存数据，自动判断插入和更新")
	@RequestMapping(method = RequestMethod.POST, value = {"/{table}/savebatch"})
    public ResponseEntity<List<BaseData>> saveBatch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam(name = "get",required = false) boolean get,
			@RequestBody List<BaseData> baseDatas) {
        return  ResponseEntity.status(HttpStatus.OK).body(getService(datasource).saveBatch(system,table,datasource,baseDatas,get));
    }


	@ApiOperation(value = "Select查询数据", tags = {"数据" } ,notes = "Select查询数据，GET，返回body<list>+header<page,total>")
	@RequestMapping(method= RequestMethod.GET , value={"/{table}/select"})
	public ResponseEntity<List<BaseData>> select(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestParam Map map) {
		FilterData context=FilterData.fromContext(map);
		return doSelect(system,table,datasource,context);
	}

	@ApiOperation(value = "查询数据", tags = {"数据" } ,notes = "查询数据，POST，返回body<list>+header<page,total>")
	@RequestMapping(method= RequestMethod.POST , value={"/{table}/select"})
	public ResponseEntity<List<BaseData>> doSelect(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@RequestBody(required = false) FilterData context) {
		if(context==null)context=new FilterData();
		if(context.needPage()) {
			Page<BaseData> baseDatas = getService(datasource).select(system,table,datasource,context,context.getPageable()) ;
			List<BaseData> list = baseDatas.getContent();
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", String.valueOf(context.getPageable().getPageNumber()))
					.header("x-per-page", String.valueOf(context.getPageable().getPageSize()))
					.header("x-total", String.valueOf(baseDatas.getTotalElements()))
					.body(list);
		}
		else {
			List<BaseData> list = getService(datasource).select(system,table,datasource,context) ;
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", "0")
					.header("x-per-page", String.valueOf(list.size()))
					.header("x-total", String.valueOf(list.size()))
					.body(list);
		}
	}


	@ApiOperation(value = "获取数据集", tags = {"数据" } ,notes = "获取数据集，GET，返回body<list>+header<page,total>")
    @RequestMapping(method= RequestMethod.GET , value={"/{table}/fetch{dataset}"})
	public ResponseEntity<List<BaseData>> fetch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataset",required = true) String dataset,
			@RequestParam Map map) {
		FilterData context=FilterData.fromContext(map);
		return doFetch(system,table,datasource,dataset,context);
	}

	@ApiOperation(value = "获取数据集", tags = {"数据" } ,notes = "获取数据集，POST，返回body<list>+header<page,total>")
	@RequestMapping(method= RequestMethod.POST , value={"/{table}/fetch{dataset}"})
	public ResponseEntity<List<BaseData>> doFetch(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataset",required = true) String dataset,
			@RequestBody(required = false) FilterData context) {
		if(context==null)context=new FilterData();
		if(context.needPage()) {
			Page<BaseData> baseDatas = getService(datasource).fetch(system, table, datasource, dataset, context, context.getPageable());
			List<BaseData> list = baseDatas.getContent();
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", String.valueOf(context.getPageable().getPageNumber()))
					.header("x-per-page", String.valueOf(context.getPageable().getPageSize()))
					.header("x-total", String.valueOf(baseDatas.getTotalElements()))
					.body(list);
		}
		else {
			List<BaseData> list = getService(datasource).fetch(system,table,datasource,dataset,context) ;
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", "0")
					.header("x-per-page", String.valueOf(list.size()))
					.header("x-total", String.valueOf(list.size()))
					.body(list);
		}
	}

	@ApiOperation(value = "获取数据集", tags = {"数据" } ,notes = "获取数据集，POST，返回body<page,total,list>")
    @RequestMapping(method= RequestMethod.POST , value={"/{table}/search{dataset}"})
	public ResponseEntity<Page<BaseData>> search(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataset",required = true) String dataset,
			@RequestBody(required = false) FilterData context) {
		if(context==null)context=new FilterData();
		Page<BaseData> baseDatas = getService(datasource).fetch(system,table,datasource,dataset,context,context.getPageable()) ;
		return ResponseEntity.status(HttpStatus.OK)
                .body(new PageImpl(baseDatas.getContent(), context.getPageable(), baseDatas.getTotalElements()));
	}



	@ApiOperation(value = "查询数据", tags = {"数据" } ,notes = "查询数据，GET，返回body<list>+header<page,total>")
	@RequestMapping(method= RequestMethod.GET , value={"/{table}/query{dataquery}"})
	public ResponseEntity<List<BaseData>> query(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataquery",required = true) String dataquery,
			@RequestParam Map map) {
		FilterData context=FilterData.fromContext(map);
		return doQuery(system,table,datasource,dataquery,context);
	}

	@ApiOperation(value = "查询数据", tags = {"数据" } ,notes = "查询数据，POST，返回body<list>+header<page,total>")
	@RequestMapping(method= RequestMethod.POST , value={"/{table}/query{dataquery}"})
	public ResponseEntity<List<BaseData>> doQuery(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataquery",required = true) String dataquery,
			@RequestBody(required = false) FilterData context) {
		if(context==null)context=new FilterData();
		if(context.needPage()) {
			Page<BaseData> baseDatas = getService(datasource).query(system,table,datasource,dataquery,context,context.getPageable()) ;
			List<BaseData> list = baseDatas.getContent();
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", String.valueOf(context.getPageable().getPageNumber()))
					.header("x-per-page", String.valueOf(context.getPageable().getPageSize()))
					.header("x-total", String.valueOf(baseDatas.getTotalElements()))
					.body(list);
		}
		else {
			List<BaseData> list = getService(datasource).query(system,table,datasource,dataquery,context) ;
			return ResponseEntity.status(HttpStatus.OK)
					.header("x-page", "0")
					.header("x-per-page", String.valueOf(list.size()))
					.header("x-total", String.valueOf(list.size()))
					.body(list);
		}
	}

	@ApiOperation(value = "查询数据", tags = {"数据" } ,notes = "查询数据，POST，返回body<page,total,list>")
	@RequestMapping(method= RequestMethod.POST , value={"/{table}/page{dataquery}"})
	public ResponseEntity<Page<BaseData>> queryPage(@PathVariable(name = "system",required = true) String system,
			@PathVariable(name = "table",required = true) String table,@PathVariable(name = "datasource",required = true) String datasource,
			@PathVariable(name = "dataquery",required = true) String dataquery,
			@RequestBody(required = false) FilterData context) {
		if(context==null)context=new FilterData();
		Page<BaseData> baseDatas = getService(datasource).fetch(system,table,datasource,dataquery,context,context.getPageable()) ;
		return ResponseEntity.status(HttpStatus.OK)
				.body(new PageImpl(baseDatas.getContent(), context.getPageable(), baseDatas.getTotalElements()));
	}

}

