#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" subprocess-based bash/powershell code execution """

import traceback
import subprocess
from typing import Any, Dict, Optional

from loguru import logger

from .types import ProcessResult

class SubprocessExecutor:
    """使用 subprocess 执行代码块"""
    name = None
    command = None
    timeout = 30  # 默认超时时间为10秒

    def __init__(self, runtime=None):
        self.runtime = runtime
        self.log = logger.bind(src=f'{self.name}_executor')

    def get_cmd(self, block) -> Optional[str]:
        """获取执行命令"""
        path = block.abs_path
        if path:
            cmd = self.command.copy()
            cmd.append(str(path))
        else:
            cmd = None
        return cmd
    
    def __call__(self, block) -> ProcessResult:
        """执行代码块"""
        cmd = self.get_cmd(block)
        if not cmd:
            return ProcessResult(errstr='No file to execute')

        self.log.info(f"Exec: {cmd}")

        try:
            cp = subprocess.run(
                cmd,
                shell=False,
                capture_output=True,
                text=True,
                encoding="utf-8",
                errors="ignore",
                timeout=self.timeout
            )
            stdout = cp.stdout.strip() if cp.stdout else None
            stderr = cp.stderr.strip() if cp.stderr else None

            result = ProcessResult(
                stdout=stdout,
                stderr=stderr,
                returncode=cp.returncode
            )
        except subprocess.TimeoutExpired:
            result = ProcessResult(errstr=f'Execution timed out after {self.timeout} seconds')
        except Exception as e:
            result = ProcessResult(errstr=str(e), traceback=str(traceback.format_exc()))

        return result
    
class BashExecutor(SubprocessExecutor):
    name = 'bash'
    command = ['bash']

class PowerShellExecutor(SubprocessExecutor):
    name = 'powershell'
    command = ['powershell', '-Command']

class AppleScriptExecutor(SubprocessExecutor):
    name = 'applescript'
    command = ['osascript']
    
class NodeExecutor(SubprocessExecutor):
    name = 'javascript'
    command = ['node']

class MarkdownExecutor(SubprocessExecutor):
    name = 'markdown'

    def __call__(self, block) -> ProcessResult:
        """Markdown 不执行，只返回成功"""
        return ProcessResult(returncode=0, stdout="Markdown file created/updated successfully")