use crate::editor_runtime::{
    command_sync::sync_persisted_editor_command,
    overlays::{
        current_table_overlay_anchor, table_col_aux_style, table_row_aux_style,
        table_selection_overlay_style, TableOverlayAnchor, TableSelectionKind,
        TableSelectionOverlayState,
    },
    persistence::{persisted_document_identity, PersistedDocumentIdentity},
    table_commands::{
        run_table_option_action, run_table_toolbar_action, table_option_checked,
        TableToolbarAction, TABLE_OPTION_ACTIONS, TABLE_TOOLBAR_ACTIONS,
    },
};
use leptos::prelude::*;
use leptos_tiptap::TiptapEditorHandle;
use serde_json::Value;
use web_sys::MouseEvent;

fn runtime_persisted_identity(
    document_id: ReadSignal<Option<String>>,
    workspace_id: ReadSignal<Option<String>>,
) -> PersistedDocumentIdentity {
    persisted_document_identity(document_id.get_untracked(), workspace_id.get_untracked())
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn table_toolbar_view(
    editor: TiptapEditorHandle,
    table_toolbar_open: ReadSignal<bool>,
    set_table_toolbar_open: WriteSignal<bool>,
    table_options_open: ReadSignal<bool>,
    set_table_options_open: WriteSignal<bool>,
    table_overlay_anchor: ReadSignal<Option<TableOverlayAnchor>>,
    set_table_overlay_anchor: WriteSignal<Option<TableOverlayAnchor>>,
    table_selection_overlay: ReadSignal<Option<TableSelectionOverlayState>>,
    set_table_selection_overlay: WriteSignal<Option<TableSelectionOverlayState>>,
    slash_open: ReadSignal<bool>,
    block_menu_open: ReadSignal<bool>,
    dragging_block_index: ReadSignal<Option<usize>>,
    document_json: ReadSignal<Value>,
    set_document_json: WriteSignal<Value>,
    set_dirty_count: WriteSignal<u32>,
    set_html_output: WriteSignal<String>,
    set_json_output: WriteSignal<String>,
    title: ReadSignal<String>,
    document_id: ReadSignal<Option<String>>,
    workspace_id: ReadSignal<Option<String>>,
    set_command_feedback: WriteSignal<String>,
) -> impl IntoView {
    view! {
        <>
            {move || {
                if !table_toolbar_open.get()
                    || slash_open.get()
                    || block_menu_open.get()
                    || dragging_block_index.get().is_some()
                {
                    return ().into_any();
                }
                let Some(anchor) = table_overlay_anchor.get() else {
                    return ().into_any();
                };
                let controls_style = format!(
                    "left:{:.1}px;top:{:.1}px;width:{:.1}px;height:{:.1}px;",
                    anchor.left, anchor.top, anchor.width, anchor.height
                );
                view! {
                    <div
                        class="table-controls"
                        data-testid="mnote-leptos-tiptap-table-controls"
                        style=controls_style
                    >
                        {move || {
                            table_selection_overlay
                                .get()
                                .map(|selection| {
                                    view! {
                                        <div
                                            class="table-selection-overlay"
                                            data-testid="table-selection-overlay"
                                            data-selection-kind=selection.kind.id()
                                            data-selection-index=selection.index.to_string()
                                            style=table_selection_overlay_style(&anchor, &selection)
                                        ></div>
                                    }
                                })
                                .into_any()
                        }}
                        {(0..anchor.rows).map(|index| {
                            let active = table_selection_overlay
                                .get()
                                .map(|selection| {
                                    selection.kind == TableSelectionKind::Row && selection.index == index
                                })
                                .unwrap_or(false);
                            view! {
                                <button
                                    type="button"
                                    class="table-aux-btn table-row-aux"
                                    data-testid=format!("table-row-aux-{index}")
                                    data-active=active.to_string()
                                    style=table_row_aux_style(&anchor, index)
                                    title="点击插入一行"
                                    aria-label="点击插入一行"
                                    on:mousedown=move |event: MouseEvent| {
                                        event.prevent_default();
                                        event.stop_propagation();
                                    }
                                    on:click=move |event: MouseEvent| {
                                        event.prevent_default();
                                        event.stop_propagation();
                                        set_table_toolbar_open.set(true);
                                        set_table_options_open.set(false);
                                        match run_table_toolbar_action(editor, TableToolbarAction::AddRowAfter) {
                                            Ok(message) => {
                                                sync_persisted_editor_command(
                                                    editor,
                                                    &runtime_persisted_identity(document_id, workspace_id),
                                                    set_dirty_count,
                                                    set_html_output,
                                                    set_document_json,
                                                    set_json_output,
                                                    title,
                                                    set_command_feedback,
                                                    message,
                                                );
                                                if let Err(err) = editor.select_table_row(index as u32) {
                                                    set_command_feedback.set(format!(
                                                        "行已插入，但表格行选区同步失败：{err}"
                                                    ));
                                                }
                                                set_table_overlay_anchor
                                                    .set(current_table_overlay_anchor());
                                                set_table_selection_overlay.set(Some(
                                                    TableSelectionOverlayState {
                                                        kind: TableSelectionKind::Row,
                                                        index,
                                                    },
                                                ));
                                            }
                                            Err(err) => set_command_feedback.set(err),
                                        }
                                    }
                                >"+"</button>
                            }
                        }).collect_view()}
                        {(0..anchor.cols).map(|index| {
                            let active = table_selection_overlay
                                .get()
                                .map(|selection| {
                                    selection.kind == TableSelectionKind::Column
                                        && selection.index == index
                                })
                                .unwrap_or(false);
                            view! {
                                <button
                                    type="button"
                                    class="table-aux-btn table-col-aux"
                                    data-testid=format!("table-col-aux-{index}")
                                    data-active=active.to_string()
                                    style=table_col_aux_style(&anchor, index)
                                    title="点击插入一列"
                                    aria-label="点击插入一列"
                                    on:mousedown=move |event: MouseEvent| {
                                        event.prevent_default();
                                        event.stop_propagation();
                                    }
                                    on:click=move |event: MouseEvent| {
                                        event.prevent_default();
                                        event.stop_propagation();
                                        set_table_toolbar_open.set(true);
                                        set_table_options_open.set(false);
                                        match run_table_toolbar_action(
                                            editor,
                                            TableToolbarAction::AddColumnAfter,
                                        ) {
                                            Ok(message) => {
                                                sync_persisted_editor_command(
                                                    editor,
                                                    &runtime_persisted_identity(document_id, workspace_id),
                                                    set_dirty_count,
                                                    set_html_output,
                                                    set_document_json,
                                                    set_json_output,
                                                    title,
                                                    set_command_feedback,
                                                    message,
                                                );
                                                if let Err(err) = editor.select_table_column(index as u32) {
                                                    set_command_feedback.set(format!(
                                                        "列已插入，但表格列选区同步失败：{err}"
                                                    ));
                                                }
                                                set_table_overlay_anchor
                                                    .set(current_table_overlay_anchor());
                                                set_table_selection_overlay.set(Some(
                                                    TableSelectionOverlayState {
                                                        kind: TableSelectionKind::Column,
                                                        index,
                                                    },
                                                ));
                                            }
                                            Err(err) => set_command_feedback.set(err),
                                        }
                                    }
                                >"+"</button>
                            }
                        }).collect_view()}
                    </div>
                }
                .into_any()
            }}
            {move || {
                if !table_toolbar_open.get()
                    || slash_open.get()
                    || block_menu_open.get()
                    || dragging_block_index.get().is_some()
                {
                    return ().into_any();
                }
                view! {
                    <div
                        class="table-toolbar"
                        data-testid="mnote-leptos-tiptap-table-toolbar"
                        on:mousedown=move |event: MouseEvent| {
                            event.prevent_default();
                            event.stop_propagation();
                        }
                        on:click=move |event: MouseEvent| {
                            event.stop_propagation();
                        }
                    >
                        {TABLE_TOOLBAR_ACTIONS.iter().enumerate().map(|(index, action)| {
                            let action = *action;
                            let testid = format!("table-toolbar-{}", action.id());
                            view! {
                                <>
                                    {if index == 3 {
                                        view! {
                                            <span
                                                class="table-toolbar-separator"
                                                aria-hidden="true"
                                            ></span>
                                        }
                                        .into_any()
                                    } else {
                                        ().into_any()
                                    }}
                                    <button
                                        type="button"
                                        class="table-toolbar-btn"
                                        data-testid=testid
                                        title=action.title()
                                        aria-label=action.title()
                                        on:click=move |_| {
                                            match run_table_toolbar_action(editor, action) {
                                                Ok(message) => {
                                                    if matches!(action, TableToolbarAction::DeleteTable)
                                                    {
                                                        set_table_toolbar_open.set(false);
                                                        set_table_options_open.set(false);
                                                        set_table_overlay_anchor.set(None);
                                                        set_table_selection_overlay.set(None);
                                                    } else {
                                                        set_table_selection_overlay.set(None);
                                                    }
                                                    sync_persisted_editor_command(
                                                        editor,
                                                        &runtime_persisted_identity(document_id, workspace_id),
                                                        set_dirty_count,
                                                        set_html_output,
                                                        set_document_json,
                                                        set_json_output,
                                                        title,
                                                        set_command_feedback,
                                                        message,
                                                    );
                                                    if !matches!(
                                                        action,
                                                        TableToolbarAction::DeleteTable
                                                    ) {
                                                        set_table_overlay_anchor
                                                            .set(current_table_overlay_anchor());
                                                    }
                                                }
                                                Err(err) => set_command_feedback.set(err),
                                            }
                                        }
                                    >
                                        {action.icon()}
                                    </button>
                                </>
                            }
                        }).collect_view()}
                        <span class="table-toolbar-separator" aria-hidden="true"></span>
                        <button
                            type="button"
                            class="table-toolbar-btn"
                            data-testid="table-toolbar-options"
                            title="选项"
                            aria-label="选项"
                            aria-expanded=move || table_options_open.get().to_string()
                            on:click=move |_| {
                                set_table_options_open.update(|open| *open = !*open);
                            }
                        >
                            "选项"
                        </button>
                        {move || {
                            if !table_options_open.get() {
                                return ().into_any();
                            }
                            view! {
                                <div
                                    class="table-options-menu"
                                    data-testid="table-toolbar-options-menu"
                                >
                                    {TABLE_OPTION_ACTIONS.iter().map(|action| {
                                        let action = *action;
                                        let testid = format!("table-option-{}", action.id());
                                        view! {
                                            <button
                                                type="button"
                                                class="table-option-btn"
                                                data-testid=testid
                                                role="switch"
                                                aria-checked=move || {
                                                    table_option_checked(&document_json.get(), action)
                                                        .to_string()
                                                }
                                                on:click=move |_| {
                                                    match run_table_option_action(editor, action) {
                                                        Ok(message) => {
                                                            sync_persisted_editor_command(
                                                                editor,
                                                                &runtime_persisted_identity(
                                                                    document_id,
                                                                    workspace_id,
                                                                ),
                                                                set_dirty_count,
                                                                set_html_output,
                                                                set_document_json,
                                                                set_json_output,
                                                                title,
                                                                set_command_feedback,
                                                                message,
                                                            );
                                                        }
                                                        Err(err) => set_command_feedback.set(err),
                                                    }
                                                }
                                            >
                                                <span>{action.title()}</span>
                                                <span
                                                    class="table-option-switch"
                                                    aria-hidden="true"
                                                ></span>
                                            </button>
                                        }
                                    }).collect_view()}
                                </div>
                            }
                            .into_any()
                        }}
                    </div>
                }
                .into_any()
            }}
        </>
    }
}
