import streamlit as st
import pandas as pd

def editable_dataframe_add():
    st.title("🛠️ 可编辑DataFrame演示, num_rows='dynamic'")

    st.write("下面的表格可以直接编辑，尝试修改评分并查看你最喜欢的命令！")

    # 示例数据
    df = pd.DataFrame(
        [
            {"command": "st.selectbox", "rating": 4, "is_widget": True},
            {"command": "st.balloons", "rating": 5, "is_widget": False},
            {"command": "st.time_input", "rating": 3, "is_widget": True},
        ]
    )
    edited_df = st.data_editor(df, num_rows="dynamic")

    favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
    st.markdown(f"Your favorite command is **{favorite_command}** 🎈")

def editable_dataframe_add_fixed():
    df = pd.DataFrame(
        [
            {"command": "st.selectbox", "rating": 4, "is_widget": True},
            {"command": "st.balloons", "rating": 5, "is_widget": False},
            {"command": "st.time_input", "rating": 3, "is_widget": True},
        ]
    )
    edited_df = st.data_editor(
        df,
        column_config={
            "command": "Streamlit Command",
            "rating": st.column_config.NumberColumn(
                "Your rating",
                help="How much do you like this command (1-5)?",
                min_value=1,
                max_value=5,
                step=1,
                format="%d ⭐",
            ),
            "is_widget": "Widget ?",
        },
        disabled=["command", "is_widget"],
        hide_index=True,
    )

    favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
    st.markdown(f"Your favorite command is **{favorite_command}** 🎈")

def editable_dataframe_basic():
    st.title("✏️ 基础可编辑DataFrame")
    
    # 初始化数据
    if 'edit_df' not in st.session_state:
        st.session_state.edit_df = pd.DataFrame({
            'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
            'Age': [25, 30, 35, 28],
            'City': ['New York', 'London', 'Tokyo', 'Paris'],
            'Salary': [50000, 60000, 70000, 55000],
            'Active': [True, False, True, True]
        })
    
    st.write("📝 双击单元格即可编辑数据：")
    
    # 使用st.data_editor进行编辑
    edited_df = st.data_editor(
        st.session_state.edit_df,
        height=300,
        use_container_width=True,
        num_rows="dynamic",  # 允许添加/删除行
        column_config={
            "Name": st.column_config.TextColumn(
                "姓名",
                help="输入姓名",
                max_chars=50,
                validate="^[A-Za-z ]+$"  # 只允许字母和空格
            ),
            "Age": st.column_config.NumberColumn(
                "年龄",
                help="输入年龄 (18-100)",
                min_value=18,
                max_value=100,
                step=1,
                format="%d岁"
            ),
            "City": st.column_config.SelectboxColumn(
                "城市",
                help="选择城市",
                options=[
                    "New York",
                    "London", 
                    "Tokyo",
                    "Paris",
                    "Beijing",
                    "Sydney"
                ],
                required=True
            ),
            "Salary": st.column_config.NumberColumn(
                "薪资",
                help="输入薪资",
                min_value=0,
                max_value=1000000,
                step=1000,
                format="$%d"
            ),
            "Active": st.column_config.CheckboxColumn(
                "是否活跃",
                help="勾选表示活跃用户",
                default=True
            )
        },
        disabled=["Name"],  # 禁用Name列的编辑
        key="basic_editor"
    )
    
    # 显示更改
    if not edited_df.equals(st.session_state.edit_df):
        st.write("🔄 **数据已更改：**")
        
        col1, col2 = st.columns(2)
        with col1:
            st.write("**原始数据：**")
            st.dataframe(st.session_state.edit_df, use_container_width=True)
        
        with col2:
            st.write("**修改后数据：**")
            st.dataframe(edited_df, use_container_width=True)
        
        # 保存更改按钮
        if st.button("💾 保存更改", type="primary"):
            st.session_state.edit_df = edited_df.copy()
            st.success("✅ 数据已保存！")
            st.rerun()
        
        if st.button("↩️ 撤销更改"):
            st.warning("❌ 已撤销更改")
            st.rerun()

def editable_dataframe_advanced():
    st.title("🔧 高级可编辑DataFrame")
    
    # 初始化复杂数据
    if 'advanced_df' not in st.session_state:
        st.session_state.advanced_df = pd.DataFrame({
            'ID': range(1, 11),
            'Product': [f'Product {i}' for i in range(1, 11)],
            'Category': ['Electronics', 'Clothing', 'Food', 'Books', 'Toys'] * 2,
            'Price': [19.99, 29.99, 9.99, 15.99, 25.99] * 2,
            'Stock': [100, 50, 200, 75, 30, 120, 80, 150, 60, 90],
            'Rating': [4.5, 3.8, 4.2, 4.7, 3.9, 4.1, 4.6, 4.3, 3.7, 4.4],
            'Launch_Date': pd.date_range('2023-01-01', periods=10, freq='30D'),
            'Image_URL': ['https://via.placeholder.com/50x50'] * 10,
            'Available': [True, False, True, True, False, True, True, False, True, True]
        })
    
    st.write("🛍️ 产品管理系统 - 高级编辑功能：")
    
    # 筛选选项
    col1, col2, col3 = st.columns(3)
    with col1:
        category_filter = st.multiselect(
            "筛选类别",
            options=st.session_state.advanced_df['Category'].unique(),
            default=st.session_state.advanced_df['Category'].unique()
        )
    
    with col2:
        price_range = st.slider(
            "价格范围",
            min_value=0.0,
            max_value=50.0,
            value=(0.0, 50.0),
            step=0.01
        )
    
    with col3:
        show_available_only = st.checkbox("只显示可用商品", value=False)
    
    # 应用筛选
    filtered_df = st.session_state.advanced_df[
        (st.session_state.advanced_df['Category'].isin(category_filter)) &
        (st.session_state.advanced_df['Price'] >= price_range[0]) &
        (st.session_state.advanced_df['Price'] <= price_range[1])
    ]
    
    if show_available_only:
        filtered_df = filtered_df[filtered_df['Available'] == True]
    
    # 添加筛选提示
    if len(filtered_df) < len(st.session_state.advanced_df):
        st.info(f"📊 当前显示 {len(filtered_df)} 行（共 {len(st.session_state.advanced_df)} 行）。在筛选状态下，新增行将添加到筛选结果的末尾。")
    
    # 选项：是否编辑完整数据
    edit_mode = st.radio(
        "编辑模式",
        options=["筛选后数据", "完整数据"],
        help="选择'完整数据'可以在任意位置插入新行"
    )
    
    if edit_mode == "筛选后数据":
        # 编辑筛选后的数据
        display_df = filtered_df.copy()
        data_key = "filtered_editor"
    else:
        # 编辑完整数据
        display_df = st.session_state.advanced_df.copy()
        data_key = "full_editor"
    
    # 高级编辑器
    edited_df = st.data_editor(
        display_df,
        height=400,
        use_container_width=True,
        num_rows="dynamic",
        column_config={
            "ID": st.column_config.NumberColumn(
                "ID",
                help="产品ID",
                disabled=True
            ),
            "Product": st.column_config.TextColumn(
                "产品名称",
                help="输入产品名称",
                pinned=True,    # 固定列
                max_chars=100
            ),
            "Category": st.column_config.SelectboxColumn(
                "类别",
                help="选择产品类别",
                options=['Electronics', 'Clothing', 'Food', 'Books', 'Toys', 'Sports', 'Home'],
                required=True
            ),
            "Price": st.column_config.NumberColumn(
                "价格",
                help="输入价格",
                min_value=0.01,
                max_value=9999.99,
                step=0.01,
                format="$%.2f"
            ),
            "Stock": st.column_config.NumberColumn(
                "库存",
                help="输入库存数量",
                min_value=0,
                max_value=10000,
                step=1,
                format="%d件"
            ),
            "Rating": st.column_config.NumberColumn(
                "评分",
                help="产品评分 (1-5)",
                min_value=1.0,
                max_value=5.0,
                step=0.1,
                format="%.1f⭐"
            ),
            "Launch_Date": st.column_config.DateColumn(
                "上架日期",
                help="选择上架日期",
                min_value=pd.Timestamp('2020-01-01'),
                max_value=pd.Timestamp('2030-12-31'),
                format="YYYY-MM-DD"
            ),
            "Image_URL": st.column_config.ImageColumn(
                "产品图片",
                help="产品图片URL"
            ),
            "Available": st.column_config.CheckboxColumn(
                "可用",
                help="产品是否可用",
                default=True
            )
        },
        key=data_key
    )
    
    # 处理数据变化
    if not edited_df.equals(display_df):
        st.write("🔄 **检测到数据变化**")
        
        # 保存按钮
        col_save, col_cancel = st.columns(2)
        with col_save:
            if st.button("💾 保存更改", type="primary"):
                if edit_mode == "完整数据":
                    # 直接更新完整数据
                    st.session_state.advanced_df = edited_df.copy()
                else:
                    # 筛选模式下的保存逻辑
                    # 需要将筛选后的更改合并回原始数据
                    # 这里简化处理：用户需要切换到完整数据模式进行编辑
                    st.warning("⚠️ 在筛选模式下只能添加新行，无法在指定位置插入。请切换到'完整数据'模式进行精确编辑。")
                    
                    # 只处理新增的行
                    new_rows = edited_df[~edited_df.index.isin(display_df.index)]
                    if len(new_rows) > 0:
                        # 为新行分配新的ID
                        max_id = st.session_state.advanced_df['ID'].max()
                        new_rows = new_rows.copy()
                        new_rows['ID'] = range(max_id + 1, max_id + 1 + len(new_rows))
                        
                        # 添加到原始数据末尾
                        st.session_state.advanced_df = pd.concat([st.session_state.advanced_df, new_rows], ignore_index=True)
                        st.success(f"✅ 已添加 {len(new_rows)} 行新数据")
                    else:
                        st.session_state.advanced_df = edited_df.copy()
                        st.success("✅ 数据已保存")
                
                st.rerun()
        
        with col_cancel:
            if st.button("↩️ 取消更改"):
                st.rerun()
    
    # 快速插入工具
    st.subheader("⚡ 快速插入工具")
    
    with st.expander("🔧 精确位置插入", expanded=False):
        col1, col2, col3 = st.columns(3)
        
        with col1:
            insert_position = st.number_input(
                "插入位置（行号）",
                min_value=0,
                max_value=len(st.session_state.advanced_df),
                value=2,
                help="0=开头，2=第2行后"
            )
        
        with col2:
            new_product_name = st.text_input("产品名称", value="New Product")
            new_category = st.selectbox("类别", ['Electronics', 'Clothing', 'Food', 'Books', 'Toys', 'Sports', 'Home'])
        
        with col3:
            new_price = st.number_input("价格", min_value=0.01, value=29.99)
            new_stock = st.number_input("库存", min_value=0, value=100)
        
        # 插入按钮
        col_btn1, col_btn2, col_btn3 = st.columns(3)
        
        with col_btn1:
            if st.button("➕ 在指定位置插入"):
                new_row = pd.DataFrame({
                    'ID': [st.session_state.advanced_df['ID'].max() + 1],
                    'Product': [new_product_name],
                    'Category': [new_category],
                    'Price': [new_price],
                    'Stock': [new_stock],
                    'Rating': [4.0],
                    'Launch_Date': [pd.Timestamp.now().date()],
                    'Image_URL': ['https://via.placeholder.com/50x50'],
                    'Available': [True]
                })
                
                # 在指定位置插入
                if insert_position == 0:
                    st.session_state.advanced_df = pd.concat([new_row, st.session_state.advanced_df], ignore_index=True)
                elif insert_position >= len(st.session_state.advanced_df):
                    st.session_state.advanced_df = pd.concat([st.session_state.advanced_df, new_row], ignore_index=True)
                else:
                    df_before = st.session_state.advanced_df.iloc[:insert_position]
                    df_after = st.session_state.advanced_df.iloc[insert_position:]
                    st.session_state.advanced_df = pd.concat([df_before, new_row, df_after], ignore_index=True)
                
                st.success(f"✅ 已在位置 {insert_position} 插入新产品")
                st.rerun()
        
        with col_btn2:
            if st.button("📝 在第2-3行间插入"):
                new_row = pd.DataFrame({
                    'ID': [st.session_state.advanced_df['ID'].max() + 1],
                    'Product': ['插入产品'],
                    'Category': ['Electronics'],
                    'Price': [35.99],
                    'Stock': [80],
                    'Rating': [4.2],
                    'Launch_Date': [pd.Timestamp.now().date()],
                    'Image_URL': ['https://via.placeholder.com/50x50'],
                    'Available': [True]
                })
                
                # 在第2行后插入（索引2的位置）
                df_before = st.session_state.advanced_df.iloc[:2]
                df_after = st.session_state.advanced_df.iloc[2:]
                st.session_state.advanced_df = pd.concat([df_before, new_row, df_after], ignore_index=True)
                
                st.success("✅ 已在第2-3行间插入新产品")
                st.rerun()
        
        with col_btn3:
            if st.button("🔄 重新排序ID"):
                # 重新分配连续的ID
                st.session_state.advanced_df['ID'] = range(1, len(st.session_state.advanced_df) + 1)
                st.success("✅ ID已重新排序")
                st.rerun()

    # 批量操作
    st.subheader("📋 批量操作")
    col1, col2, col3, col4 = st.columns([1,1,1,1])
    
    with col1:
        if st.button("🛒 全部设为可用"):
            st.session_state.advanced_df['Available'] = True
            st.success("✅ 所有产品已设为可用")
            st.rerun()
    
    with col2:
        if st.button("❌ 全部设为不可用"):
            st.session_state.advanced_df['Available'] = False
            st.success("✅ 所有产品已设为不可用")
            st.rerun()
    
    with col3:
        discount_rate = st.number_input("折扣率 (%)", min_value=0, max_value=50, value=10, label_visibility="collapsed")
        if st.button("💰 应用折扣"):
            st.session_state.advanced_df['Price'] *= (1 - discount_rate / 100)
            st.success(f"✅ 已应用 {discount_rate}% 折扣")
            st.rerun()
    
    with col4:
        # # 修复方案1：使用session_state管理重置确认状态
        # if 'reset_confirm' not in st.session_state:
        #     st.session_state.reset_confirm = False
        
        # if st.button("📊 重置数据"):
        #     st.session_state.reset_confirm = True
        
        # if st.session_state.reset_confirm:
        #     st.warning("⚠️ 确认要重置所有数据吗？此操作不可撤销！")
            
        #     if st.button("✅ 确认重置", type="primary"):
        #         del st.session_state.advanced_df
        #         st.session_state.reset_confirm = False
        #         st.success("✅ 数据已重置")
        #         st.rerun()
        
        #     if st.button("❌ 取消"):
        #         st.session_state.reset_confirm = False
        #         st.rerun()    

        # 方案2：使用expander + checkbox + button的组合
        with st.expander("🗑️ 危险操作", expanded=False):
            if 'reset_confirm' not in st.session_state:
                st.session_state.reset_confirm = False

            st.warning("⚠️ 重置数据将删除所有当前数据！")
            
            confirm_reset = st.checkbox("我确认要重置所有数据", key="confirm_reset_checkbox")
            
            if st.button("📊 执行重置", disabled=not confirm_reset, type="primary"):
                if confirm_reset:
                    # 重置数据
                    del st.session_state.advanced_df
                    # 清除确认状态
                    st.session_state.reset_confirm = False
                    st.success("✅ 数据已重置")
                    st.rerun()
                else:
                    st.session_state.reset_confirm = False
                    st.error("❌ 请先确认重置操作")

    # 统计信息
    st.subheader("📈 统计信息")
    col1, col2, col3, col4 = st.columns(4)
    
    with col1:
        st.metric("总产品数", len(st.session_state.advanced_df))
    
    with col2:
        available_count = len(st.session_state.advanced_df[st.session_state.advanced_df['Available']])
        st.metric("可用产品", available_count)
    
    with col3:
        avg_price = st.session_state.advanced_df['Price'].mean()
        st.metric("平均价格", f"${avg_price:.2f}")
    
    with col4:
        total_stock = st.session_state.advanced_df['Stock'].sum()
        st.metric("总库存", f"{total_stock:,}件")

def editable_dataframe_with_validation():
    st.title("✅ 带数据验证的可编辑DataFrame")
    
    # 初始化数据
    if 'validation_df' not in st.session_state:
        st.session_state.validation_df = pd.DataFrame({
            'Email': ['user1@example.com', 'user2@example.com', 'user3@example.com'],
            'Phone': ['+1-555-0123', '+1-555-0124', '+1-555-0125'],
            'Website': ['https://www.example1.com', 'https://www.example2.com', 'https://www.example3.com'],
            'Score': [85, 92, 78],
            'Grade': ['B', 'A', 'C']
        })
    
    st.write("🔒 此表格包含数据验证规则：")
    
    # 显示验证规则
    with st.expander("📋 查看验证规则"):
        st.markdown("""
        - **Email**: 必须是有效的邮箱格式
        - **Phone**: 必须是 +X-XXX-XXXX 格式
        - **Website**: 必须是有效的URL格式
        - **Score**: 必须在 0-100 之间
        - **Grade**: 只能是 A, B, C, D, F
        """)
    
    # 带验证的编辑器
    edited_df = st.data_editor(
        st.session_state.validation_df,
        height=300,
        use_container_width=True,
        column_config={
            "Email": st.column_config.TextColumn(
                "邮箱",
                help="输入有效的邮箱地址",
                validate=r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
            ),
            "Phone": st.column_config.TextColumn(
                "电话",
                help="格式: +1-555-0123",
                validate=r"^\+\d{1,3}-\d{3}-\d{4}$"
            ),
            "Website": st.column_config.LinkColumn(
                "网站",
                help="输入完整的URL",
                validate=r"^https?://[^\s/$.?#].[^\s]*$"
            ),
            "Score": st.column_config.NumberColumn(
                "分数",
                help="输入 0-100 之间的分数",
                min_value=0,
                max_value=100,
                step=1
            ),
            "Grade": st.column_config.SelectboxColumn(
                "等级",
                help="选择等级",
                options=['A', 'B', 'C', 'D', 'F'],
                required=True
            )
        },
        key="validation_editor"
    )
    
    # 验证结果
    if st.button("🔍 验证数据"):
        errors = []
        
        # 邮箱验证
        import re
        email_pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
        for idx, email in enumerate(edited_df['Email']):
            if not re.match(email_pattern, str(email)):
                errors.append(f"第{idx+1}行: 无效的邮箱格式")
        
        # 电话验证
        phone_pattern = r"^\+\d{1,3}-\d{3}-\d{4}$"
        for idx, phone in enumerate(edited_df['Phone']):
            if not re.match(phone_pattern, str(phone)):
                errors.append(f"第{idx+1}行: 无效的电话格式")
        
        if errors:
            st.error("❌ 发现以下错误：")
            for error in errors:
                st.error(f"• {error}")
        else:
            st.success("✅ 所有数据验证通过！")

page = st.radio("Select Page", [
    "🔧 Editable DataFrame - add rows",
    "🔧 Editable DataFrame - add rows (fixed)",
    "🔧 Editable DataFrame - Basic",
    "🔧 Editable DataFrame - Advanced",
    "✅ Editable DataFrame - With Validation"
])
if page == "🔧 Editable DataFrame - add rows":
    editable_dataframe_add()
elif page == "🔧 Editable DataFrame - add rows (fixed)":
    editable_dataframe_add_fixed()
elif page == "🔧 Editable DataFrame - Basic":
    editable_dataframe_basic()
elif page == "🔧 Editable DataFrame - Advanced":
    editable_dataframe_advanced()
elif page == "✅ Editable DataFrame - With Validation":
    editable_dataframe_with_validation()