package nc.service.rest.api;

import java.util.List;
import nc.bs.dao.BaseDAO;
import nc.bs.sec.esapi.NCESAPI;
import nc.itf.gl.voucher.IVoucher;
import nc.itf.uap.IUAPQueryBS;
import nc.vo.gl.closeaccbook.CloseaccbookVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pubapp.AppContext;
import nc.jdbc.framework.SQLParameter;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.service.rest.base.NcToNccBaseRestService;
import javax.servlet.http.HttpServletRequest;

import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nccloud.commons.lang.StringUtils;
import nccloud.pubitf.gl.lightgl.voucher.IVoucherWebService;

/**
 * 删除NCC凭证接口：此接口只能删除NC推送过来的凭证
 * 2020-11-24
 * @version NCC2005
 */
@SuppressWarnings("restriction")
public class DeleteVoucherRestService extends NcToNccBaseRestService {

	private static final long serialVersionUID = 1L;
	private BaseDAO dao = new BaseDAO();
	private IVoucherWebService service = NCLocator.getInstance().lookup(IVoucherWebService.class);
	private IVoucher queryService = NCLocator.getInstance().lookup(IVoucher.class);

	@Override
	protected Object execute(JSONObject json) throws Exception {

		JSONArray data = json.getJSONArray("data");
		if (data == null || data.size() == 0) {
			throw new BusinessException("单据编码为空，无法删除凭证");
		}
		// 1.根据单据号查询凭证主键
		String[] billCodes = data.toArray(new String[0]); // 单据编码
		String[] pks = getVoucherKeys(billCodes); // 查询删除凭证主键
		if (pks.length > 0) {
			throw new BusinessException("NCC系统对应的凭证未删除，不能取消制单");
			//return"NCC系统对应的凭证已被删除";
		} /*
			 * else { // 2.根据凭证号查询VO VoucherVO[] vos = queryService.queryByPks(pks); //
			 * 查询出所有凭证VO if (pks.length != vos.length) { // throw new
			 * BusinessException("NCC系统对应的凭证已被删除"); return"NCC系统对应的凭证已被删除"; }else { //
			 * 3.校验状态，并删除 String paraSql =
			 * "SELECT value FROM pub_sysinit WHERE initcode ='GL140' and nvl(dr,0)=0 ";
			 * String para = (String) dao.executeQuery(paraSql, new ColumnProcessor());
			 * if(null != para && para.equals("Y")) { for (VoucherVO vo : vos) { //校验是否关账、结账
			 * String returnMsg = closeAccbook(vo.getPk_org(),vo.getPrepareddate());
			 * if(StringUtils.isEmpty(returnMsg)) { String pk_checked = vo.getPk_checked();
			 * // 审核人 String pk_manager = vo.getPk_manager(); // 记账人 UFBoolean signflag =
			 * vo.getSignflag(); // 签字标记 if (pk_checked != null && !"~".equals(pk_checked)
			 * && !"N".equals(pk_checked)) { throw new BusinessException("NCC凭证已审核，不能删除"); }
			 * if (pk_manager != null && !"~".equals(pk_manager) &&
			 * !"N/A".equals(pk_manager) && !"N".equals(pk_manager)) { throw new
			 * BusinessException("NCC凭证已记账，不能删除"); } if (signflag.booleanValue()) { throw
			 * new BusinessException("NCC凭证已签字，不能删除"); }
			 * InvocationInfoProxy.getInstance().setUserId(vo.getPk_prepared()); //
			 * 制单人设置为当前用户，否则删除接口报没有权限 service.deleteVoucher4RestAPI(new String[] {
			 * vo.getPk_voucher() }); // 删除：每个单据的制单人可能不一致，所有只能循环删除 }else { throw new
			 * BusinessException(returnMsg); } } }else { for (VoucherVO vo : vos) {
			 * //校验是否关账、结账 String returnMsg =
			 * closeAccbook(vo.getPk_org(),vo.getPrepareddate());
			 * if(StringUtils.isEmpty(returnMsg)) { //凭证取消记账
			 * InvocationInfoProxy.getInstance().setUserId(vo.getPk_manager());
			 * service.tallyVoucher(new String[] {vo.getPk_voucher()},
			 * AppContext.getInstance().getBusiDate().toString(), false, true); //凭证取消审核
			 * InvocationInfoProxy.getInstance().setUserId(vo.getPk_checked());
			 * service.checkVoucher(new String[] {vo.getPk_voucher()}, false, true); //凭证删除
			 * InvocationInfoProxy.getInstance().setUserId(vo.getPk_prepared()); //
			 * 制单人设置为当前用户，否则删除接口报没有权限 service.deleteVoucher4RestAPI(new String[] {
			 * vo.getPk_voucher() }); // 删除：每个单据的制单人可能不一致，所有只能循环删除 }else { throw new
			 * BusinessException(returnMsg); } } } return "通过NCC接口成功删除【" + vos.length +
			 * "】张凭证"; } }
			 */
		return "成功";
	}

	private String closeAccbook(String pk_org, UFDate prepareddate) throws BusinessException {
		String yearmth = prepareddate.toString().substring(0, 7);
		//校验当月关账、结账情况
		String closeaccSql = "SELECT * FROM org_closeacc WHERE pk_org ='"+pk_org+"' AND pk_accperiodmonth in(SELECT pk_accperiodmonth  FROM bd_accperiodmonth WHERE yearmth='"+yearmth+"' AND nvl(dr,0)=0) AND moduleid='2002'AND nvl(dr,0)=0\r\n" ;
		List<CloseaccbookVO> accbookvoList = (List<CloseaccbookVO>)NCLocator.getInstance().lookup(IUAPQueryBS.class).executeQuery(closeaccSql,new BeanListProcessor(CloseaccbookVO.class));
		String flagSql = "SELECT isendacc FROM org_closeacc WHERE pk_org ='"+pk_org+"' AND pk_accperiodmonth in(SELECT pk_accperiodmonth  FROM bd_accperiodmonth WHERE yearmth='"+yearmth+"' AND nvl(dr,0)=0) AND moduleid='2002'AND nvl(dr,0)=0\r\n" ;
		String isendacc = (String)NCLocator.getInstance().lookup(IUAPQueryBS.class).executeQuery(flagSql,new ColumnProcessor());
		if((null != accbookvoList && accbookvoList.size() != 0)) {
			if(null != accbookvoList.get(0).getIsclose() && accbookvoList.get(0).getIsclose().booleanValue()) {
				return"NCC系统已关账，请确认后继续操作！";
			}else if(!StringUtils.isEmpty(isendacc) && "Y".equalsIgnoreCase(isendacc)){
				return"NCC系统已结账，请确认后继续操作！";
			}else if((null != accbookvoList.get(0).getIsclose() && accbookvoList.get(0).getIsclose().booleanValue()) && !StringUtils.isEmpty(isendacc) && "Y".equalsIgnoreCase(isendacc)) {
				return"NCC系统已关账、已结账，请确认后继续操作！";
			}
		}
		return null;
	}

	/**
	 * 通过单据号查询删除凭证主键。
	 * 
	 * @param billCodes
	 * @return
	 * @throws BusinessException
	 */
	@SuppressWarnings("unchecked")
	public String[] getVoucherKeys(String[] billCodes) throws BusinessException {
		if (billCodes == null || billCodes.length == 0) {
			return new String[0];
		}
		String sql = "select pk_voucher from gl_voucher where free3 in (" + createInSql(billCodes) + ") and nvl(dr,0)=0";
		List<String> result = (List<String>) this.dao.executeQuery(sql, new ColumnListProcessor());
		return result == null ? new String[0] : result.toArray(new String[0]);
	}

	@Override
	public void exeBoforeLog(HttpServletRequest request, JSONObject json) throws Exception {
		String logID = getLogID(json); // 单据号

		// 1.删除当前单据已有日志（重复推送的场景）
		String deleteSql = "delete from push_voucher_log where billcode='" + NCESAPI.sqlEncode(logID) + "'";
		this.dao.executeUpdate(deleteSql);

		// 2. 新增日志信息
		String insertSql = "insert into push_voucher_log(billcode,description,status,json_data) values(?,?,?,?)";
		SQLParameter params = new SQLParameter();
		params = new SQLParameter();
		params.addParam(logID);
		params.addParam("NCC收到删除凭证请求");
		params.addParam("processing"); // 状态：处理中
		params.addParam(json.toJSONString()); // 报文数据
		this.dao.executeUpdate(insertSql, params);
	}

	@Override
	public void exeAfterLog(HttpServletRequest request, JSONObject json) throws Exception {
		String logID = getLogID(json); // 单据号
		String status = "success";
		String description = "NCC凭证删除成功";
		String sql = "update push_voucher_log set description='" + NCESAPI.sqlEncode(description) + "',status='"
				+ NCESAPI.sqlEncode(status) + "' where billcode='" + NCESAPI.sqlEncode(logID) + "'";
		this.dao.executeUpdate(sql);
	}

	@Override
	public void businessErrorLog(HttpServletRequest request, JSONObject json, String errorMsg) throws Exception {
		String logID = getLogID(json); // 单据号
		String status = "failure"; // 状态：失败
		String description = "NCC删除凭证出现业务异常";
		String sql = "update push_voucher_log set description='" + NCESAPI.sqlEncode(description) + "',status='"
				+ NCESAPI.sqlEncode(status) + "',error_msg='" + NCESAPI.sqlEncode(errorMsg) + "' where billcode='"
				+ NCESAPI.sqlEncode(logID) + "'";
		this.dao.executeUpdate(sql);
	}

	/**
	 * 获取日志表主键
	 * 
	 * @param json
	 * @return
	 */
	public String getLogID(JSONObject json) throws BusinessException {
		JSONArray data = json.getJSONArray("data");
		if (data == null || data.size() == 0) {
			return "D_~";
		}
		StringBuffer result = new StringBuffer("D_"); // 凭证目标单据号，批量情况用逗号隔开（D表示删除操作）
		for (int i = 0; i < data.size(); i++) {
			result.append((i == data.size() - 1) ? data.getString(i) : (data.getString(i) + ","));
		}
		return result.toString().trim();
	}

	/**
	 * 拼接SQL IN语句
	 * 
	 * @param paramsSet
	 * @return
	 */
	public static String createInSql(String[] params) {
		if (params == null || params.length == 0) {
			return "''";
		}
		StringBuffer inSql = new StringBuffer();
		for (int i = 0; i < params.length; i++) {
			String param = params[i] == null ? "" : params[i];
			inSql.append(i == params.length - 1 ? ("'" + param + "'") : ("'" + param + "',"));
		}
		return inSql.toString();
	}

}
