package scanner

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

const (
	gotestwafTimeout = 120 * time.Second
)

// RunGoTestWAF executes GoTestWAF scan against the given target domain.
// Tries HTTPS first; if the report file isn't created (target not reachable
// on port 443), retries with plain HTTP on port 80.
// The report is saved to reports/ directory with the given reportName.
// Returns the raw output for AI analysis.
func RunGoTestWAF(ctx context.Context, projectRoot string, reportName string, targetDomain string) (string, error) {
	// Try HTTPS first, then HTTP as fallback
	for _, protocol := range []string{"https", "http"} {
		output, err := runWithProtocol(ctx, projectRoot, reportName, targetDomain, protocol)
		// If the report file exists, the scan produced output — success
		reportPath := filepath.Join(projectRoot, "reports", reportName+".html")
		if _, statErr := os.Stat(reportPath); statErr == nil {
			return output, nil
		}
		// No report file — try next protocol or return error
		if err != nil {
			fmt.Printf("gotestwaf: %s failed for %s: %v\n", protocol, targetDomain, err)
		}
	}
	return "", fmt.Errorf("GoTestWAF: %s not reachable on HTTPS or HTTP", targetDomain)
}

// runWithProtocol executes GoTestWAF with the given protocol (https or http).
func runWithProtocol(ctx context.Context, projectRoot string, reportName string, targetDomain string, protocol string) (string, error) {
	targetURL := fmt.Sprintf("%s://%s", protocol, targetDomain)
	binaryPath := filepath.Join(projectRoot, "gotestwaf")

	if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
		return "", fmt.Errorf("GoTestWAF binary not found at %s", binaryPath)
	}

	reportsDir := filepath.Join(projectRoot, "reports")
	if err := os.MkdirAll(reportsDir, 0755); err != nil {
		return "", fmt.Errorf("failed to create reports directory: %w", err)
	}

	scanCtx, cancel := context.WithTimeout(ctx, gotestwafTimeout)
	defer cancel()

	cmd := exec.CommandContext(scanCtx, binaryPath,
		"--url", targetURL,
		"--configPath", "gotestwaf-config.yaml",
		"--testCasesPath", "testcases",
		"--maxIdleConns", "2",
		"--maxRedirects", "10",
		"--reportPath", reportsDir,
		"--reportName", reportName,
		"--reportFormat", "html",
		"--wafName", "generic",
		"--skipWAFBlockCheck",
		"--nonBlockedAsPassed",
		"--tlsVerify=false",
		"--noEmailReport",
		"--quiet",
	)

	cmd.Dir = projectRoot

	output, err := cmd.CombinedOutput()
	outputStr := string(output)

	if err != nil {
		if scanCtx.Err() == context.DeadlineExceeded {
			return outputStr, fmt.Errorf("GoTestWAF scan timed out after %v", gotestwafTimeout)
		}
		return outputStr, fmt.Errorf("GoTestWAF scan failed: %w", err)
	}

	return outputStr, nil
}
