import gradio as gr

from mcp_email_server.config import EmailSettings, get_settings, store_settings
from mcp_email_server.tools.installer import install_claude_desktop, is_installed, need_update, uninstall_claude_desktop


def create_ui():  # noqa: C901
    # Create a Gradio interface
    with gr.Blocks(title="Email Settings Configuration") as app:
        gr.Markdown("# Email Settings Configuration")

        # Function to get current accounts
        def get_current_accounts():
            settings = get_settings(reload=True)
            email_accounts = [email.account_name for email in settings.emails]
            return email_accounts

        # Function to update account list display
        def update_account_list():
            settings = get_settings(reload=True)
            email_accounts = [email.account_name for email in settings.emails]

            if email_accounts:
                # Create a detailed list of accounts with more information
                accounts_details = []
                for email in settings.emails:
                    details = [
                        f"**Account Name:** {email.account_name}",
                        f"**Full Name:** {email.full_name}",
                        f"**Email Address:** {email.email_address}",
                    ]

                    if hasattr(email, "description") and email.description:
                        details.append(f"**Description:** {email.description}")

                    # Add IMAP/SMTP provider info if available
                    if hasattr(email, "incoming") and hasattr(email.incoming, "host"):
                        details.append(f"**IMAP Provider:** {email.incoming.host}")

                    if hasattr(email, "outgoing") and hasattr(email.outgoing, "host"):
                        details.append(f"**SMTP Provider:** {email.outgoing.host}")

                    accounts_details.append("### " + email.account_name + "\n" + "\n".join(details) + "\n")

                accounts_md = "\n".join(accounts_details)
                return (
                    f"## Configured Accounts\n{accounts_md}",
                    gr.update(choices=email_accounts, value=None),
                    gr.update(visible=True),
                )
            else:
                return (
                    "No email accounts configured yet.",
                    gr.update(choices=[], value=None),
                    gr.update(visible=False),
                )

        # Display current email accounts and allow deletion
        with gr.Accordion("Current Email Accounts", open=True):
            # Display the list of accounts
            accounts_display = gr.Markdown("")

            # Create a dropdown to select account to delete
            account_to_delete = gr.Dropdown(choices=[], label="Select Account to Delete", interactive=True)

            # Status message for deletion
            delete_status = gr.Markdown("")

            # Delete button
            delete_btn = gr.Button("Delete Selected Account")

            # Function to delete an account
            def delete_email_account(account_name):
                if not account_name:
                    return "Error: Please select an account to delete.", *update_account_list()

                try:
                    # Get current settings
                    settings = get_settings()

                    # Delete the account
                    settings.delete_email(account_name)

                    # Store settings
                    store_settings(settings)

                    # Return success message and update the UI
                    return f"Success: Email account '{account_name}' has been deleted.", *update_account_list()
                except Exception as e:
                    return f"Error: {e!s}", *update_account_list()

            # Connect the delete button to the delete function
            delete_btn.click(
                fn=delete_email_account,
                inputs=[account_to_delete],
                outputs=[delete_status, accounts_display, account_to_delete, delete_btn],
            )

            # Initialize the account list
            app.load(
                fn=update_account_list,
                inputs=None,
                outputs=[accounts_display, account_to_delete, delete_btn],
            )

        # Form for adding a new email account
        with gr.Accordion("Add New Email Account", open=True):
            gr.Markdown("### Add New Email Account")

            # Basic account information
            account_name = gr.Textbox(label="Account Name", placeholder="e.g. work_email")
            full_name = gr.Textbox(label="Full Name", placeholder="e.g. John Doe")
            email_address = gr.Textbox(label="Email Address", placeholder="e.g. john@example.com")

            # Credentials
            user_name = gr.Textbox(label="Username", placeholder="e.g. john@example.com")
            password = gr.Textbox(label="Password", type="password")

            # IMAP settings
            with gr.Row():
                with gr.Column():
                    gr.Markdown("### IMAP Settings")
                    imap_host = gr.Textbox(label="IMAP Host", placeholder="e.g. imap.example.com")
                    imap_port = gr.Number(label="IMAP Port", value=993)
                    imap_ssl = gr.Checkbox(label="Use SSL", value=True)
                    imap_user_name = gr.Textbox(
                        label="IMAP Username (optional)", placeholder="Leave empty to use the same as above"
                    )
                    imap_password = gr.Textbox(
                        label="IMAP Password (optional)",
                        type="password",
                        placeholder="Leave empty to use the same as above",
                    )

                # SMTP settings
                with gr.Column():
                    gr.Markdown("### SMTP Settings")
                    smtp_host = gr.Textbox(label="SMTP Host", placeholder="e.g. smtp.example.com")
                    smtp_port = gr.Number(label="SMTP Port", value=465)
                    smtp_ssl = gr.Checkbox(label="Use SSL", value=True)
                    smtp_start_ssl = gr.Checkbox(label="Start SSL", value=False)
                    smtp_user_name = gr.Textbox(
                        label="SMTP Username (optional)", placeholder="Leave empty to use the same as above"
                    )
                    smtp_password = gr.Textbox(
                        label="SMTP Password (optional)",
                        type="password",
                        placeholder="Leave empty to use the same as above",
                    )

            # Status message
            status_message = gr.Markdown("")

            # Save button
            save_btn = gr.Button("Save Email Settings")

            # Function to save settings
            def save_email_settings(
                account_name,
                full_name,
                email_address,
                user_name,
                password,
                imap_host,
                imap_port,
                imap_ssl,
                imap_user_name,
                imap_password,
                smtp_host,
                smtp_port,
                smtp_ssl,
                smtp_start_ssl,
                smtp_user_name,
                smtp_password,
            ):
                try:
                    # Validate required fields
                    if not account_name or not full_name or not email_address or not user_name or not password:
                        # Get account list update
                        account_md, account_choices, btn_visible = update_account_list()
                        return (
                            "Error: Please fill in all required fields.",
                            account_md,
                            account_choices,
                            btn_visible,
                            account_name,
                            full_name,
                            email_address,
                            user_name,
                            password,
                            imap_host,
                            imap_port,
                            imap_ssl,
                            imap_user_name,
                            imap_password,
                            smtp_host,
                            smtp_port,
                            smtp_ssl,
                            smtp_start_ssl,
                            smtp_user_name,
                            smtp_password,
                        )

                    if not imap_host or not smtp_host:
                        # Get account list update
                        account_md, account_choices, btn_visible = update_account_list()
                        return (
                            "Error: IMAP and SMTP hosts are required.",
                            account_md,
                            account_choices,
                            btn_visible,
                            account_name,
                            full_name,
                            email_address,
                            user_name,
                            password,
                            imap_host,
                            imap_port,
                            imap_ssl,
                            imap_user_name,
                            imap_password,
                            smtp_host,
                            smtp_port,
                            smtp_ssl,
                            smtp_start_ssl,
                            smtp_user_name,
                            smtp_password,
                        )

                    # Get current settings
                    settings = get_settings()

                    # Check if account name already exists
                    for email in settings.emails:
                        if email.account_name == account_name:
                            # Get account list update
                            account_md, account_choices, btn_visible = update_account_list()
                            return (
                                f"Error: Account name '{account_name}' already exists.",
                                account_md,
                                account_choices,
                                btn_visible,
                                account_name,
                                full_name,
                                email_address,
                                user_name,
                                password,
                                imap_host,
                                imap_port,
                                imap_ssl,
                                imap_user_name,
                                imap_password,
                                smtp_host,
                                smtp_port,
                                smtp_ssl,
                                smtp_start_ssl,
                                smtp_user_name,
                                smtp_password,
                            )

                    # Create new email settings
                    email_settings = EmailSettings.init(
                        account_name=account_name,
                        full_name=full_name,
                        email_address=email_address,
                        user_name=user_name,
                        password=password,
                        imap_host=imap_host,
                        smtp_host=smtp_host,
                        imap_port=int(imap_port),
                        imap_ssl=imap_ssl,
                        smtp_port=int(smtp_port),
                        smtp_ssl=smtp_ssl,
                        smtp_start_ssl=smtp_start_ssl,
                        imap_user_name=imap_user_name if imap_user_name else None,
                        imap_password=imap_password if imap_password else None,
                        smtp_user_name=smtp_user_name if smtp_user_name else None,
                        smtp_password=smtp_password if smtp_password else None,
                    )

                    # Add to settings
                    settings.add_email(email_settings)

                    # Store settings
                    store_settings(settings)

                    # Get account list update
                    account_md, account_choices, btn_visible = update_account_list()

                    # Return success message, update the UI, and clear form fields
                    return (
                        f"Success: Email account '{account_name}' has been added.",
                        account_md,
                        account_choices,
                        btn_visible,
                        "",  # Clear account_name
                        "",  # Clear full_name
                        "",  # Clear email_address
                        "",  # Clear user_name
                        "",  # Clear password
                        "",  # Clear imap_host
                        993,  # Reset imap_port
                        True,  # Reset imap_ssl
                        "",  # Clear imap_user_name
                        "",  # Clear imap_password
                        "",  # Clear smtp_host
                        465,  # Reset smtp_port
                        True,  # Reset smtp_ssl
                        False,  # Reset smtp_start_ssl
                        "",  # Clear smtp_user_name
                        "",  # Clear smtp_password
                    )
                except Exception as e:
                    # Get account list update
                    account_md, account_choices, btn_visible = update_account_list()
                    return (
                        f"Error: {e!s}",
                        account_md,
                        account_choices,
                        btn_visible,
                        account_name,
                        full_name,
                        email_address,
                        user_name,
                        password,
                        imap_host,
                        imap_port,
                        imap_ssl,
                        imap_user_name,
                        imap_password,
                        smtp_host,
                        smtp_port,
                        smtp_ssl,
                        smtp_start_ssl,
                        smtp_user_name,
                        smtp_password,
                    )

            # Connect the save button to the save function
            save_btn.click(
                fn=save_email_settings,
                inputs=[
                    account_name,
                    full_name,
                    email_address,
                    user_name,
                    password,
                    imap_host,
                    imap_port,
                    imap_ssl,
                    imap_user_name,
                    imap_password,
                    smtp_host,
                    smtp_port,
                    smtp_ssl,
                    smtp_start_ssl,
                    smtp_user_name,
                    smtp_password,
                ],
                outputs=[
                    status_message,
                    accounts_display,
                    account_to_delete,
                    delete_btn,
                    account_name,
                    full_name,
                    email_address,
                    user_name,
                    password,
                    imap_host,
                    imap_port,
                    imap_ssl,
                    imap_user_name,
                    imap_password,
                    smtp_host,
                    smtp_port,
                    smtp_ssl,
                    smtp_start_ssl,
                    smtp_user_name,
                    smtp_password,
                ],
            )

        # Claude Desktop Integration
        with gr.Accordion("Claude Desktop Integration", open=True):
            gr.Markdown("### Claude Desktop Integration")

            # Status display for Claude Desktop integration
            claude_status = gr.Markdown("")

            # Function to check and update Claude Desktop status
            def update_claude_status():
                if is_installed():
                    if need_update():
                        return "Claude Desktop integration is installed but needs to be updated."
                    else:
                        return "Claude Desktop integration is installed and up to date."
                else:
                    return "Claude Desktop integration is not installed."

            # Buttons for Claude Desktop actions
            with gr.Row():
                install_update_btn = gr.Button("Install to Claude Desktop")
                uninstall_btn = gr.Button("Uninstall from Claude Desktop")

            # Functions for Claude Desktop actions
            def install_or_update_claude():
                try:
                    install_claude_desktop()
                    status = update_claude_status()
                    # Update button states based on new status
                    is_inst = is_installed()
                    needs_upd = need_update()

                    button_text = "Update Claude Desktop" if (is_inst and needs_upd) else "Install to Claude Desktop"
                    button_interactive = not (is_inst and not needs_upd)

                    return [
                        status,
                        gr.update(value=button_text, interactive=button_interactive),
                        gr.update(interactive=is_inst),
                    ]
                except Exception as e:
                    return [f"Error installing/updating Claude Desktop: {e!s}", gr.update(), gr.update()]

            def uninstall_from_claude():
                try:
                    uninstall_claude_desktop()
                    status = update_claude_status()
                    # Update button states based on new status
                    is_inst = is_installed()
                    needs_upd = need_update()

                    button_text = "Update Claude Desktop" if (is_inst and needs_upd) else "Install to Claude Desktop"
                    button_interactive = not (is_inst and not needs_upd)

                    return [
                        status,
                        gr.update(value=button_text, interactive=button_interactive),
                        gr.update(interactive=is_inst),
                    ]
                except Exception as e:
                    return [f"Error uninstalling from Claude Desktop: {e!s}", gr.update(), gr.update()]

            # Function to update button states based on installation status
            def update_button_states():
                status = update_claude_status()
                is_inst = is_installed()
                needs_upd = need_update()

                button_text = "Update Claude Desktop" if (is_inst and needs_upd) else "Install to Claude Desktop"
                button_interactive = not (is_inst and not needs_upd)

                return [
                    status,
                    gr.update(value=button_text, interactive=button_interactive),
                    gr.update(interactive=is_inst),
                ]

            # Connect buttons to functions
            install_update_btn.click(
                fn=install_or_update_claude, inputs=[], outputs=[claude_status, install_update_btn, uninstall_btn]
            )
            uninstall_btn.click(
                fn=uninstall_from_claude, inputs=[], outputs=[claude_status, install_update_btn, uninstall_btn]
            )

            # Initialize Claude Desktop status and button states
            app.load(fn=update_button_states, inputs=None, outputs=[claude_status, install_update_btn, uninstall_btn])

    return app


def main():
    app = create_ui()
    app.launch(inbrowser=True)


if __name__ == "__main__":
    main()
