package study.saga;

import java.util.Map;
import java.util.HashMap;
import org.springframework.jdbc.core.JdbcTemplate;

/** 在独有实验库内记录合成业务副作用；每次 JDBC 操作是本地事务。 */
public final class InventoryService {
    private final JdbcTemplate jdbc;
    public InventoryService(JdbcTemplate jdbc) { this.jdbc = jdbc; }

    public Map<String, Object> reserve(Map<String, Object> input) {
        String key = key(input);
        jdbc.update("INSERT INTO u38_saga_order (id, state) VALUES (?, 'RESERVED') "
                + "ON DUPLICATE KEY UPDATE id=id", key);
        if (!"RESERVED".equals(state(key))) throw new IllegalStateException("reservation already finalized: " + key);
        return new HashMap<>(Map.of("key", key));
    }

    public Map<String, Object> charge(Map<String, Object> input) {
        String key = key(input);
        if ("true".equals(input.get("fail"))) throw new ExpectedFailure("simulated-charge-failure");
        int changed = jdbc.update("UPDATE u38_saga_order SET state='CHARGED' WHERE id=? AND state='RESERVED'", key);
        if (changed != 1 && !"CHARGED".equals(state(key)))
            throw new IllegalStateException("reservation not chargeable: " + key);
        return new HashMap<>(Map.of("key", key));
    }

    public Map<String, Object> release(Map<String, Object> input) {
        String key = key(input);
        if ("true".equals(input.get("fail"))) throw new ExpectedFailure("simulated-compensation-failure");
        int changed = jdbc.update("UPDATE u38_saga_order SET state='RELEASED' WHERE id=? AND state='RESERVED'", key);
        if (changed != 1 && !"RELEASED".equals(state(key)))
            throw new IllegalStateException("reservation not releasable: " + key);
        return new HashMap<>(Map.of("key", key));
    }

    private String state(String key) {
        return jdbc.query("SELECT state FROM u38_saga_order WHERE id=?",
                rs -> rs.next() ? rs.getString(1) : null, key);
    }

    private static String key(Map<String, Object> input) {
        Object value = input.get("key");
        if (!(value instanceof String key) || key.isBlank()) throw new IllegalArgumentException("missing order key");
        return key;
    }
}
