using VoiceCat.Interop;

namespace VoiceCat.App.Forms;

/// <summary>
/// Admin account management: list, create, reset password, and delete server accounts.
/// </summary>
public sealed class AccountsDialog : Form
{
    private readonly VoiceCatClient _client;
    private readonly ListView _lvAccounts;
    private readonly Button _btnRefresh;
    private readonly Button _btnAdd;
    private readonly Button _btnResetPassword;
    private readonly Button _btnDelete;

    public AccountsDialog(VoiceCatClient client)
    {
        _client = client;

        Text = "Server accounts";
        FormBorderStyle = FormBorderStyle.Sizable;
        StartPosition = FormStartPosition.CenterParent;
        AutoScaleMode = AutoScaleMode.Font;
        ClientSize = new Size(560, 360);
        MinimumSize = new Size(420, 260);

        _lvAccounts = new ListView
        {
            View = View.Details,
            FullRowSelect = true,
            GridLines = true,
            Dock = DockStyle.Fill,
            TabIndex = 0,
        };
        _lvAccounts.Columns.Add("Username", 160);
        _lvAccounts.Columns.Add("Admin", 50);
        _lvAccounts.Columns.Add("Created", 130);
        _lvAccounts.Columns.Add("Last login", 130);
        _lvAccounts.SelectedIndexChanged += (_, _) => UpdateButtons();

        var pnlButtons = new Panel
        {
            Dock = DockStyle.Bottom,
            Height = 44,
        };

        _btnRefresh = new Button
        {
            Text = "&Refresh",
            Location = new Point(12, 9),
            Size = new Size(75, 27),
            TabIndex = 1,
        };
        _btnRefresh.Click += (_, _) => RefreshList();

        _btnAdd = new Button
        {
            Text = "&Add...",
            Location = new Point(100, 9),
            Size = new Size(75, 27),
            TabIndex = 2,
        };
        _btnAdd.Click += (_, _) => AddAccount();

        _btnResetPassword = new Button
        {
            Text = "&Reset password...",
            Location = new Point(188, 9),
            Size = new Size(120, 27),
            TabIndex = 3,
            Enabled = false,
        };
        _btnResetPassword.Click += (_, _) => ResetPassword();

        _btnDelete = new Button
        {
            Text = "&Delete",
            Location = new Point(320, 9),
            Size = new Size(75, 27),
            TabIndex = 4,
            Enabled = false,
        };
        _btnDelete.Click += (_, _) => DeleteAccount();

        pnlButtons.Controls.AddRange([_btnRefresh, _btnAdd, _btnResetPassword, _btnDelete]);

        Controls.Add(_lvAccounts);
        Controls.Add(pnlButtons);

        Load += (_, _) => RefreshList();
    }

    private void UpdateButtons()
    {
        bool selected = _lvAccounts.SelectedItems.Count > 0;
        _btnResetPassword.Enabled = selected;
        _btnDelete.Enabled = selected;
    }

    private void RefreshList()
    {
        _client.RequestAccountList();
        // The event will come back asynchronously; poll briefly for the list.
        var deadline = DateTime.UtcNow.AddSeconds(2);
        List<AccountInfo>? accounts = null;
        while (DateTime.UtcNow < deadline)
        {
            _client.PumpEvents();
            accounts = _client.ListAccounts();
            if (accounts.Count > 0) break;
            Thread.Sleep(30);
        }
        accounts ??= _client.ListAccounts();

        _lvAccounts.BeginUpdate();
        _lvAccounts.Items.Clear();
        foreach (var a in accounts.OrderBy(a => a.Username))
        {
            var item = new ListViewItem(a.Username);
            item.SubItems.Add(a.IsAdmin ? "Yes" : "No");
            item.SubItems.Add(FormatDate(a.CreatedAtUnixMs));
            item.SubItems.Add(FormatDate(a.LastLoginUnixMs));
            _lvAccounts.Items.Add(item);
        }
        _lvAccounts.EndUpdate();
        UpdateButtons();
    }

    private static string FormatDate(ulong ms)
    {
        if (ms == 0) return "—";
        try
        {
            return DateTimeOffset.FromUnixTimeMilliseconds((long)ms).LocalDateTime.ToString("g");
        }
        catch
        {
            return "—";
        }
    }

    private void AddAccount()
    {
        using var userDlg = new InputDialog("Add account", "&Username:");
        if (userDlg.ShowDialog(this) != DialogResult.OK || string.IsNullOrWhiteSpace(userDlg.TextValue))
            return;

        using var pwDlg = new PasswordPromptDialog($"Password for {userDlg.TextValue}:");
        if (pwDlg.ShowDialog(this) != DialogResult.OK || string.IsNullOrEmpty(pwDlg.Password))
            return;

        var r = _client.CreateAccount(userDlg.TextValue, pwDlg.Password);
        if (r != VcResult.Ok)
        {
            MessageBox.Show(this, $"Create account failed: {r}", "VoiceCat",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }
        RefreshList();
    }

    private void ResetPassword()
    {
        if (_lvAccounts.SelectedItems.Count == 0) return;
        string username = _lvAccounts.SelectedItems[0].Text;

        using var dlg = new PasswordPromptDialog($"New password for {username}:");
        if (dlg.ShowDialog(this) != DialogResult.OK || string.IsNullOrEmpty(dlg.Password))
            return;

        var r = _client.ResetPassword(username, dlg.Password);
        if (r != VcResult.Ok)
        {
            MessageBox.Show(this, $"Reset password failed: {r}", "VoiceCat",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }
        RefreshList();
    }

    private void DeleteAccount()
    {
        if (_lvAccounts.SelectedItems.Count == 0) return;
        string username = _lvAccounts.SelectedItems[0].Text;

        var confirm = MessageBox.Show(this, $"Delete account '{username}'?",
            "VoiceCat", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        if (confirm != DialogResult.Yes) return;

        var r = _client.DeleteAccount(username);
        if (r != VcResult.Ok)
        {
            MessageBox.Show(this, $"Delete account failed: {r}", "VoiceCat",
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }
        RefreshList();
    }
}
