package project.svc.generic.csv.define;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import common.db.JdbcSource;
import common.db.jdbc.Jdbc;
import core.exception.ThrowableUtil;
import project.base.ServiceAbstract;

/**
 * クエリテスト
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class DefineTestQuery extends ServiceAbstract {

	/** メッセージ */
	private String message;

	/** 項目名リスト */
	private final List<String> item = new ArrayList<>();

	/**
	 * メッセージ取得
	 * @return メッセージ
	 */
	public String getMessage() {
		return this.message;
	}

	/**
	 * 項目名リスト取得
	 * @return 項目名リスト
	 */
	public List<String> getItem() {
		return Collections.unmodifiableList(this.item);
	}

	/**
	 * クエリテスト
	 * @param name 接続名
	 * @param query クエリ
	 * @return テスト結果 正常の場合 true を返す。
	 */
	public boolean tryQuery(final String name, final String query) {
		this.item.clear();

		try (Jdbc conn = JdbcSource.getConnection(name)) {
			try (PreparedStatement psmt = conn.readonlyStatement(query)) {
				psmt.setMaxRows(1);
				psmt.setFetchSize(1);

				try (ResultSet rs = psmt.executeQuery()) {
					final ResultSetMetaData rsmd = rs.getMetaData();
					for (int i = 1; i <= rsmd.getColumnCount(); i++) {
						this.item.add(rsmd.getColumnLabel(i));
					}
					return true;
				}
			}
		} catch (final SQLException ex) {
			final Throwable root = getRootCause(ex);
			final Throwable next = ThrowableUtil.getNextException(root);
			if (next != null) {
				this.message = next.getMessage();
			} else {
				this.message = root.getMessage();
			}
		}

		return false;
	}

	/**
	 * ルート原因例外取得
	 * @param th 例外
	 * @return ルート原因例外
	 */
	private Throwable getRootCause(final Throwable th) {
		Throwable ret = th;
		while (ret != null && ret.getCause() != null && ret != ret.getCause()) {
			ret = ret.getCause();
		}
		return ret;
	}
}
