package io.delphi.qa.auto.awsmfrw.models.db;

import com.google.common.base.CaseFormat;
import com.google.gson.internal.LinkedTreeMap;
import io.delphi.qa.auto.awsmfrw.common_baby.IsaCommonMethods;
import lombok.*;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Getter
@With
@ToString
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
public abstract class BsSqlTable<T> implements IsaCommonMethods {

  //  public abstract DB_SQL_ENTITY builder(ResultSet rs);

  public <T> T builder(ResultSet rs) {
    Set<String> set = fields();
    Map<String, Object> map = new LinkedTreeMap<>();
    set.forEach(
        s -> {
          try {
            String key = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, s);
            map.put(key, rs.getObject(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, s)));
          } catch (SQLException e) {
            e.printStackTrace();
          }
        });
    return (T) gson.fromJson(gson.toJson(map), this.getClass());
  }

  public Set<String> fields() {
    Class ftClass = this.getClass();
    Field[] fields = ftClass.getDeclaredFields();
    return Arrays.stream(fields)
        .filter(
            f -> {
              try {
                f.setAccessible(true);
                return f.get(this) != null;
              } catch (IllegalAccessException e) {
                e.printStackTrace();
                return false;
              }
            })
        .map(Field::getName)
        .collect(Collectors.toSet());
  }

  public String tableName() {
    return CaseFormat.UPPER_CAMEL.to(
        CaseFormat.UPPER_UNDERSCORE, this.getClass().getSimpleName().split("_")[1]);
  }

  public String schemaTable() {
    String[] split = this.getClass().getPackage().getName().split("\\.");
    String schema =
        CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, split[split.length - 1]);
    String table =
        CaseFormat.UPPER_CAMEL.to(
            CaseFormat.UPPER_UNDERSCORE, this.getClass().getSimpleName().split("_")[1]);
    return String.format("%s.%s", schema, table);
  }

  public String locator() {
    String[] split = this.getClass().getPackage().getName().split("\\.");
    String db =
        CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, split[split.length - 2]);
    String schema =
        CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, split[split.length - 1]);
    String table =
        CaseFormat.UPPER_CAMEL.to(
            CaseFormat.UPPER_UNDERSCORE, this.getClass().getSimpleName().split("_")[1]);
    String format = String.format(
        (envConfig.isProd() || !db.startsWith("_"))
            ? "%s.%s.%s"
            : envConfig.env().toUpperCase(Locale.ROOT) + "%s.%s.%s",
        db,
        schema,
        table);
    return format;
  }
}
