import streamlit as st
import io
import sys
from contextlib import redirect_stdout
import re
import mistune

# Set page config
st.set_page_config(page_title="Python Code Executor", layout="wide", page_icon="๐Ÿงช")

# Default example code
DEFAULT_CODE = '''import streamlit as st
import random

# Title and introduction
st.title("๐Ÿงช Test Program")
st.markdown("Welcome to this simple test application!")

# Create two columns
col1, col2 = st.columns(2)

with col1:
    # Number input
    number = st.number_input("Enter a number:", min_value=1, max_value=100, value=50)
    
    # Slider
    multiplier = st.slider("Select multiplier:", 1, 10, 5)
    
    # Calculate and display result
    if st.button("Calculate"):
        result = number * multiplier
        st.success(f"Result: {result}")

with col2:
    # Color picker
    color = st.color_picker("Pick a color", "#00f900")
    
    # Display a box with the selected color
    st.markdown(
        f"""
        <div style="background-color: {color}; padding: 20px; border-radius: 5px;">
            Selected color: {color}
        </div>
        """,
        unsafe_allow_html=True
    )
    
    # Random number generator
    if st.button("Generate Random Number"):
        random_num = random.randint(1, 100)
        st.balloons()
        st.write(f"Random number: {random_num}")

# Add a text input with a toggle
show_text_input = st.toggle("Show text input")
if show_text_input:
    user_text = st.text_input("Enter some text:")
    if user_text:
        st.write("You entered:", user_text)

# Add an expander with additional information
with st.expander("About this app"):
    st.write("""
    This is a simple test application demonstrating various Streamlit features:
    - Number inputs and sliders
    - Calculations
    - Color picker
    - Random number generation
    - Text input with toggle
    - Columns layout
    """)'''

def extract_python_code(markdown_text):
    """Extract Python code blocks from markdown text."""
    pattern = r"```python\s*(.*?)\s*```"
    matches = re.findall(pattern, markdown_text, re.DOTALL)
    return matches

def execute_code(code):
    """Execute Python code and return the output."""
    # Create string buffer to capture output
    buffer = io.StringIO()
    
    # Create a dictionary for local variables
    local_vars = {}
    
    try:
        # Redirect stdout to our buffer
        with redirect_stdout(buffer):
            # Execute the code
            exec(code, {}, local_vars)
        
        # Get the output
        output = buffer.getvalue()
        return output, None
    except Exception as e:
        return None, str(e)
    finally:
        buffer.close()

def main():
    
    st.title("๐Ÿ“ Python Code Executor")
    st.markdown("Enter Python code directly or upload a .py/.md file")
    
    # File uploader
    uploaded_file = st.file_uploader("๐Ÿ“ค Upload a Python (.py) or Markdown (.md) file", 
                                   type=['py', 'md'])
    
    # Initialize session state for code if not exists
    if 'code' not in st.session_state:
        st.session_state.code = DEFAULT_CODE
    
    # Code input area
    if uploaded_file is None:
        code_input = st.text_area("๐Ÿ’ป Python Code Editor:", 
                                value=st.session_state.code,
                                height=400,
                                key="code_editor")
    else:
        content = uploaded_file.getvalue().decode()
        if uploaded_file.type == "text/markdown":
            # Extract Python code from markdown
            code_blocks = extract_python_code(content)
            if code_blocks:
                code_input = code_blocks[0]  # Use the first Python code block found
            else:
                st.error("โŒ No Python code blocks found in the markdown file!")
                return
        else:
            # Assume it's a Python file
            code_input = content
        
        st.code(code_input, language='python')
    
    # Button columns
    col1, col2, col3 = st.columns([1, 1, 4])
    
    with col1:
        # Execute button
        if st.button("โ–ถ๏ธ Run Code"):
            if code_input:
                st.markdown("### ๐Ÿ“‹ Output:")
                output, error = execute_code(code_input)
                
                if error:
                    st.error(f"โŒ Error:\n{error}")
                elif output:
                    st.code(output)
                else:
                    st.success("โœ… Code executed successfully with no output.")
            else:
                st.warning("โš ๏ธ Please enter some code to execute!")
    
    with col2:
        # Clear button
        if st.button("๐Ÿ—‘๏ธ Clear Code"):
            st.session_state.code = ""
            st.rerun()
    
    # Add some usage information
    with st.expander("โ„น๏ธ How to use"):
        st.markdown("""
        1. Either upload a Python (.py) or Markdown (.md) file containing Python code
        2. Or enter Python code directly in the text area
        3. Use the buttons below the editor to:
           - โ–ถ๏ธ Run Code: Execute the current code
           - ๐Ÿ—‘๏ธ Clear Code: Clear the editor
        
        **Note:** For markdown files, the code should be in Python code blocks like:
        ````
        ```python
        print("Hello World!")
        ```
        ````
        """)
    
    # Add safety information
    with st.expander("โš ๏ธ Safety Notice"):
        st.markdown("""
        - The code executor runs in a restricted environment
        - Some operations may be limited for security reasons
        - Be careful when executing code from unknown sources
        """)

if __name__ == "__main__":
    main()