package com.psg.dlsysinfo.dl_sysinfo_server.repository;

import com.psg.dlsysinfo.dl_sysinfo_server.dto.TopVulnerabilityDTO;
import com.psg.dlsysinfo.dl_sysinfo_server.dto.VulnerableSoftwareDTO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
public interface ReportingRepository extends JpaRepository<com.psg.dlsysinfo.dl_sysinfo_server.entity.Devices, Long> {

    // Compliance Summary Queries

    @Query("SELECT COUNT(DISTINCT d.deviceId) FROM Devices d WHERE d.client.clientId = :clientId")
    Long countTotalDevices(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(DISTINCT cdv.deviceId) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
    Long countVulnerableDevices(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
    Long countTotalVulnerabilities(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
           "AND UPPER(cdv.severity) = 'CRITICAL'")
    Long countCriticalVulnerabilities(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
           "AND UPPER(cdv.severity) = 'HIGH'")
    Long countHighVulnerabilities(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
           "AND UPPER(cdv.severity) = 'MEDIUM'")
    Long countMediumVulnerabilities(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(cdv) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
           "AND UPPER(cdv.severity) = 'LOW'")
    Long countLowVulnerabilities(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(DISTINCT cis.softwareName) FROM CachedInstalledSoftware cis " +
           "WHERE cis.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
    Long countTotalSoftware(@Param("clientId") Long clientId);

    @Query("SELECT COUNT(DISTINCT cis.softwareName) FROM CachedInstalledSoftware cis " +
           "WHERE cis.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId) " +
           "AND cis.totalCves > 0")
    Long countVulnerableSoftware(@Param("clientId") Long clientId);

    @Query("SELECT MAX(cdv.lastUpdated) FROM CachedDeviceVuln cdv " +
           "WHERE cdv.deviceId IN (SELECT d.deviceId FROM Devices d WHERE d.client.clientId = :clientId)")
    LocalDateTime findLastVulnerabilityScanDate(@Param("clientId") Long clientId);

    // Top Vulnerabilities Query - Using native SQL for LIMIT support

    @Query(value = "SELECT cdv.cve_id as cveId, " +
           "cdv.description as title, " +
           "cdv.severity as severity, " +
           "cdv.score as score, " +
           "COUNT(DISTINCT cdv.device_id) as affectedDevices " +
           "FROM cached_device_vulns cdv " +
           "WHERE cdv.device_id IN (SELECT d.deviceId FROM devices d WHERE d.clientId = :clientId) " +
           "GROUP BY cdv.cve_id, cdv.description, cdv.severity, cdv.score " +
           "ORDER BY " +
           "CASE WHEN UPPER(cdv.severity) = 'CRITICAL' THEN 0 " +
           "     WHEN UPPER(cdv.severity) = 'HIGH' THEN 1 " +
           "     WHEN UPPER(cdv.severity) = 'MEDIUM' THEN 2 " +
           "     WHEN UPPER(cdv.severity) = 'LOW' THEN 3 " +
           "     ELSE 4 END, " +
           "COUNT(DISTINCT cdv.device_id) DESC " +
           "LIMIT 20",
           nativeQuery = true)
    List<Object[]> findTopVulnerabilitiesNative(@Param("clientId") Long clientId);

    // Vulnerable Software Query - Using native SQL for LIMIT support

    @Query(value = "SELECT cis.software_name as softwareName, " +
           "COUNT(cis.id) as totalInstances, " +
           "SUM(CASE WHEN cis.total_cves > 0 THEN 1 ELSE 0 END) as vulnerableInstances, " +
           "MAX(COALESCE(cis.total_cves, 0)) as totalCves " +
           "FROM cached_installed_software cis " +
           "WHERE cis.device_id IN (SELECT d.deviceId FROM devices d WHERE d.clientId = :clientId) " +
           "GROUP BY cis.software_name " +
           "ORDER BY (SUM(CASE WHEN cis.total_cves > 0 THEN 1 ELSE 0 END) * 1.0 / COUNT(cis.id) * MAX(COALESCE(cis.total_cves, 0))) DESC " +
           "LIMIT 20",
           nativeQuery = true)
    List<Object[]> findVulnerableSoftwareNative(@Param("clientId") Long clientId);
}
