package com.psg.dlsysinfo.dl_sysinfo_server.repository;

import com.psg.dlsysinfo.dl_sysinfo_server.dto.ProductCveDTO;
import com.psg.dlsysinfo.dl_sysinfo_server.entity.Cve;
import com.psg.dlsysinfo.dl_sysinfo_server.entity.CveMatchResult;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface CveRepository extends JpaRepository<Cve, String> {

    // 🆕 Add this for the admin page
    @Query("""
                SELECT c FROM Cve c
                WHERE (:search IS NULL OR :search = '' 
                    OR LOWER(c.id) LIKE LOWER(CONCAT('%', :search, '%')) 
                    OR LOWER(c.description) LIKE LOWER(CONCAT('%', :search, '%')) 
                    OR LOWER(c.severity) LIKE LOWER(CONCAT('%', :search, '%')))
            """)
    Page<Cve> findFiltered(@Param("search") String search, Pageable pageable);

    @Query(value = """
        SELECT DISTINCT 
            v.id AS cveId, 
            v.severity AS severity, 
            v.cvss_score AS score, 
            v.description AS description,
            i.appName AS affectedApp,
            i.appVersion AS installedVersion,
            v.last_modified_date AS lastModifiedDate
        FROM installed_software i
        JOIN cpe_matches c ON
            i.normalized_product = c.product
            AND i.normalized_publisher = c.vendor
            AND (
                 (
                   (c.version_start IS NULL OR i.appVersion >= c.version_start)
                   AND (c.version_end IS NULL OR i.appVersion <= c.version_end)
                 )
                 OR i.appVersion = c.version
            )
        JOIN cves v ON c.cve_id = v.id
        WHERE i.deviceId = :deviceId
        """,
            countQuery = """
            SELECT COUNT(DISTINCT v.id)
            FROM installed_software i
            JOIN cpe_matches c ON
                i.normalized_product = c.product
                AND i.normalized_publisher = c.vendor
                AND (
                     (
                       (c.version_start IS NULL OR i.appVersion >= c.version_start)
                       AND (c.version_end IS NULL OR i.appVersion <= c.version_end)
                     )
                     OR i.appVersion = c.version
                )
            JOIN cves v ON c.cve_id = v.id
            WHERE i.deviceId = :deviceId
        """,
            nativeQuery = true)
    Page<CveMatchResult> findPaginatedVulnerabilitiesForDevice(@Param("deviceId") Long deviceId, Pageable pageable);

    @Query(value = """
    SELECT 
        v.id AS cve_id,                 -- 0
        v.description,                  -- 1
        v.severity,                     -- 2 ✅ NEW: severity
        c.version_start,                -- 3
        c.version_end,                  -- 4
        c.version,                      -- 5
        i.appVersion,                   -- 6
        i.appName,                      -- 7
        i.normalized_app_name,          -- 8
        v.cvss_score,                   -- 9
        v.last_modified_date            -- 10
    FROM installed_software i
    JOIN cpe_matches c ON
        (i.normalized_product = c.product OR i.normalized_app_name = c.product)
        AND i.normalized_publisher = c.vendor
    JOIN cves v ON c.cve_id = v.id
    WHERE i.deviceId = :deviceId
""", nativeQuery = true)
    List<Object[]> findUnfilteredMatches(@Param("deviceId") Long deviceId);

    @Query(value = """
    SELECT DISTINCT v.*
    FROM cves v
    JOIN cpe_matches c ON c.cve_id = v.id
    WHERE LOWER(c.product) = LOWER(:productName)
""", nativeQuery = true)
    List<Cve> findByProductName(@Param("productName") String productName);

    @Query(value = """
    SELECT DISTINCT v.*
    FROM cves v
    JOIN cpe_matches c ON c.cve_id = v.id
    WHERE LOWER(c.product) IN :products
""", nativeQuery = true)
    List<Cve> findAllByProductNames(@Param("products") List<String> products);

    @Query("""
    SELECT DISTINCT new com.psg.dlsysinfo.dl_sysinfo_server.dto.ProductCveDTO(
        c.cve.id, c.cve.severity, c.cve.description, c.product
    )
    FROM CpeMatch c
    WHERE LOWER(c.product) IN :products
""")
    List<ProductCveDTO> findAllProductMatches(@Param("products") List<String> products);




}
