package com.psg.dlsysinfo.dl_sysinfo_server.service;

import com.psg.dlsysinfo.dl_sysinfo_server.entity.CachedInstalledSoftware;
import com.psg.dlsysinfo.dl_sysinfo_server.entity.CveMatchResult;
import com.psg.dlsysinfo.dl_sysinfo_server.entity.Devices;
import com.psg.dlsysinfo.dl_sysinfo_server.entity.InstalledSoftware;
import com.psg.dlsysinfo.dl_sysinfo_server.repository.CachedInstalledSoftwareRepository;
import com.psg.dlsysinfo.dl_sysinfo_server.repository.DevicesRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

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

@Service
@RequiredArgsConstructor
public class CachedSoftwareService {

    private final DevicesRepository devicesRepository;
    private final CachedInstalledSoftwareRepository cachedSoftwareRepo;
    private final VulnerabilityScannerService vulnerabilityScannerService;

    @Scheduled(cron = "0 30 * * * *") // Every hour at minute 30
    @Transactional
    public void refreshSoftwareCache() {
        System.out.println("♻️ Refreshing cached installed software...");
        refreshSoftwareCacheWithSummary(); // 🔥 Call the real logic
    }

    @Transactional
    public String refreshSoftwareCacheWithSummary() {
        StringBuilder sb = new StringBuilder();
        List<Devices> devices = devicesRepository.findAll();

        for (Devices device : devices) {
            sb.append(refreshDeviceSoftwareCache(device));
        }

        System.out.println("✅ Software cache refresh complete.");
        return sb.toString();
    }

    /**
     * Refreshes the cached software entries for a single device.
     */
    private String refreshDeviceSoftwareCache(Devices device) {
        Long deviceId = device.getDeviceId();
        String hashedHostname = device.getHashedHostname();
        String encryptedHostname = device.getEncryptedHostname();

        cachedSoftwareRepo.deleteByDeviceId(deviceId);
        cachedSoftwareRepo.flush();

        List<InstalledSoftware> installedApps = device.getInstalledApplications();

        List<CachedInstalledSoftware> toSave = installedApps.stream()
                .map(app -> CachedInstalledSoftware.builder()
                        .deviceId(deviceId)
                        .hostname(hashedHostname)
                        .encryptedHostname(encryptedHostname)
                        .softwareName(app.getAppName())
                        .appVersion(app.getAppVersion())
                        .publisher(app.getPublisher())
                        .lastUpdated(LocalDateTime.now())
                        .build())
                .toList();

        List<CveMatchResult> deviceVulns = vulnerabilityScannerService.getVulnerabilitiesForDevice(deviceId);

        for (CachedInstalledSoftware entry : toSave) {
            List<String> matchingCveIds = deviceVulns.stream()
                    .filter(vuln -> vuln.getAffectedApp().equalsIgnoreCase(entry.getSoftwareName()))
                    .map(CveMatchResult::getCveId)
                    .toList();

            entry.setTotalCves(matchingCveIds.size());
            entry.setCveList(String.join(",", matchingCveIds));
        }

        cachedSoftwareRepo.saveAll(toSave);
        return String.format("📦 Device %d: %d software entries cached\n", deviceId, installedApps.size());
    }
}
