using System.Data;
using System.Text;
using ComputerSalesApp.Data;
using ComputerSalesApp.Models;
using ComputerSalesApp.Services;

namespace ComputerSalesApp.UI;

internal sealed class MainForm : Form
{
    private readonly UserSession _session;
    private readonly TableRepository _repository = new();
    private readonly List<TableDefinition> _tables;

    private readonly ListBox _tableList = new();
    private readonly DataGridView _dataGrid = new();
    private readonly Button _refreshButton = new();
    private readonly Button _addButton = new();
    private readonly Button _editButton = new();
    private readonly Button _deleteButton = new();
    private readonly Button _logoutButton = new();
    private readonly Label _currentTableLabel = new();
    private readonly Label _userLabel = new();

    private readonly ComboBox _reportCustomerCombo = new();
    private readonly DateTimePicker _reportDatePicker = new();
    private readonly ComboBox _reportSortCombo = new();
    private readonly Button _reportFindButton = new();
    private readonly Button _reportExportButton = new();
    private readonly DataGridView _reportGrid = new();
    private readonly Label _reportHintLabel = new();

    private TableDefinition? CurrentTable => _tableList.SelectedItem as TableDefinition;

    public bool LogoutRequested { get; private set; }

    public MainForm(UserSession session)
    {
        _session = session;
        _tables = TableCatalog.CreateTables(session)
            .Where(t => !t.AdminOnly || session.IsAdmin)
            .ToList();

        Text = "Продажа компьютерной техники";
        StartPosition = FormStartPosition.CenterScreen;
        MinimumSize = new Size(1120, 730);
        BackColor = AppTheme.Background;
        BuildUi();
        Load += MainForm_Load;
    }

    private void BuildUi()
    {
        var root = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 2,
            ColumnCount = 1,
            BackColor = AppTheme.Background
        };
        root.RowStyles.Add(new RowStyle(SizeType.Absolute, 82));
        root.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        Controls.Add(root);

        var header = new Panel
        {
            Dock = DockStyle.Fill,
            BackColor = AppTheme.Header,
            Padding = new Padding(24, 12, 18, 8)
        };
        root.Controls.Add(header, 0, 0);

        var title = new Label
        {
            Text = "Продажа компьютерной техники",
            ForeColor = Color.White,
            Font = AppTheme.Bold(17f),
            AutoSize = true,
            Location = new Point(24, 14)
        };
        header.Controls.Add(title);

        string roleText = _session.IsAdmin ? "администратор" : "покупатель";
        _userLabel.Text = $"Пользователь: {_session.Login} | Роль: {roleText}";
        _userLabel.ForeColor = Color.WhiteSmoke;
        _userLabel.Font = AppTheme.Regular(10f);
        _userLabel.AutoSize = true;
        _userLabel.Location = new Point(26, 48);
        header.Controls.Add(_userLabel);

        _logoutButton.Text = "Выйти";
        _logoutButton.Width = 120;
        _logoutButton.Height = 36;
        _logoutButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
        _logoutButton.Location = new Point(header.Width - _logoutButton.Width - 18, 23);
        AppTheme.StyleSecondaryButton(_logoutButton);
        _logoutButton.Click += (_, _) =>
        {
            LogoutRequested = true;
            Close();
        };
        header.Controls.Add(_logoutButton);
        header.Resize += (_, _) => _logoutButton.Location = new Point(header.Width - _logoutButton.Width - 18, 23);

        var tabs = new TabControl
        {
            Dock = DockStyle.Fill,
            Font = AppTheme.Regular(10f)
        };
        root.Controls.Add(tabs, 0, 1);

        var dataTab = new TabPage("Данные") { BackColor = AppTheme.Background };
        var reportTab = new TabPage("Заказы покупателя по дате") { BackColor = AppTheme.Background };
        tabs.TabPages.Add(dataTab);
        tabs.TabPages.Add(reportTab);

        BuildDataTab(dataTab);
        BuildReportTab(reportTab);
    }

    private void BuildDataTab(TabPage tab)
    {
        var layout = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 1,
            ColumnCount = 2,
            BackColor = AppTheme.Background,
            Padding = new Padding(0)
        };
        layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 290));
        layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
        tab.Controls.Add(layout);

        var sidebar = new Panel
        {
            Dock = DockStyle.Fill,
            BackColor = AppTheme.Surface,
            Padding = new Padding(18, 16, 18, 14),
            MinimumSize = new Size(290, 0)
        };
        layout.Controls.Add(sidebar, 0, 0);

        var left = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 2,
            ColumnCount = 1,
            Padding = new Padding(0),
            BackColor = AppTheme.Surface
        };
        left.RowStyles.Add(new RowStyle(SizeType.Absolute, 42));
        left.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        sidebar.Controls.Add(left);

        left.Controls.Add(new Label
        {
            Text = "Разделы",
            Dock = DockStyle.Fill,
            Font = AppTheme.Bold(12.5f),
            ForeColor = AppTheme.Text,
            TextAlign = ContentAlignment.MiddleLeft
        }, 0, 0);

        _tableList.Dock = DockStyle.Fill;
        _tableList.Font = AppTheme.Regular(10.5f);
        _tableList.ItemHeight = 24;
        _tableList.BorderStyle = BorderStyle.FixedSingle;
        _tableList.BackColor = Color.White;
        _tableList.ForeColor = AppTheme.Text;
        _tableList.HorizontalScrollbar = false;
        _tableList.IntegralHeight = false;
        _tableList.SelectedIndexChanged += async (_, _) => await LoadCurrentTableAsync();
        left.Controls.Add(_tableList, 0, 1);

        var right = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 3,
            ColumnCount = 1,
            Padding = new Padding(18, 16, 18, 14),
            BackColor = AppTheme.Background
        };
        right.RowStyles.Add(new RowStyle(SizeType.Absolute, 44));
        right.RowStyles.Add(new RowStyle(SizeType.Absolute, 52));
        right.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        layout.Controls.Add(right, 1, 0);

        _currentTableLabel.Text = "Выберите раздел";
        _currentTableLabel.Dock = DockStyle.Fill;
        _currentTableLabel.Font = AppTheme.Bold(14f);
        _currentTableLabel.ForeColor = AppTheme.Text;
        _currentTableLabel.TextAlign = ContentAlignment.MiddleLeft;
        right.Controls.Add(_currentTableLabel, 0, 0);

        var buttons = new FlowLayoutPanel
        {
            Dock = DockStyle.Fill,
            FlowDirection = FlowDirection.LeftToRight,
            BackColor = AppTheme.Background,
            Padding = new Padding(0, 2, 0, 2)
        };
        right.Controls.Add(buttons, 0, 1);

        ConfigureButton(_refreshButton, "Обновить", async (_, _) => await LoadCurrentTableAsync(), primary: true);
        ConfigureButton(_addButton, "Добавить", async (_, _) => await AddRecordAsync());
        ConfigureButton(_editButton, "Изменить", async (_, _) => await EditRecordAsync());
        ConfigureButton(_deleteButton, "Удалить", async (_, _) => await DeleteRecordAsync());

        buttons.Controls.AddRange(new Control[] { _refreshButton, _addButton, _editButton, _deleteButton });

        if (!_session.IsAdmin)
        {
            _addButton.Visible = false;
            _editButton.Visible = false;
            _deleteButton.Visible = false;
        }

        _dataGrid.Dock = DockStyle.Fill;
        _dataGrid.ReadOnly = true;
        _dataGrid.AllowUserToAddRows = false;
        _dataGrid.AllowUserToDeleteRows = false;
        _dataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        _dataGrid.MultiSelect = false;
        AppTheme.StyleGrid(_dataGrid);
        right.Controls.Add(_dataGrid, 0, 2);
    }

    private void BuildReportTab(TabPage tab)
    {
        var root = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 3,
            ColumnCount = 1,
            Padding = new Padding(18),
            BackColor = AppTheme.Background
        };
        root.RowStyles.Add(new RowStyle(SizeType.Absolute, 24));
        root.RowStyles.Add(new RowStyle(SizeType.Absolute, 88));
        root.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
        tab.Controls.Add(root);

        _reportHintLabel.Dock = DockStyle.Fill;
        _reportHintLabel.ForeColor = AppTheme.Text;
        _reportHintLabel.Font = AppTheme.Regular(9.5f);
        _reportHintLabel.Text = _session.IsAdmin
            ? "Администратор видит заказы любого покупателя."
            : "Покупатель видит только свои заказы.";
        root.Controls.Add(_reportHintLabel, 0, 0);

        var filters = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            RowCount = 2,
            ColumnCount = 5,
            BackColor = AppTheme.Background
        };
        filters.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40));
        filters.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 180));
        filters.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 270));
        filters.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 160));
        filters.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 180));
        root.Controls.Add(filters, 0, 1);

        AddFilterLabel(filters, "Покупатель", 0);
        AddFilterLabel(filters, "Дата заказа", 1);
        AddFilterLabel(filters, "Сортировка", 2);

        _reportCustomerCombo.DropDownStyle = ComboBoxStyle.DropDownList;
        _reportCustomerCombo.Dock = DockStyle.Top;
        _reportCustomerCombo.Font = AppTheme.Regular(10f);
        _reportCustomerCombo.Enabled = _session.IsAdmin;
        filters.Controls.Add(_reportCustomerCombo, 0, 1);

        _reportDatePicker.Format = DateTimePickerFormat.Short;
        _reportDatePicker.Dock = DockStyle.Top;
        _reportDatePicker.Font = AppTheme.Regular(10f);
        filters.Controls.Add(_reportDatePicker, 1, 1);

        _reportSortCombo.DropDownStyle = ComboBoxStyle.DropDownList;
        _reportSortCombo.Items.AddRange(new object[] { "По возрастанию количества", "По убыванию количества" });
        _reportSortCombo.SelectedIndex = 0;
        _reportSortCombo.Dock = DockStyle.Top;
        _reportSortCombo.Font = AppTheme.Regular(10f);
        filters.Controls.Add(_reportSortCombo, 2, 1);

        _reportFindButton.Text = "Найти";
        _reportFindButton.Width = 140;
        _reportFindButton.Height = 32;
        _reportFindButton.Margin = new Padding(8, 0, 0, 0);
        AppTheme.StylePrimaryButton(_reportFindButton);
        _reportFindButton.Click += async (_, _) => await LoadReportAsync();
        filters.Controls.Add(_reportFindButton, 3, 1);

        _reportExportButton.Text = "Сохранить отчёт";
        _reportExportButton.Width = 160;
        _reportExportButton.Height = 32;
        _reportExportButton.Margin = new Padding(8, 0, 0, 0);
        _reportExportButton.Enabled = false;
        AppTheme.StyleSecondaryButton(_reportExportButton);
        _reportExportButton.Click += (_, _) => ExportReport();
        filters.Controls.Add(_reportExportButton, 4, 1);

        _reportGrid.Dock = DockStyle.Fill;
        _reportGrid.ReadOnly = true;
        _reportGrid.AllowUserToAddRows = false;
        _reportGrid.AllowUserToDeleteRows = false;
        _reportGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        _reportGrid.MultiSelect = false;
        AppTheme.StyleGrid(_reportGrid);
        root.Controls.Add(_reportGrid, 0, 2);
    }

    private static void AddFilterLabel(TableLayoutPanel filters, string text, int column)
    {
        filters.Controls.Add(new Label
        {
            Text = text,
            Dock = DockStyle.Fill,
            TextAlign = ContentAlignment.BottomLeft,
            ForeColor = AppTheme.Text,
            Font = AppTheme.Regular(10f)
        }, column, 0);
    }

    private static void ConfigureButton(Button button, string text, EventHandler onClick, bool primary = false)
    {
        button.Text = text;
        button.Width = 135;
        button.Height = 36;
        button.Margin = new Padding(0, 5, 10, 5);
        if (primary)
        {
            AppTheme.StylePrimaryButton(button);
        }
        else
        {
            AppTheme.StyleSecondaryButton(button);
        }
        button.Click += onClick;
    }

    private async void MainForm_Load(object? sender, EventArgs e)
    {
        try
        {
            _tableList.DataSource = _tables;
            if (_tables.Count > 0)
            {
                _tableList.SelectedIndex = 0;
            }

            await LoadReportCustomersAsync();
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка запуска", "Не удалось загрузить начальные данные приложения.", ex);
        }
    }

    private async Task LoadCurrentTableAsync()
    {
        TableDefinition? table = CurrentTable;
        if (table == null)
        {
            return;
        }

        SetBusy(true);
        try
        {
            _currentTableLabel.Text = table.DisplayName;
            DataTable data = await _repository.LoadTableAsync(table);
            _dataGrid.DataSource = data;
            ApplyGridSettings(_dataGrid, table.Headers, table.HiddenColumns);
            UpdateActionButtons();
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка загрузки", $"Не удалось загрузить раздел \"{table.DisplayName}\".", ex);
        }
        finally
        {
            SetBusy(false);
        }
    }

    private async Task AddRecordAsync()
    {
        if (!EnsureAdmin()) return;
        TableDefinition? table = CurrentTable;
        if (table == null || table.ReadOnly) return;

        using var form = new EditRecordForm(table, null);
        if (form.ShowDialog(this) != DialogResult.OK)
        {
            return;
        }

        SetBusy(true);
        try
        {
            await _repository.InsertAsync(table, form.Values);
            await LoadCurrentTableAsync();
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка добавления", $"Не удалось добавить запись в раздел \"{table.DisplayName}\".", ex);
        }
        finally
        {
            SetBusy(false);
        }
    }

    private async Task EditRecordAsync()
    {
        if (!EnsureAdmin()) return;
        TableDefinition? table = CurrentTable;
        if (table == null || table.ReadOnly) return;
        DataRowView? row = GetSelectedRow();
        if (table == null || row == null) return;

        using var form = new EditRecordForm(table, row);
        if (form.ShowDialog(this) != DialogResult.OK)
        {
            return;
        }

        SetBusy(true);
        try
        {
            int id = Convert.ToInt32(row[table.IdColumn]);
            await _repository.UpdateAsync(table, id, form.Values);
            await LoadCurrentTableAsync();
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка изменения", $"Не удалось изменить запись в разделе \"{table.DisplayName}\".", ex);
        }
        finally
        {
            SetBusy(false);
        }
    }

    private async Task DeleteRecordAsync()
    {
        if (!EnsureAdmin()) return;
        TableDefinition? table = CurrentTable;
        if (table == null || table.ReadOnly) return;
        DataRowView? row = GetSelectedRow();
        if (table == null || row == null) return;

        if (!ErrorHandler.Confirm("Удалить выбранную запись? Если она связана с другими таблицами, база данных не позволит удалить её."))
        {
            return;
        }

        SetBusy(true);
        try
        {
            int id = Convert.ToInt32(row[table.IdColumn]);
            await _repository.DeleteAsync(table, id);
            await LoadCurrentTableAsync();
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка удаления", $"Не удалось удалить запись из раздела \"{table.DisplayName}\".", ex);
        }
        finally
        {
            SetBusy(false);
        }
    }

    private async Task LoadReportCustomersAsync()
    {
        DataTable customers = await _repository.LoadCustomersForReportAsync(_session);
        var items = customers.Rows.Cast<DataRow>()
            .Where(row => row.Table.Columns.Contains("id") && row["id"] != DBNull.Value)
            .Select(row => new ComboItem
            {
                Id = Convert.ToInt32(row["id"]),
                Text = Convert.ToString(row["text"]) ?? string.Empty
            })
            .ToList();

        _reportCustomerCombo.ValueMember = nameof(ComboItem.Id);
        _reportCustomerCombo.DisplayMember = nameof(ComboItem.Text);
        _reportCustomerCombo.DataSource = items;

        if (items.Count == 0)
        {
            _reportHintLabel.Text = _session.IsAdmin
                ? "В таблице покупателей нет записей. Добавьте покупателя, чтобы искать заказы."
                : "Для этого пользователя не указан покупатель. Проверьте поле customer_id в app_users.";
            _reportGrid.DataSource = new DataTable();
            return;
        }

        _reportCustomerCombo.SelectedIndex = 0;
        await SetLatestReportDateAsync();

        // Отчёт не запускается автоматически при старте, чтобы случайная ошибка
        // в представлении или пустая дата не мешала работать с основными таблицами.
        // Пользователь сам нажимает кнопку "Найти".
    }

    private async Task SetLatestReportDateAsync()
    {
        int? customerId = GetSelectedReportCustomerId(showMessage: false);
        if (!customerId.HasValue)
        {
            return;
        }

        DateTime? latest = await _repository.LoadLatestOrderDateAsync(customerId.Value);
        if (latest.HasValue)
        {
            _reportDatePicker.Value = latest.Value;
        }
    }

    private int? GetSelectedReportCustomerId(bool showMessage)
    {
        if (_reportCustomerCombo.SelectedItem is ComboItem selectedItem && selectedItem.Id.HasValue)
        {
            return selectedItem.Id.Value;
        }

        if (_reportCustomerCombo.SelectedValue is int selectedValue)
        {
            return selectedValue;
        }

        if (_reportCustomerCombo.SelectedValue != null &&
            int.TryParse(Convert.ToString(_reportCustomerCombo.SelectedValue), out int parsedValue))
        {
            return parsedValue;
        }

        if (showMessage)
        {
            MessageBox.Show("Выберите покупателя.", "Поиск заказов", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        return null;
    }

    private async Task LoadReportAsync()
    {
        int? customerId = GetSelectedReportCustomerId(showMessage: true);
        if (!customerId.HasValue)
        {
            return;
        }

        SetBusy(true);
        try
        {
            bool descending = _reportSortCombo.SelectedIndex == 1;
            DataTable data = await _repository.LoadCustomerOrderItemsAsync(_session, customerId.Value, _reportDatePicker.Value.Date, descending);
            _reportGrid.DataSource = data;
            _reportExportButton.Enabled = data.Rows.Count > 0;

            ApplyGridSettings(_reportGrid, new Dictionary<string, string>
            {
                ["order_id"] = "№ заказа",
                ["order_date"] = "Дата заказа",
                ["customer_full_name"] = "Покупатель",
                ["employee_full_name"] = "Сотрудник",
                ["product_name"] = "Товар",
                ["manufacturer"] = "Изготовитель",
                ["quantity"] = "Количество",
                ["unit_price"] = "Цена за единицу",
                ["item_total"] = "Сумма",
                ["status"] = "Статус"
            }, new HashSet<string>());

            if (data.Rows.Count == 0)
            {
                MessageBox.Show("За выбранную дату заказов не найдено.", "Поиск заказов", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка поиска", "Не удалось получить сведения о заказах покупателя за указанную дату.", ex);
        }
        finally
        {
            SetBusy(false);
        }
    }

    private void ExportReport()
    {
        if (_reportGrid.DataSource is not DataTable data || data.Rows.Count == 0)
        {
            MessageBox.Show("Сначала сформируйте отчёт.", "Сохранение отчёта", MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }

        using var dialog = new SaveFileDialog
        {
            Title = "Сохранить отчёт",
            Filter = "CSV-файл (*.csv)|*.csv",
            FileName = $"orders_report_{DateTime.Now:yyyyMMdd_HHmm}.csv"
        };

        if (dialog.ShowDialog(this) != DialogResult.OK)
        {
            return;
        }

        try
        {
            var visibleColumns = _reportGrid.Columns
                .Cast<DataGridViewColumn>()
                .Where(c => c.Visible)
                .OrderBy(c => c.DisplayIndex)
                .ToList();

            var lines = new List<string>();
            lines.Add(string.Join(";", visibleColumns.Select(c => EscapeCsv(c.HeaderText))));

            foreach (DataRow row in data.Rows)
            {
                var values = visibleColumns.Select(c =>
                {
                    object value = row.Table.Columns.Contains(c.Name) ? row[c.Name] : string.Empty;
                    return EscapeCsv(value == DBNull.Value ? string.Empty : Convert.ToString(value) ?? string.Empty);
                });
                lines.Add(string.Join(";", values));
            }

            File.WriteAllLines(dialog.FileName, lines, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true));
            MessageBox.Show("Отчёт сохранён.", "Сохранение отчёта", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        catch (Exception ex)
        {
            ErrorHandler.Show("Ошибка сохранения отчёта", "Не удалось сохранить отчётный CSV-файл.", ex);
        }
    }

    private static string EscapeCsv(string value)
    {
        string escaped = value.Replace("\"", "\"\"");
        return $"\"{escaped}\"";
    }

    private DataRowView? GetSelectedRow()
    {
        if (_dataGrid.CurrentRow?.DataBoundItem is DataRowView row)
        {
            return row;
        }

        MessageBox.Show("Выберите запись в таблице.", "Выбор записи", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return null;
    }

    private bool EnsureAdmin()
    {
        if (_session.IsAdmin)
        {
            return true;
        }

        MessageBox.Show("Изменять данные может только администратор.", "Ограничение доступа", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return false;
    }

    private static void ApplyGridSettings(DataGridView grid, Dictionary<string, string>? headers, HashSet<string>? hiddenColumns)
    {
        if (grid == null || grid.Columns.Count == 0)
        {
            return;
        }

        headers ??= new Dictionary<string, string>();
        hiddenColumns ??= new HashSet<string>();

        grid.AutoGenerateColumns = true;
        grid.AllowUserToAddRows = false;
        grid.AllowUserToDeleteRows = false;
        grid.ReadOnly = true;
        grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
        grid.MultiSelect = false;
        AppTheme.StyleGrid(grid);

        foreach (DataGridViewColumn column in grid.Columns)
        {
            if (column == null)
            {
                continue;
            }

            string columnName = column.Name ?? string.Empty;
            if (headers.TryGetValue(columnName, out string? header) && !string.IsNullOrWhiteSpace(header))
            {
                column.HeaderText = header;
            }

            bool hide = hiddenColumns.Contains(columnName);
            column.Visible = !hide;

            if (!hide)
            {
                string headerText = string.IsNullOrWhiteSpace(column.HeaderText) ? columnName : column.HeaderText;
                column.MinimumWidth = Math.Max(95, headerText.Length * 8);
            }
        }
    }

    private void UpdateActionButtons()
    {
        if (!_session.IsAdmin)
        {
            return;
        }

        bool canEdit = CurrentTable is { ReadOnly: false };
        _addButton.Visible = canEdit;
        _editButton.Visible = canEdit;
        _deleteButton.Visible = canEdit;
    }

    private void SetBusy(bool busy)
    {
        Cursor = busy ? Cursors.WaitCursor : Cursors.Default;
        _refreshButton.Enabled = !busy;
        _tableList.Enabled = !busy;
        _reportFindButton.Enabled = !busy;
        _reportExportButton.Enabled = !busy && _reportGrid.DataSource is DataTable reportData && reportData.Rows.Count > 0;
        _reportCustomerCombo.Enabled = !busy && _session.IsAdmin && _reportCustomerCombo.Items.Count > 0;
        _reportDatePicker.Enabled = !busy;
        _reportSortCombo.Enabled = !busy;
        _logoutButton.Enabled = !busy;

        if (_session.IsAdmin)
        {
            bool canEdit = !busy && CurrentTable is { ReadOnly: false };
            _addButton.Enabled = canEdit;
            _editButton.Enabled = canEdit;
            _deleteButton.Enabled = canEdit;
        }
    }
}
