package lc.sips.postgres;

import lc.mecha.log.MechaLogger;
import lc.mecha.log.MechaLoggerFactory;
import lc.mecha.util.StringAccumulatorV2;
import lc.sips.QueryAccumulator;
import lc.sips.jdbc.Dialect;
import lc.sips.schema.ColumnDefinition;
import lc.sips.schema.Table;

import java.util.List;

/**
 * This class implements the {@link Dialect} for the PostgreSQL database system.
 *
 * @author Alex Leigh
 * @since 1.0
 */
public class PostgresDialect implements Dialect {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(PostgresDialect.class);

    public static String COL_ID = "_id";
    private final String prefix;

    public PostgresDialect(String prefix) {
        this.prefix = prefix;
    }

    private String makeTableName(Table table) {
        return "\"" + prefix + "_" + table.name() + "\"";
    }

    public List<String> createTableQuery(Table table) {
        var q = new QueryAccumulator();

        q.append("CREATE TABLE " + makeTableName(table) + " (" + COL_ID + " BIGSERIAL PRIMARY KEY,");

        var cols = new StringAccumulatorV2(",");

        for (ColumnDefinition col : table.columns()) {
            var sb = new StringBuilder();
            sb.append("\"").append(col.name()).append("\" ");
            switch (col.type()) {
                case BIGINT -> sb.append("BIGINT");
                case ID -> sb.append("BIGSERIAL");
                case VARCHAR -> {
                    sb.append("VARCHAR(");
                    sb.append(col.length());
                    sb.append(")");
                }
                default -> throw new IllegalStateException("Unknown column type: " + col.type());
            }

            var parentTable = col.parentTable();
            if (parentTable != null) {
                sb.append(" REFERENCES \"" + parentTable + "\"(_id)");
                if (col.onDeleteCascade()) {
                    sb.append(" ON DELETE CASCADE");
                }
            }

            cols.push(sb.toString());
        }
        q.append(cols.asString() + ")");
        return List.of(q.toString());
    }

    public List<String> createTableDrop(Table table) {
        return List.of("DROP TABLE " + makeTableName(table));
    }

    @Override
    public List<String> createSelect(Table table) {
        return null;
    }
}
