package shine.db.dao;

import shine.db.SqliteDbController;
import shine.db.entities.ChannelNameStateEntry;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public final class ChannelNameStateDAO {
    private static volatile ChannelNameStateDAO instance;
    private final SqliteDbController db = SqliteDbController.getInstance();

    private ChannelNameStateDAO() {}

    public static ChannelNameStateDAO getInstance() {
        if (instance == null) {
            synchronized (ChannelNameStateDAO.class) {
                if (instance == null) instance = new ChannelNameStateDAO();
            }
        }
        return instance;
    }

    public boolean existsByOwnerTypeAndSlug(Connection c, String ownerBchName, int channelTypeCode, String slug) throws SQLException {
        String sql = """
                SELECT 1
                FROM channel_names_state
                WHERE owner_bch_name = ? AND channel_type_code = ? AND slug = ?
                LIMIT 1
                """;
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setString(1, ownerBchName);
            ps.setInt(2, channelTypeCode);
            ps.setString(3, slug);
            try (ResultSet rs = ps.executeQuery()) {
                return rs.next();
            }
        }
    }

    public boolean existsByOwnerTypeAndSlug(String ownerBchName, int channelTypeCode, String slug) throws SQLException {
        try (Connection c = db.getConnection()) {
            return existsByOwnerTypeAndSlug(c, ownerBchName, channelTypeCode, slug);
        }
    }

    public void clearAll(Connection c) throws SQLException {
        try (PreparedStatement ps = c.prepareStatement("DELETE FROM channel_names_state")) {
            ps.executeUpdate();
        }
    }

    public void insert(Connection c, ChannelNameStateEntry entry) throws SQLException {
        String sql = """
                INSERT INTO channel_names_state (
                    slug,
                    display_name,
                    channel_description,
                    owner_login,
                    owner_bch_name,
                    channel_type_code,
                    channel_type_version,
                    channel_root_block_number,
                    channel_root_block_hash,
                    created_at_ms
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """;
        try (PreparedStatement ps = c.prepareStatement(sql)) {
            ps.setString(1, entry.getSlug());
            ps.setString(2, entry.getDisplayName());
            ps.setString(3, entry.getChannelDescription() == null ? "" : entry.getChannelDescription());
            ps.setString(4, entry.getOwnerLogin());
            ps.setString(5, entry.getOwnerBlockchainName());
            ps.setInt(6, entry.getChannelTypeCode());
            ps.setInt(7, entry.getChannelTypeVersion());
            ps.setInt(8, entry.getChannelRootBlockNumber());
            ps.setBytes(9, entry.getChannelRootBlockHash());
            ps.setLong(10, entry.getCreatedAtMs());
            ps.executeUpdate();
        }
    }

    public void insertAll(Connection c, List<ChannelNameStateEntry> entries) throws SQLException {
        for (ChannelNameStateEntry entry : entries) {
            insert(c, entry);
        }
    }
}
