package dev.lions.user.manager.resource;

import dev.lions.user.manager.api.SyncResourceApi;
import dev.lions.user.manager.dto.sync.HealthStatusDTO;
import dev.lions.user.manager.dto.sync.SyncConsistencyDTO;
import dev.lions.user.manager.dto.sync.SyncHistoryDTO;
import dev.lions.user.manager.dto.sync.SyncResultDTO;
import dev.lions.user.manager.service.SyncService;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * REST Resource pour la synchronisation avec Keycloak.
 * Suit le même pattern que AuditResource : les annotations JAX-RS des méthodes
 * héritées de l'interface ne sont PAS répétées ici (conformité RESTEasy Reactive).
 */
@Slf4j
@jakarta.enterprise.context.ApplicationScoped
@jakarta.ws.rs.Path("/api/sync")
@jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
@jakarta.ws.rs.Consumes(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
public class SyncResource implements SyncResourceApi {

    @Inject
    SyncService syncService;

    @GET
    @Path("/ping")
    @PermitAll
    public String ping() {
        return "{\"status\":\"pong\",\"resource\":\"SyncResource\"}";
    }

    @Override
    @PermitAll
    public HealthStatusDTO checkKeycloakHealth() {
        log.info("REST: checkKeycloakHealth sur /api/sync/health/keycloak");
        try {
            boolean available = syncService.isKeycloakAvailable();
            Map<String, Object> details = syncService.getKeycloakHealthInfo();
            return HealthStatusDTO.builder()
                    .keycloakAccessible(available)
                    .overallHealthy(available)
                    .keycloakVersion((String) details.getOrDefault("version", "Unknown"))
                    .timestamp(System.currentTimeMillis())
                    .build();
        } catch (Exception e) {
            log.error("Erreur lors du check health keycloak", e);
            return HealthStatusDTO.builder()
                    .overallHealthy(false)
                    .errorMessage("Erreur: " + e.getMessage())
                    .timestamp(System.currentTimeMillis())
                    .build();
        }
    }

    @Override
    @RolesAllowed({ "admin", "sync_manager" })
    public SyncResultDTO syncUsers(String realmName) {
        log.info("REST: syncUsers pour le realm: {}", realmName);
        long start = System.currentTimeMillis();
        try {
            int count = syncService.syncUsersFromRealm(realmName);
            return SyncResultDTO.builder()
                    .success(true)
                    .usersCount(count)
                    .realmName(realmName)
                    .startTime(start)
                    .endTime(System.currentTimeMillis())
                    .build();
        } catch (Exception e) {
            log.error("Erreur lors de la synchro users realm {}", realmName, e);
            return SyncResultDTO.builder()
                    .success(false)
                    .errorMessage(e.getMessage())
                    .realmName(realmName)
                    .startTime(start)
                    .endTime(System.currentTimeMillis())
                    .build();
        }
    }

    @Override
    @RolesAllowed({ "admin", "sync_manager" })
    public SyncResultDTO syncRoles(String realmName, String clientName) {
        log.info("REST: syncRoles pour le realm: {}, client: {}", realmName, clientName);
        long start = System.currentTimeMillis();
        try {
            int count = syncService.syncRolesFromRealm(realmName);
            return SyncResultDTO.builder()
                    .success(true)
                    .realmRolesCount(count)
                    .realmName(realmName)
                    .startTime(start)
                    .endTime(System.currentTimeMillis())
                    .build();
        } catch (Exception e) {
            log.error("Erreur lors de la synchro roles realm {}", realmName, e);
            return SyncResultDTO.builder()
                    .success(false)
                    .errorMessage(e.getMessage())
                    .realmName(realmName)
                    .startTime(start)
                    .endTime(System.currentTimeMillis())
                    .build();
        }
    }

    @Override
    @RolesAllowed({ "admin", "sync_manager" })
    public SyncConsistencyDTO checkDataConsistency(String realmName) {
        log.info("REST: checkDataConsistency pour realm: {}", realmName);
        try {
            Map<String, Object> report = syncService.checkDataConsistency(realmName);
            return SyncConsistencyDTO.builder()
                    .realmName((String) report.get("realmName"))
                    .status((String) report.get("status"))
                    .usersKeycloakCount((Integer) report.get("usersKeycloakCount"))
                    .usersLocalCount((Integer) report.get("usersLocalCount"))
                    .error((String) report.get("error"))
                    .build();
        } catch (Exception e) {
            log.error("Erreur checkDataConsistency realm {}", realmName, e);
            return SyncConsistencyDTO.builder()
                    .realmName(realmName)
                    .status("ERROR")
                    .error(e.getMessage())
                    .build();
        }
    }

    @Override
    @RolesAllowed({ "admin", "sync_manager", "user_viewer" })
    public SyncHistoryDTO getLastSyncStatus(String realmName) {
        log.info("REST: getLastSyncStatus pour realm: {}", realmName);
        return SyncHistoryDTO.builder()
                .realmName(realmName)
                .status("NEVER_SYNCED")
                .build();
    }

    @Override
    @RolesAllowed({ "admin", "sync_manager" })
    public SyncHistoryDTO forceSyncRealm(String realmName) {
        log.info("REST: forceSyncRealm pour realm: {}", realmName);
        try {
            syncService.forceSyncRealm(realmName);
            return SyncHistoryDTO.builder()
                    .realmName(realmName)
                    .status("SUCCESS")
                    .build();
        } catch (Exception e) {
            log.error("Erreur forceSyncRealm realm {}", realmName, e);
            return SyncHistoryDTO.builder()
                    .realmName(realmName)
                    .status("FAILED")
                    .build();
        }
    }
}
