package com.cameleer.server.app.storage;

import com.cameleer.server.core.runtime.AppVersion;
import com.cameleer.server.core.runtime.AppVersionRepository;
import org.springframework.jdbc.core.JdbcTemplate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

public class PostgresAppVersionRepository implements AppVersionRepository {

    private final JdbcTemplate jdbc;

    public PostgresAppVersionRepository(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }

    @Override
    public List<AppVersion> findByAppId(UUID appId) {
        return jdbc.query(
                "SELECT id, app_id, version, jar_path, jar_checksum, jar_filename, jar_size_bytes, detected_runtime_type, detected_main_class, uploaded_at FROM app_versions WHERE app_id = ? ORDER BY version DESC",
                (rs, rowNum) -> mapRow(rs), appId);
    }

    @Override
    public Optional<AppVersion> findById(UUID id) {
        var results = jdbc.query(
                "SELECT id, app_id, version, jar_path, jar_checksum, jar_filename, jar_size_bytes, detected_runtime_type, detected_main_class, uploaded_at FROM app_versions WHERE id = ?",
                (rs, rowNum) -> mapRow(rs), id);
        return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
    }

    @Override
    public int findMaxVersion(UUID appId) {
        Integer max = jdbc.queryForObject(
                "SELECT COALESCE(MAX(version), 0) FROM app_versions WHERE app_id = ?",
                Integer.class, appId);
        return max != null ? max : 0;
    }

    @Override
    public UUID create(UUID appId, int version, String jarPath, String jarChecksum, String jarFilename, Long jarSizeBytes) {
        UUID id = UUID.randomUUID();
        jdbc.update("INSERT INTO app_versions (id, app_id, version, jar_path, jar_checksum, jar_filename, jar_size_bytes) VALUES (?, ?, ?, ?, ?, ?, ?)",
                id, appId, version, jarPath, jarChecksum, jarFilename, jarSizeBytes);
        return id;
    }

    @Override
    public void delete(UUID id) {
        jdbc.update("DELETE FROM app_versions WHERE id = ?", id);
    }

    @Override
    public void updateDetectedRuntime(UUID id, String detectedRuntimeType, String detectedMainClass) {
        jdbc.update("UPDATE app_versions SET detected_runtime_type = ?, detected_main_class = ? WHERE id = ?",
                detectedRuntimeType, detectedMainClass, id);
    }

    private AppVersion mapRow(ResultSet rs) throws SQLException {
        Long sizeBytes = rs.getLong("jar_size_bytes");
        if (rs.wasNull()) sizeBytes = null;
        return new AppVersion(
                UUID.fromString(rs.getString("id")),
                UUID.fromString(rs.getString("app_id")),
                rs.getInt("version"),
                rs.getString("jar_path"),
                rs.getString("jar_checksum"),
                rs.getString("jar_filename"),
                sizeBytes,
                rs.getString("detected_runtime_type"),
                rs.getString("detected_main_class"),
                rs.getTimestamp("uploaded_at").toInstant()
        );
    }
}
