//! Pre-write validation and auto-fix for edited content.
//!
//! All checks operate on in-memory content — nothing is written to disk.
//! The caller is responsible for writing the validated/fixed content.
//!
//! Post-write syntax check (`post_edit_syntax_check`) needs the file on disk
//! (runs external commands like `node --check`) and is called separately after write.

/// Result of `validate_and_fix`: the (possibly fixed) content, any warnings,
/// and whether any auto-fix was applied.
pub struct ValidateResult {
    pub fixed_content: String,
    pub warnings: Vec<String>,
    pub was_fixed: bool,
    /// If true, the edit should be REJECTED — don't write to disk.
    /// The model must fix its edit and retry.
    pub rejected: bool,
}

/// Run all pre-write validations on the content in memory:
/// 1. Duplicate block detection
/// 2. Brace auto-fix
/// 3. HTML tag auto-fix
///
/// Returns a `ValidateResult` with the (possibly fixed) content.
/// The caller should write `fixed_content` to disk, then optionally call
/// `post_edit_syntax_check` for on-disk syntax validation.
/// `content` is the post-edit content (what would be written to disk).
/// `original_content` is the pre-edit content (for delta validation).
pub async fn validate_and_fix(
    content: &str,
    _file_path: &str,
    _new_string: &str,
    _original_content: &str,
) -> ValidateResult {
    let warnings: Vec<String> = Vec::new();
    let current = content.to_string();

    // Duplicate detection REMOVED.
    // Zero proven positive value across all sessions.
    // False positives on HTML (repeated <div>/<button>) caused edit rejections.
    // auto-compile catches real structural errors with better diagnostics.

    // Structural checks (brace balance, HTML balance, Vue SFC) REMOVED.
    // auto-compile after edit catches all structural errors with better
    // diagnostics (line number + error type from compiler).
    // Delta validation was net negative: 7 false rejections today, 0 true catches.
    // Principle: "don't block the model, enhance the tool."

    if !warnings.is_empty() {
        return ValidateResult {
            fixed_content: current,
            warnings,
            was_fixed: false,
            rejected: true,
        };
    }

    ValidateResult {
        fixed_content: current,
        warnings: vec![],
        was_fixed: false,
        rejected: false,
    }
}

/// Post-edit syntax check for common file types.
/// Runs a fast, non-destructive check and returns a warning if syntax is broken.
/// This needs the file to be on disk — call AFTER writing.
pub async fn post_edit_syntax_check(file_path: &str) -> String {
    let ext = file_path.rsplit('.').next().unwrap_or("");
    let cmd = match ext {
        "js" | "mjs" | "cjs" => Some(("node", vec!["--check".to_string(), file_path.to_string()])),
        "json" => {
            // Validate JSON by attempting parse
            return match tokio::fs::read_to_string(file_path).await {
                Ok(content) => {
                    if serde_json::from_str::<serde_json::Value>(&content).is_err() {
                        format!(
                            "\n\u{26a0} SYNTAX ERROR: {} is not valid JSON. Fix before proceeding.",
                            file_path
                        )
                    } else {
                        String::new()
                    }
                }
                Err(_) => String::new(),
            };
        }
        "ts" | "tsx" => {
            return String::new();
        }
        "vue" | "svelte" => {
            // Quick checks for common Vue SFC errors:
            // 1. Nested backticks in <script> (template strings containing `)
            // 2. Fast build check if no dev server is running
            let mut warnings = Vec::new();

            if let Ok(content) = tokio::fs::read_to_string(file_path).await {
                // Check for nested backticks in <script> section
                if let Some(script_start) = content.find("<script") {
                    let script_end = content.find("</script>").unwrap_or(content.len());
                    let script = &content[script_start..script_end];
                    // Count backticks — odd number means unclosed template string
                    let backtick_count = script.chars().filter(|c| *c == '`').count();
                    if backtick_count % 2 != 0 {
                        warnings.push(format!(
                            "Unclosed template string (`) in <script> — {} backticks found (odd). \
                             Use regular strings ('') for data containing backticks.",
                            backtick_count
                        ));
                    }
                }
            }

            // NOTE: auto-build removed — violates "do NOT deploy" principle.
            // Model should run build manually via bash when it wants to verify.

            if warnings.is_empty() {
                return String::new();
            }
            return format!("\n⚠ VUE SYNTAX: {}", warnings.join("; "));
        }
        "py" => Some((
            "python3",
            vec![
                "-m".to_string(),
                "py_compile".to_string(),
                file_path.to_string(),
            ],
        )),
        _ => None,
    };

    if let Some((program, args)) = cmd {
        let mut command = tokio::process::Command::new(program);
        command.args(&args);
        crate::process_utils::suppress_console_window(&mut command);
        match command.output().await {
            Ok(output) if !output.status.success() => {
                let stderr = String::from_utf8_lossy(&output.stderr);
                let first_lines: String = stderr.lines().take(3).collect::<Vec<_>>().join("\n");
                format!("\n\u{26a0} SYNTAX ERROR in {}:\n{}", file_path, first_lines)
            }
            _ => String::new(),
        }
    } else {
        String::new()
    }
}