"""SQL Server Agent job management tools."""

import json
import re
import shutil
from pathlib import Path
from typing import Annotated

from ..config import is_exec_allowed
from ..utils import (
    format_result,
    get_connection,
    row_to_dict,
    rows_to_dicts,
    sanitize_filename,
    validate_sql_syntax,
)


def list_agent_jobs() -> str:
    """List all SQL Server Agent jobs with their basic info, status, and category."""
    query = """
        SELECT j.job_id, j.name as job_name, j.enabled, j.description,
               j.date_created, j.date_modified, c.name as category,
               SUSER_SNAME(j.owner_sid) as owner,
               CASE WHEN ja.run_requested_date IS NOT NULL AND ja.stop_execution_date IS NULL
                    THEN 'Running' ELSE 'Idle' END as current_status
        FROM msdb.dbo.sysjobs j
        LEFT JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
        LEFT JOIN msdb.dbo.sysjobactivity ja ON j.job_id = ja.job_id
            AND ja.session_id = (SELECT MAX(session_id) FROM msdb.dbo.sysjobactivity)
        ORDER BY j.name
    """
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(query)
        return format_result(rows_to_dicts(cursor))
    finally:
        conn.close()


def get_job_steps(
    job_name: Annotated[str, "The name of the SQL Server Agent job"]
) -> str:
    """Get all steps for a specific SQL Server Agent job, including commands and flow control."""
    query = """
        SELECT js.step_id, js.step_name, js.subsystem, js.command, js.database_name,
               js.on_success_action,
               CASE js.on_success_action
                   WHEN 1 THEN 'Quit with success' WHEN 2 THEN 'Quit with failure'
                   WHEN 3 THEN 'Go to next step' WHEN 4 THEN 'Go to step ' + CAST(js.on_success_step_id AS VARCHAR)
               END as on_success_action_desc,
               js.on_fail_action,
               CASE js.on_fail_action
                   WHEN 1 THEN 'Quit with success' WHEN 2 THEN 'Quit with failure'
                   WHEN 3 THEN 'Go to next step' WHEN 4 THEN 'Go to step ' + CAST(js.on_fail_step_id AS VARCHAR)
               END as on_fail_action_desc,
               js.retry_attempts, js.retry_interval
        FROM msdb.dbo.sysjobsteps js
        JOIN msdb.dbo.sysjobs j ON js.job_id = j.job_id
        WHERE j.name = ?
        ORDER BY js.step_id
    """
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(query, (job_name,))
        return format_result(rows_to_dicts(cursor))
    finally:
        conn.close()


def get_job_details(
    job_name: Annotated[str, "The name of the SQL Server Agent job"]
) -> str:
    """Get detailed settings and status of a specific SQL Server Agent job, including last run info."""
    query = """
        SELECT j.job_id, j.name as job_name, j.enabled, j.description, j.start_step_id,
               j.date_created, j.date_modified, c.name as category, SUSER_SNAME(j.owner_sid) as owner,
               j.notify_level_eventlog, j.notify_level_email, j.notify_level_page, j.delete_level,
               (SELECT COUNT(*) FROM msdb.dbo.sysjobschedules jsc WHERE jsc.job_id = j.job_id) as schedule_count,
               (SELECT TOP 1 CASE jh.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded'
                    WHEN 2 THEN 'Retry' WHEN 3 THEN 'Canceled' WHEN 4 THEN 'In Progress' END
                FROM msdb.dbo.sysjobhistory jh WHERE jh.job_id = j.job_id AND jh.step_id = 0
                ORDER BY jh.run_date DESC, jh.run_time DESC) as last_run_status,
               (SELECT TOP 1 CONVERT(DATETIME,
                    STUFF(STUFF(CAST(jh.run_date AS VARCHAR), 5, 0, '-'), 8, 0, '-') + ' ' +
                    STUFF(STUFF(RIGHT('000000' + CAST(jh.run_time AS VARCHAR), 6), 3, 0, ':'), 6, 0, ':'))
                FROM msdb.dbo.sysjobhistory jh WHERE jh.job_id = j.job_id AND jh.step_id = 0
                ORDER BY jh.run_date DESC, jh.run_time DESC) as last_run_datetime,
               (SELECT TOP 1 jh.run_duration FROM msdb.dbo.sysjobhistory jh
                WHERE jh.job_id = j.job_id AND jh.step_id = 0
                ORDER BY jh.run_date DESC, jh.run_time DESC) as last_run_duration_seconds
        FROM msdb.dbo.sysjobs j
        LEFT JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
        WHERE j.name = ?
    """
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(query, (job_name,))
        return format_result(rows_to_dicts(cursor))
    finally:
        conn.close()


def get_job_schedules(
    job_name: Annotated[str, "The name of the SQL Server Agent job"]
) -> str:
    """Get schedules for a specific SQL Server Agent job."""
    query = """
        SELECT s.schedule_id, s.name as schedule_name, s.enabled,
               CASE s.freq_type
                   WHEN 1 THEN 'Once' WHEN 4 THEN 'Daily' WHEN 8 THEN 'Weekly'
                   WHEN 16 THEN 'Monthly' WHEN 32 THEN 'Monthly relative'
                   WHEN 64 THEN 'When SQL Server Agent starts' WHEN 128 THEN 'When computer is idle'
               END as frequency_type,
               s.freq_interval, s.freq_subday_type, s.freq_subday_interval,
               s.freq_relative_interval, s.freq_recurrence_factor,
               CONVERT(TIME, STUFF(STUFF(RIGHT('000000' + CAST(s.active_start_time AS VARCHAR), 6), 3, 0, ':'), 6, 0, ':')) as active_start_time,
               CONVERT(TIME, STUFF(STUFF(RIGHT('000000' + CAST(s.active_end_time AS VARCHAR), 6), 3, 0, ':'), 6, 0, ':')) as active_end_time,
               s.date_created, s.date_modified
        FROM msdb.dbo.sysschedules s
        JOIN msdb.dbo.sysjobschedules js ON s.schedule_id = js.schedule_id
        JOIN msdb.dbo.sysjobs j ON js.job_id = j.job_id
        WHERE j.name = ?
        ORDER BY s.name
    """
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(query, (job_name,))
        return format_result(rows_to_dicts(cursor))
    finally:
        conn.close()


def get_job_history(
    job_name: Annotated[str, "The name of the SQL Server Agent job"],
    limit: Annotated[int, "Number of history records to return (default 50, max 500)"] = 50
) -> str:
    """Get execution history for a specific SQL Server Agent job."""
    safe_limit = min(max(1, int(limit)), 500)
    query = f"""
        SELECT TOP {safe_limit} jh.step_id, jh.step_name,
               CASE jh.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded'
                    WHEN 2 THEN 'Retry' WHEN 3 THEN 'Canceled' WHEN 4 THEN 'In Progress' END as run_status,
               CONVERT(DATETIME,
                   STUFF(STUFF(CAST(jh.run_date AS VARCHAR), 5, 0, '-'), 8, 0, '-') + ' ' +
                   STUFF(STUFF(RIGHT('000000' + CAST(jh.run_time AS VARCHAR), 6), 3, 0, ':'), 6, 0, ':')) as run_datetime,
               jh.run_duration, jh.message
        FROM msdb.dbo.sysjobhistory jh
        JOIN msdb.dbo.sysjobs j ON jh.job_id = j.job_id
        WHERE j.name = ?
        ORDER BY jh.run_date DESC, jh.run_time DESC, jh.step_id
    """
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(query, (job_name,))
        return format_result(rows_to_dicts(cursor))
    finally:
        conn.close()


def _get_procedure_definition(database: str | None, schema: str | None, procedure: str) -> str | None:
    """Get the definition of a stored procedure from the database."""
    schema = schema or "dbo"
    conn = get_connection()
    try:
        cursor = conn.cursor()
        if database:
            db_safe = "".join(c for c in database if c.isalnum() or c in "_-")
            query = f"""
                SELECT m.definition FROM [{db_safe}].sys.sql_modules m
                JOIN [{db_safe}].sys.objects o ON m.object_id = o.object_id
                JOIN [{db_safe}].sys.schemas s ON o.schema_id = s.schema_id
                WHERE o.name = ? AND s.name = ? AND o.type = 'P'
            """
            cursor.execute(query, (procedure, schema))
        else:
            query = """
                SELECT m.definition FROM sys.sql_modules m
                JOIN sys.objects o ON m.object_id = o.object_id
                JOIN sys.schemas s ON o.schema_id = s.schema_id
                WHERE o.name = ? AND s.name = ? AND o.type = 'P'
            """
            cursor.execute(query, (procedure, schema))
        result = row_to_dict(cursor)
        return result.get("definition") if result else None
    except Exception:
        return None
    finally:
        conn.close()


def _get_procedure_definitions_for_command(sql_command: str, default_database: str = None) -> str:
    """Get all stored procedure definitions referenced in a SQL command."""
    pattern = r"(?i)(?:exec|execute)\s+(?:@\w+\s*=\s*)?([\[\]\w]+(?:\.[\[\]\w]+)*)(?=\s|$|;|\(|--)"
    matches = re.findall(pattern, sql_command)

    if not matches:
        return ""

    definitions = []
    seen = set()

    for match in matches:
        full_name = match.replace("[", "").replace("]", "")
        parts = full_name.split(".")

        if len(parts) == 3:
            db, schema, name = parts
        elif len(parts) == 2:
            db, schema, name = default_database, parts[0], parts[1]
        else:
            db, schema, name = default_database, None, parts[0]

        key = f"{db or ''}.{schema or 'dbo'}.{name}"
        if key in seen:
            continue
        seen.add(key)

        definition = _get_procedure_definition(db, schema, name)
        if definition:
            full_name_str = f"{db + '.' if db else ''}{schema + '.' if schema else 'dbo.'}{name}"
            definitions.append(f"""
/*
================================================================================
Stored Procedure: {full_name_str}
================================================================================
{definition}
*/
""")

    return "\n".join(definitions)


def export_enabled_jobs_to_files(
    output_dir: Annotated[str, "The output directory path where job folders and SQL files will be created"]
) -> str:
    """Export all enabled (non-deprecated) SQL Server Agent jobs and their steps to SQL files."""
    steps_query = """
        SELECT j.job_id, j.name AS job_name, j.description AS job_description,
               js.step_id, js.step_name, js.subsystem, js.command, js.database_name
        FROM msdb.dbo.sysjobs j
        INNER JOIN msdb.dbo.sysjobsteps js ON j.job_id = js.job_id
        WHERE j.enabled = 1
        ORDER BY j.name, js.step_id
    """

    jobs_info_query = """
        SELECT j.job_id, j.name AS job_name, j.enabled, j.description, j.start_step_id,
               j.date_created, j.date_modified, c.name AS category, SUSER_SNAME(j.owner_sid) AS owner,
               j.notify_level_eventlog, j.notify_level_email, j.notify_level_page, j.delete_level
        FROM msdb.dbo.sysjobs j
        LEFT JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id
        WHERE j.enabled = 1
        ORDER BY j.name
    """

    schedules_query = """
        SELECT j.name AS job_name, s.schedule_id, s.name AS schedule_name, s.enabled AS schedule_enabled,
               CASE s.freq_type
                   WHEN 1 THEN 'Once' WHEN 4 THEN 'Daily' WHEN 8 THEN 'Weekly'
                   WHEN 16 THEN 'Monthly' WHEN 32 THEN 'Monthly relative'
                   WHEN 64 THEN 'When SQL Server Agent starts' WHEN 128 THEN 'When computer is idle'
               END AS frequency_type,
               s.freq_type AS freq_type_code, s.freq_interval,
               CASE s.freq_subday_type
                   WHEN 1 THEN 'At the specified time' WHEN 2 THEN 'Seconds'
                   WHEN 4 THEN 'Minutes' WHEN 8 THEN 'Hours'
               END AS subday_type,
               s.freq_subday_type AS freq_subday_type_code, s.freq_subday_interval,
               s.freq_relative_interval, s.freq_recurrence_factor,
               s.active_start_date, s.active_end_date, s.active_start_time, s.active_end_time,
               s.date_created AS schedule_created, s.date_modified AS schedule_modified
        FROM msdb.dbo.sysschedules s
        JOIN msdb.dbo.sysjobschedules js ON s.schedule_id = js.schedule_id
        JOIN msdb.dbo.sysjobs j ON js.job_id = j.job_id
        WHERE j.enabled = 1
        ORDER BY j.name, s.name
    """

    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute(steps_query)
        steps_rows = rows_to_dicts(cursor)
        cursor.execute(jobs_info_query)
        jobs_info_rows = rows_to_dicts(cursor)
        cursor.execute(schedules_query)
        schedules_rows = rows_to_dicts(cursor)
    finally:
        conn.close()

    if not steps_rows:
        return "No enabled jobs found in the database."

    # Build jobs info dictionary
    jobs_info = {}
    for row in jobs_info_rows:
        job_name = row["job_name"]
        jobs_info[job_name] = {
            "job_id": str(row["job_id"]),
            "job_name": job_name,
            "enabled": bool(row["enabled"]),
            "description": row["description"] or "",
            "start_step_id": row["start_step_id"],
            "date_created": str(row["date_created"]) if row["date_created"] else None,
            "date_modified": str(row["date_modified"]) if row["date_modified"] else None,
            "category": row["category"] or "",
            "owner": row["owner"] or "",
            "schedules": [],
        }

    # Add schedules
    for row in schedules_rows:
        job_name = row["job_name"]
        if job_name in jobs_info:
            jobs_info[job_name]["schedules"].append({
                "schedule_id": row["schedule_id"],
                "schedule_name": row["schedule_name"] or "",
                "enabled": bool(row["schedule_enabled"]),
                "frequency_type": row["frequency_type"] or "",
                "freq_interval": row["freq_interval"],
                "subday_type": row["subday_type"] or "",
                "freq_subday_interval": row["freq_subday_interval"],
            })

    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    jobs_created = []
    current_job = None
    job_dir = None

    for row in steps_rows:
        job_name = row["job_name"]

        if current_job != job_name:
            current_job = job_name
            job_dir = output_path / sanitize_filename(job_name)
            job_dir.mkdir(parents=True, exist_ok=True)
            jobs_created.append({"job_name": job_name, "directory": str(job_dir), "steps": []})

            if job_name in jobs_info:
                job_info_file = job_dir / "job_info.json"
                job_info_file.write_text(json.dumps(jobs_info[job_name], indent=2, default=str), encoding="utf-8")

        step_id = row["step_id"]
        step_name = row["step_name"]
        command = row["command"] or ""
        database_name = row["database_name"] or ""
        subsystem = row["subsystem"] or ""

        filename = f"{step_id:02d}_{sanitize_filename(step_name)}.sql"

        procedure_definitions = ""
        if subsystem == "TSQL" and command:
            procedure_definitions = _get_procedure_definitions_for_command(command, database_name)

        file_content = f"""-- Job: {job_name}
-- Step ID: {step_id}
-- Step Name: {step_name}
-- Subsystem: {subsystem}
-- Database: {database_name}
-- ============================================

{command}
{procedure_definitions}"""

        (job_dir / filename).write_text(file_content, encoding="utf-8")
        jobs_created[-1]["steps"].append({"step_id": step_id, "step_name": step_name, "filename": filename})

    summary = {
        "output_directory": str(output_path),
        "total_jobs": len(jobs_created),
        "total_steps": sum(len(job["steps"]) for job in jobs_created),
        "jobs": jobs_created,
    }
    return format_result(summary)


def _get_existing_step_ids_from_folder(job_dir: Path) -> list[int]:
    """Scan job folder for existing SQL files and extract their step_ids."""
    step_ids = []
    for sql_file in job_dir.glob("*.sql"):
        match = re.match(r"^(\d+)_", sql_file.stem)
        if match:
            step_ids.append(int(match.group(1)))
    return sorted(step_ids)


def _get_next_available_step_id(job_dir: Path, job_name: str = None) -> int:
    """Determine the next available step_id by checking both folder and database."""
    folder_step_ids = _get_existing_step_ids_from_folder(job_dir)

    db_step_ids = []
    if job_name:
        try:
            query = """
                SELECT step_id FROM msdb.dbo.sysjobsteps js
                JOIN msdb.dbo.sysjobs j ON js.job_id = j.job_id
                WHERE j.name = ? ORDER BY step_id
            """
            conn = get_connection()
            try:
                cursor = conn.cursor()
                cursor.execute(query, (job_name,))
                db_step_ids = [row[0] for row in cursor.fetchall()]
            finally:
                conn.close()
        except Exception:
            pass

    all_step_ids = set(folder_step_ids) | set(db_step_ids)
    return max(all_step_ids) + 1 if all_step_ids else 1


def update_job_step_from_file(
    file_path: Annotated[str, "The absolute path to the SQL file (e.g., /path/to/agent_server_jobs/Job_Name/02_step_name.sql)"]
) -> str:
    """Update a SQL Server Agent job step from an edited SQL file."""
    file_path_obj = Path(file_path)

    if not file_path_obj.exists():
        return format_result({"success": False, "error": f"File not found: {file_path}"})

    if file_path_obj.suffix.lower() != ".sql":
        return format_result({"success": False, "error": "File must be a .sql file"})

    job_dir_name = file_path_obj.parent.name
    filename = file_path_obj.stem
    match = re.match(r"^(\d+)_", filename)
    if not match:
        return format_result({"success": False, "error": "Invalid filename format. Expected: {step_id}_{step_name}.sql"})

    step_id = int(match.group(1))
    file_content = file_path_obj.read_text(encoding="utf-8")

    # Skip header
    lines = file_content.split("\n")
    sql_start_index = 0
    for i, line in enumerate(lines):
        if line.strip() == "-- ============================================":
            sql_start_index = i + 1
            break

    sql_command = "\n".join(lines[sql_start_index:]).strip()

    if not sql_command:
        return format_result({"success": False, "error": "SQL file is empty"})

    # Find actual job name
    job_info_file = file_path_obj.parent / "job_info.json"
    actual_job_name = None
    if job_info_file.exists():
        try:
            job_info = json.loads(job_info_file.read_text(encoding="utf-8"))
            actual_job_name = job_info.get("job_name")
        except (json.JSONDecodeError, KeyError):
            pass

    if not actual_job_name:
        actual_job_name = job_dir_name.replace("_", " ")

    # Verify job step exists
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute("""
            SELECT j.job_id, j.name as job_name, js.step_id, js.step_name, js.subsystem, js.database_name
            FROM msdb.dbo.sysjobs j
            INNER JOIN msdb.dbo.sysjobsteps js ON j.job_id = js.job_id
            WHERE j.name = ? AND js.step_id = ?
        """, (actual_job_name, step_id))
        step_info = row_to_dict(cursor)
    finally:
        conn.close()

    if not step_info:
        return format_result({"success": False, "error": f"Job step not found: job='{actual_job_name}', step_id={step_id}"})

    # Validate SQL
    validation_result = validate_sql_syntax(sql_command)
    if not validation_result["valid"]:
        return format_result({"success": False, "error": f"SQL validation failed: {validation_result['error']}"})

    if not is_exec_allowed():
        return format_result({"success": False, "error": "EXEC operations are disabled by configuration."})

    # Update job step
    try:
        conn = get_connection()
        try:
            cursor = conn.cursor()
            cursor.execute("EXEC msdb.dbo.sp_update_jobstep @job_name = ?, @step_id = ?, @command = ?",
                         (actual_job_name, step_id, sql_command))
            conn.commit()
        finally:
            conn.close()

        return format_result({
            "success": True,
            "message": "Successfully updated job step",
            "job_name": actual_job_name,
            "step_id": step_id,
            "step_name": step_info["step_name"],
        })
    except Exception as e:
        return format_result({"success": False, "error": f"Failed to update job step: {str(e)}"})


def create_job_step_from_file(
    file_path: Annotated[str, "The absolute path to the new SQL file (e.g., /path/to/agent_server_jobs/Job_Name/my_new_step.sql)"],
    database_name: Annotated[str | None, "The database name for the step (defaults to 'master')"] = None,
    auto_rename: Annotated[bool, "If true, automatically rename files with incorrect format"] = True
) -> str:
    """Create a new SQL Server Agent job step from a SQL file. Auto-renames files to {step_id}_{step_name}.sql format."""
    file_path_obj = Path(file_path)

    if not file_path_obj.exists():
        return format_result({"success": False, "error": f"File not found: {file_path}"})

    job_dir = file_path_obj.parent

    # Get job name from job_info.json
    job_info_file = job_dir / "job_info.json"
    actual_job_name = None
    if job_info_file.exists():
        try:
            job_info = json.loads(job_info_file.read_text(encoding="utf-8"))
            actual_job_name = job_info.get("job_name")
        except (json.JSONDecodeError, KeyError):
            pass

    if not actual_job_name:
        return format_result({"success": False, "error": "Could not find job_info.json. Cannot determine job name."})

    # Validate/fix filename format
    if file_path_obj.suffix.lower() != ".sql":
        if auto_rename:
            new_path = file_path_obj.with_suffix(".sql")
            shutil.move(str(file_path_obj), str(new_path))
            file_path_obj = new_path
        else:
            return format_result({"success": False, "error": "File must have .sql extension"})

    filename = file_path_obj.stem
    match = re.match(r"^(\d+)_(.+)$", filename)

    if not match:
        step_name = re.sub(r"^\d+[\s_-]*", "", filename).strip() or "new_step"
        step_name_sanitized = sanitize_filename(step_name)
        next_step_id = _get_next_available_step_id(job_dir, actual_job_name)
        new_filename = f"{next_step_id:02d}_{step_name_sanitized}.sql"
        new_path = job_dir / new_filename

        if auto_rename:
            shutil.move(str(file_path_obj), str(new_path))
            file_path_obj = new_path
            filename = file_path_obj.stem
            match = re.match(r"^(\d+)_(.+)$", filename)
        else:
            return format_result({
                "success": False,
                "error": "Invalid filename format. Expected: {step_id}_{step_name}.sql",
                "suggestion": {"suggested_name": new_filename, "suggested_step_id": next_step_id},
            })

    step_id = int(match.group(1))
    step_name_from_file = match.group(2).replace("_", " ")

    # Verify job exists
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute("SELECT job_id, name FROM msdb.dbo.sysjobs WHERE name = ?", (actual_job_name,))
        job_info_db = row_to_dict(cursor)
    finally:
        conn.close()

    if not job_info_db:
        return format_result({"success": False, "error": f"Job not found: '{actual_job_name}'"})

    # Check if step_id already exists
    conn = get_connection()
    try:
        cursor = conn.cursor()
        cursor.execute("""
            SELECT step_id, step_name FROM msdb.dbo.sysjobsteps js
            JOIN msdb.dbo.sysjobs j ON js.job_id = j.job_id
            WHERE j.name = ? AND js.step_id = ?
        """, (actual_job_name, step_id))
        existing_step = row_to_dict(cursor)
    finally:
        conn.close()

    if existing_step:
        next_available = _get_next_available_step_id(job_dir, actual_job_name)
        return format_result({
            "success": False,
            "error": f"Step ID {step_id} already exists",
            "suggestion": {"next_available_step_id": next_available},
        })

    # Read SQL content
    file_content = file_path_obj.read_text(encoding="utf-8")
    lines = file_content.split("\n")
    sql_start_index = 0
    for i, line in enumerate(lines):
        if line.strip() == "-- ============================================":
            sql_start_index = i + 1
            break

    sql_command = "\n".join(lines[sql_start_index:]).strip() if sql_start_index > 0 else file_content.strip()

    if not sql_command:
        return format_result({"success": False, "error": "SQL file is empty"})

    # Validate SQL
    validation_result = validate_sql_syntax(sql_command)
    if not validation_result["valid"]:
        return format_result({"success": False, "error": f"SQL validation failed: {validation_result['error']}"})

    db_name = database_name or "master"

    if not is_exec_allowed():
        return format_result({"success": False, "error": "EXEC operations are disabled by configuration."})

    # Create job step
    try:
        conn = get_connection()
        try:
            cursor = conn.cursor()
            cursor.execute("""
                EXEC msdb.dbo.sp_add_jobstep
                    @job_name = ?, @step_id = ?, @step_name = ?,
                    @subsystem = N'TSQL', @command = ?, @database_name = ?,
                    @on_success_action = 1, @on_fail_action = 2,
                    @retry_attempts = 0, @retry_interval = 0
            """, (actual_job_name, step_id, step_name_from_file, sql_command, db_name))
            conn.commit()
        finally:
            conn.close()

        # Update file with proper header
        updated_content = f"""-- Job: {actual_job_name}
-- Step ID: {step_id}
-- Step Name: {step_name_from_file}
-- Subsystem: TSQL
-- Database: {db_name}
-- ============================================

{sql_command}
"""
        file_path_obj.write_text(updated_content, encoding="utf-8")

        return format_result({
            "success": True,
            "message": "Successfully created new job step",
            "job_name": actual_job_name,
            "step_id": step_id,
            "step_name": step_name_from_file,
            "database_name": db_name,
        })
    except Exception as e:
        return format_result({"success": False, "error": f"Failed to create job step: {str(e)}"})
