/*******************************************************************************
 * Copyright 2019 2Fi Business Solutions Ltd.
 *
 *
 *
 * This code is copyrighted. Under no circumstances should any party, people,
 * or organization should redistribute any portions of this code in any form,
 * either verbatim or through electronic media, to any third parties, unless
 * under explicit written permission by 2Fi Business Solutions Ltd.
 ******************************************************************************/
package com.ffii.tbms.log.service;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.ffii.core.BaseEntity;
import com.ffii.core.dao.JdbcDao;
import com.ffii.core.utils.MapUtils;
import com.ffii.core.web.AbstractService;

/**
 * @author Patrick
 */
@Service
public class AuditLogService extends AbstractService {

	@Autowired
	private JdbcDao jdbcDao;

	private static final String SQL_INSERT_AUDIT_LOG = "INSERT INTO audit_log "
	+" (`tableName`, `recordId`, `modifiedBy`, `modified`, `actionStr`, `dataStr`, `refId`, `refType`) "
			+ "VALUES (:tableName, :recordId, :modifiedBy, :modified, :actionStr, :dataStr, :refId, :refType)";

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public int save(String tableName, int recordId, Integer modifiedBy, Date modified, String actionStr, String dataStr) {
		return jdbcDao.executeUpdate(SQL_INSERT_AUDIT_LOG,
				MapUtils.toHashMap("tableName", tableName, "recordId", recordId,
						"modifiedBy", modifiedBy, "modified", modified,
						"actionStr", actionStr, "dataStr", dataStr,
						"refId",null, "refType", null));
	}

	@Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class, readOnly = false)
	public int save(String tableName, int recordId, Integer modifiedBy, Date modified, String actionStr,
	 String dataStr, int refId, String refType) {
		return jdbcDao.executeUpdate(SQL_INSERT_AUDIT_LOG,
				MapUtils.toHashMap("tableName", tableName, "recordId", recordId,
						"modifiedBy", modifiedBy, "modified", modified,
						"actionStr", actionStr, "dataStr", dataStr,
						"refId",refId, "refType", refType));
	}

	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = true)
	public List<Map<String, Object>> searchOrderLog(Map<String, Object> args) {

		final StringBuilder sql = new StringBuilder(" SELECT ad.*, "
			+" u.fullname AS userName "
			+" FROM audit_log ad "
			+" LEFT JOIN users u ON u.id = ad.modifiedBy "
			+" WHERE (ad.tableName = 'orders' AND ad.recordId = :orderId) "
			+" OR (ad.refType = 'orders' AND ad.refId = :orderId ) ");

		if(args != null){
			if(args.containsKey("action")) sql.append(" AND ad.actionStr = :action ");
		}

			sql.append(" ORDER BY ad.modified DESC ");

		if (args != null) {
			if (args.containsKey("start") && args.containsKey("limit"))
				sql.append(" LIMIT :start, :limit ");
		}	

		return jdbcDao.queryForList(sql.toString(), args);
	}
	

	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = true)
	public List<Map<String, Object>> search(String tableName, Integer recordId) {

		String sql = "SELECT * FROM audit_log WHERE tableName = :tableName AND recordId = :recordId ORDER BY modified";

		return jdbcDao.queryForList(sql, MapUtils.toHashMap("tableName", tableName, "recordId", recordId));
	}

	@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, readOnly = true)
	public List<Map<String, Object>> getTables() {
		return jdbcDao.queryForList("SELECT DISTINCT tableName FROM audit_log;", null);
	}

	

}
