package com.psg.dlsysinfo.dl_sysinfo_server.scheduling;

import com.psg.dlsysinfo.dl_sysinfo_server.service.CveStatisticsService;
import com.psg.dlsysinfo.dl_sysinfo_server.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Map;

@Component
public class CveSyncScheduler {

    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Value("${spring.datasource.username}")
    private String dbUser;

    @Value("${spring.datasource.password}")
    private String dbPass;

    @Value("${nvd.api.key}")
    private String apiKey;

    @Value("${nvd.max-range-days:7}")
    private String nvdMaxRangeDays;

    @Value("${scripts.directory:/home/sonder/ld-sysinfo-server/scripts}")
    private String scriptsDirectory;

    @Value("${scripts.logs.directory:/home/sonder/ld-sysinfo-server/scripts}")
    private String logsDirectory;

    @Autowired
    private EmailService emailService;

    @Autowired
    private CveStatisticsService cveStatisticsService;


    @Scheduled(cron = "0 0 */8 * * *") // ⏰ Every 8 hours
    public void runCveSyncScript() {
        File scriptDir = new File(scriptsDirectory);
        File scriptFile = new File(scriptDir, "fetchCVE_v2.js");
        File logFile = new File(logsDirectory, "cve-sync.log");

        if (!scriptFile.exists()) {
            String msg = "❌ Script not found: " + scriptFile.getAbsolutePath();
            log(msg, logFile);
            emailService.sendHtmlEmail("⚠️ CVE Sync Failed", wrapHtml(msg));
            return;
        }

        try {
            ProcessBuilder pb = new ProcessBuilder("node", "fetchCVE_v2.js");
            pb.directory(scriptDir);

            Map<String, String> env = pb.environment();
            env.put("DB_HOST", extractHost(dbUrl));
            env.put("DB_PORT", extractPort(dbUrl));
            env.put("DB_NAME", extractDbName(dbUrl));
            env.put("DB_USER", dbUser);
            env.put("DB_PASSWORD", dbPass);
            env.put("NVD_API_KEY", apiKey);
            env.put("NVD_MAX_RANGE_DAYS", nvdMaxRangeDays);

            env.put("NODE_OPTIONS", "--no-warnings --enable-source-maps");
            env.put("LC_ALL", "en_US.UTF-8");
            env.put("LANG", "en_US.UTF-8");
            env.put("LANGUAGE", "en_US:en");

            pb.redirectErrorStream(true);
            Process process = pb.start();

            StringBuilder output = new StringBuilder();
            output.append("=== CVE Sync Run at ").append(LocalDateTime.now()).append(" ===\n");

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
                 FileWriter fw = new FileWriter(logFile, true)) {

                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                    fw.write(line + "\n");
                }

                int exitCode = process.waitFor();
                output.append(">>> Exit Code: ").append(exitCode).append("\n");
                fw.write(">>> Exit Code: " + exitCode + "\n");

                String subject = (exitCode == 0 ? "✅ CVE Sync Complete" : "⚠️ CVE Sync Completed with Errors");
                emailService.sendHtmlEmail(subject, wrapHtml(output.toString()));
                if (exitCode == 0) {
                    cveStatisticsService.refreshStatistics();
                }

            }

        } catch (Exception e) {
            String err = "❌ Exception during CVE sync: " + e.getMessage();
            log(err, logFile);
            emailService.sendHtmlEmail("❌ CVE Sync Error", wrapHtml(err));
        }
    }

    private String extractHost(String url) {
        String clean = url.replace("jdbc:mysql://", "").split("/")[0];

        // Handle IPv6 addresses like [::1]:3307
        if (clean.startsWith("[")) {
            int closeBracket = clean.indexOf("]");
            if (closeBracket > 0) {
                return clean.substring(1, closeBracket);
            }
        }

        // Handle standard host:port format
        return clean.split(":")[0];
    }

    private String extractPort(String url) {
        String clean = url.replace("jdbc:mysql://", "").split("/")[0];

        // Handle IPv6: [::1]:3307
        if (clean.contains("]:")) {
            return clean.substring(clean.indexOf("]:") + 2);
        }

        // Handle standard: hostname:3307
        if (clean.contains(":") && !clean.startsWith("[")) {
            String[] parts = clean.split(":");
            if (parts.length > 1) {
                return parts[1];
            }
        }

        return "3306"; // default MySQL port
    }

    private String extractDbName(String url) {
        return url.substring(url.lastIndexOf("/") + 1).split("\\?")[0];
    }

    private void log(String message, File logFile) {
        try (FileWriter fw = new FileWriter(logFile, true)) {
            fw.write(LocalDateTime.now() + " — " + message + "\n");
        } catch (IOException ignored) {}
    }

    private String wrapHtml(String content) {
        return """
            <html>
              <body style="font-family: sans-serif; font-size: 14px;">
                <h2 style="color: #2E86C1;">CVE Sync Report</h2>
                <pre style="background: #f4f4f4; padding: 1em; border-radius: 4px;">%s</pre>
              </body>
            </html>
            """.formatted(content.replace("<", "&lt;").replace(">", "&gt;"));
    }
}
