package com.cameleer.server.app.storage;

import com.cameleer.server.core.rbac.*;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class PostgresRoleRepository implements RoleRepository {

    private final JdbcTemplate jdbc;

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

    @Override
    public List<RoleDetail> findAll() {
        return jdbc.query("""
                SELECT id, name, description, scope, system, created_at FROM roles ORDER BY system DESC, name
                """, (rs, rowNum) -> new RoleDetail(
                rs.getObject("id", UUID.class),
                rs.getString("name"),
                rs.getString("description"),
                rs.getString("scope"),
                rs.getBoolean("system"),
                rs.getTimestamp("created_at").toInstant(),
                List.of(), List.of(), List.of()
        ));
    }

    @Override
    public Optional<RoleDetail> findById(UUID id) {
        var rows = jdbc.query("""
                SELECT id, name, description, scope, system, created_at FROM roles WHERE id = ?
                """, (rs, rowNum) -> new RoleDetail(
                rs.getObject("id", UUID.class),
                rs.getString("name"),
                rs.getString("description"),
                rs.getString("scope"),
                rs.getBoolean("system"),
                rs.getTimestamp("created_at").toInstant(),
                List.of(), List.of(), List.of()
        ), id);
        if (rows.isEmpty()) return Optional.empty();
        var r = rows.get(0);

        List<GroupSummary> assignedGroups = jdbc.query("""
                SELECT g.id, g.name FROM group_roles gr
                JOIN groups g ON g.id = gr.group_id WHERE gr.role_id = ?
                """, (rs, rowNum) -> new GroupSummary(rs.getObject("id", UUID.class),
                rs.getString("name")), id);

        List<UserSummary> directUsers = jdbc.query("""
                SELECT u.user_id, u.display_name, u.provider FROM user_roles ur
                JOIN users u ON u.user_id = ur.user_id WHERE ur.role_id = ?
                """, (rs, rowNum) -> new UserSummary(rs.getString("user_id"),
                rs.getString("display_name"), rs.getString("provider")), id);

        return Optional.of(new RoleDetail(r.id(), r.name(), r.description(),
                r.scope(), r.system(), r.createdAt(), assignedGroups, directUsers, List.of()));
    }

    @Override
    public UUID create(String name, String description, String scope) {
        UUID id = UUID.randomUUID();
        jdbc.update("INSERT INTO roles (id, name, description, scope, system) VALUES (?, ?, ?, ?, false)",
                id, name, description, scope);
        return id;
    }

    @Override
    public void update(UUID id, String name, String description, String scope) {
        jdbc.update("""
                UPDATE roles SET name = COALESCE(?, name), description = COALESCE(?, description),
                scope = COALESCE(?, scope) WHERE id = ? AND system = false
                """, name, description, scope, id);
    }

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