import dash
import dash_mantine_components as dmc
import numpy as np
from dash import MATCH, ALL, Dash, Input, Output, State, _dash_renderer, clientside_callback, dcc, html, no_update, callback
from dash_iconify import DashIconify
import pandas as pd
import uuid
_dash_renderer._set_react_version("18.2.0")
# Generate random data
np.random.seed(42)  # for reproducibility
# Sample data for names and countries
first_names = ['James', 'Mary', 'John', 'Patricia', 'Robert', 'Jennifer', 'Michael', 'Linda', 'William', 'Elizabeth',
               'David', 'Barbara', 'Richard', 'Susan', 'Joseph', 'Jessica', 'Thomas', 'Sarah', 'Charles', 'Karen']
last_names = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez',
              'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson', 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin']
countries = ['USA', 'Canada', 'UK', 'Australia', 'Germany', 'France', 'Japan', 'Brazil', 'India', 'China',
             'Italy', 'Spain', 'Mexico', 'South Korea', 'Russia', 'Netherlands', 'Switzerland', 'Sweden', 'Norway', 'Denmark']
# Generate 1000 random entries
n_entries = 1000
df = pd.DataFrame({
    'first_name': np.random.choice(first_names, n_entries),
    'last_name': np.random.choice(last_names, n_entries),
    'country': np.random.choice(countries, n_entries),
    'age': np.random.randint(18, 80, n_entries),
    'salary': np.random.randint(30000, 150000, n_entries)
})
# Combine first and last names
df['full_name'] = df['first_name'] + ' ' + df['last_name']
df['id'] = [uuid.uuid4().hex for _ in range(n_entries)]
app = Dash(__name__)
app.layout = dmc.MantineProvider(
    children=[
        dmc.Container(
            size='md',
            p='md',
            children=dmc.Stack(
                children=[
                    dmc.Title(
                        'Clientside searchable table with pagination',
                        order=3,
                    ),
                    dmc.Group(
                        justify='left',
                        children=[
                            dmc.TextInput(
                                id='search',
                                placeholder='Enter any text to search',
                                label='Search',
                            ),
                        ],
                    ),
                    dmc.Container(
                        fluid=True,
                        pos="relative",
                        children=[
                            dmc.LoadingOverlay(
                                visible=False,
                                id="loading-overlay",
                                overlayProps={"radius": "sm", "blur": 2},
                                zIndex=10,
                            ),
                            html.Div(
                                id='container',
                                children=dmc.Container(
                                    mx='md',
                                    px=0,
                                    fluid=True,
                                    children=[
                                        dmc.Skeleton(h=10, my="md"),
                                        dmc.Skeleton(h=10, my="md"),
                                        dmc.Skeleton(h=10, my="md"),
                                    ]
                                )
                            ),
                        ]
                    ),
                    dmc.Group(
                        justify='right',
                        children=dmc.Pagination(
                            id='pagination',
                            value=1,
                            total=df.shape[0],
                            size='sm',
                        )
                    ),
                    dcc.Store(
                        id='store-data',
                        data=df.to_dict(orient='records'),
                    ),
                    dcc.Store(id="edit-btn-store", data={}),
                    dmc.Modal(
                        id='modal',
                    )
                ]
            )
        )
    ]
)
clientside_callback(
    """
    function(search, page, data) {
        const dmc = window.dash_mantine_components;
        const dash_iconify = window.dash_iconify;
        if (search && search.length > 0) {
            const searchUpper = search.toUpperCase();
            data = data.filter(row => {
                return Object.values(row).some(value => {
                    return String(value).toUpperCase().includes(searchUpper);
                });
            });
        }
        const length = 100;
        page = page || 1;
        const startIdx = (page - 1) * length;
        const endIdx = Math.min(startIdx + length, data.length);
        const pageData = data.slice(startIdx, endIdx);
        const header = React.createElement(dmc.TableThead, {
            children: React.createElement(dmc.TableTr, {
                children: [
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'First Name',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Last Name',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Country',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Age',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Salary',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }), 
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Full Name',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                    React.createElement(dmc.TableTh, {
                        children: React.createElement(dmc.Text, {
                            children: 'Edit',
                            size: 'sm',
                            fw: 'bold'
                        })
                    }),
                ]
            })
        });
        const rows = pageData.map(row => {
            const rowCopy = {...row};
           
            const rowId = dash_component_api.stringifyId({
                index: row.id,
                type: 'edit-btn'
            });
            
            const cells = [
                React.createElement(dmc.Text, {children: rowCopy.first_name, size: 'sm'}),
                React.createElement(dmc.Text, {children: rowCopy.last_name, size: 'sm'}),
                React.createElement(dmc.Text, {children: rowCopy.country, size: 'sm'}),
                React.createElement(dmc.Text, {children: rowCopy.age, size: 'sm'}),
                React.createElement(dmc.Text, {children: rowCopy.salary, size: 'sm'}),
                React.createElement(dmc.Text, {children: rowCopy.full_name, size: 'sm'}),
                React.createElement(dmc.ActionIcon, {
                    id: rowId,
                    n_clicks: 0,
                    variant: 'transparent',
                    onClick: () => {dash_clientside.set_props('edit-btn-store', {data: new Date().toISOString()})},                   
                    children: React.createElement(dash_iconify.DashIconify, {
                        icon: 'mdi:pencil',
                        height: 16
                    })
                })
            ]
            return React.createElement(
                dmc.TableTr,
                {},
                cells.map((cell, index) => {
                    return React.createElement(
                        dmc.TableTd,
                        {
                            children: cell,
                        },
                    );
                })
            );
        });
        dash_clientside.set_props('pagination', {
            total: Math.ceil(data.length / 100),
        });
        const table = React.createElement(dmc.Table, {
            striped: true,
            withRowBorders: true,
            withColumnBorders: false,
            highlightOnHover: false,
            stickyHeader: true,
        }, [header, rows]);
        const scrollArea = React.createElement(dmc.ScrollArea, {
            h: '800px',
            children: table,
        });
        return [
            scrollArea,
        ];
    }
    """,
    Output('container', 'children'),
    Input('search', 'value'),
    Input('pagination', 'value'),
    State('store-data', 'data'),
    running=(Output('loading-overlay', 'visible'), True, False),
    prevent_initial_call=False,
)
@callback(
    Output('modal', 'opened'),
    Input('edit-btn-store', 'data'),
    prevent_initial_call=True,
)
def func(click_data):
    if not any(click_data):
        return False
    print('entered callback')
    return True
if __name__ == "__main__":
    app.run(debug=True)