import { Offcanvas } from 'bootstrap';
import $ from 'jquery';
import 'datatables.net-bs5';

$(function () {
    const $table = $('#admUsersTable');
    if (!$table.length) {
        return;
    }

    const dataUrl = String($table.data('url') ?? '');
    const toggleTemplate = String($table.data('toggle-url-template') ?? '');
    const labelYes = String($table.data('label-yes') ?? 'Yes');
    const labelNo = String($table.data('label-no') ?? 'No');
    const labelEdit = String($table.data('label-edit') ?? 'Edit');
    const labelPassword = String($table.data('label-password') ?? 'Password');
    const labelDelete = String($table.data('label-delete') ?? 'Delete');
    const confirmDelete = String($table.data('confirm-delete') ?? 'Delete?');
    const yesNo = (value: boolean): string => (value ? labelYes : labelNo);

    const $activeFilter = $('#admUsersActiveFilter');
    const $activeFilterLabel = $('#admUsersActiveFilterLabel');
    const $roleFilter = $('#admUsersRoleFilter');
    const editBody = document.getElementById('admUserEditOffcanvasBody');
    const passwordBody = document.getElementById('admUserPasswordOffcanvasBody');
    const editEl = document.getElementById('admUserEditOffcanvas');
    const passwordEl = document.getElementById('admUserPasswordOffcanvas');

    // Body content sits in a z-index:10 stacking context below the admin header (50).
    // Move panels to <body> so they can cover the navigation.
    [editEl, passwordEl].forEach((el) => {
        if (el && el.parentElement !== document.body) {
            document.body.appendChild(el);
        }
    });

    const editOffcanvas = editEl ? Offcanvas.getOrCreateInstance(editEl) : null;
    const passwordOffcanvas = passwordEl ? Offcanvas.getOrCreateInstance(passwordEl) : null;

    const isActiveFilterOn = (): boolean => $activeFilter.is(':checked');

    const updateActiveFilterLabel = (): void => {
        $activeFilterLabel.text(isActiveFilterOn() ? 'Aktive Benutzer' : 'Inaktive Benutzer');
    };
    updateActiveFilterLabel();

    let reloadAfterOffcanvasHide = false;

    const requestTableReload = (): void => {
        table.ajax.reload(undefined, false);
    };

    const loadInto = (url: string, body: HTMLElement | null, panel: Offcanvas | null): void => {
        if (!body || !panel) {
            return;
        }
        body.innerHTML = '<div class="text-muted">…</div>';
        panel.show();
        $.ajax({
            url,
            method: 'GET',
            dataType: 'html',
            cache: false,
        })
            .done((html) => {
                body.innerHTML = html;
            })
            .fail(() => {
                body.innerHTML = '<div class="text-danger">Error</div>';
            });
    };

    const submitOffcanvasForm = (
        form: HTMLFormElement,
        body: HTMLElement | null,
        panel: Offcanvas | null,
    ): void => {
        const action = form.getAttribute('data-action') || form.action;
        const formData = new FormData(form);

        $.ajax({
            url: action,
            method: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            dataType: 'json',
        })
            .done((response) => {
                if (response?.ok) {
                    reloadAfterOffcanvasHide = true;
                    panel?.hide();
                    // Fallback if panel was already hidden / hide event does not fire.
                    window.setTimeout(() => {
                        if (reloadAfterOffcanvasHide) {
                            reloadAfterOffcanvasHide = false;
                            requestTableReload();
                        }
                    }, 400);
                    return;
                }
                if (response?.html && body) {
                    body.innerHTML = response.html;
                }
            })
            .fail((xhr) => {
                const html = xhr.responseJSON?.html;
                if (html && body) {
                    body.innerHTML = html;
                    return;
                }
                alert('Save failed.');
            });
    };

    const table = $table.DataTable({
        initComplete: function () {
            $('input[type="search"]').first().focus();
        },
        stateSave: false,
        autoWidth: false,
        paging: true,
        ordering: true,
        order: [[0, 'asc']],
        serverSide: true,
        ajax: (dtParams: object, callback: (json: object) => void) => {
            const params = dtParams as Record<string, unknown>;
            params.active = isActiveFilterOn() ? '1' : '0';
            params.role = String($roleFilter.val() ?? '');

            $.ajax({
                url: dataUrl,
                method: 'GET',
                data: params,
                dataType: 'json',
                cache: false,
            })
                .done((json) => {
                    const payload = json as {
                        draw?: number;
                        recordsTotal?: number;
                        recordsFiltered?: number;
                        data?: unknown[];
                    };
                    callback({
                        draw: Number(payload.draw ?? params.draw ?? 0),
                        recordsTotal: Number(payload.recordsTotal ?? 0),
                        recordsFiltered: Number(payload.recordsFiltered ?? 0),
                        data: Array.isArray(payload.data) ? payload.data : [],
                    });
                })
                .fail((xhr, textStatus) => {
                    // DataTables aborts the previous request on reload — do not wipe the table.
                    if (textStatus === 'abort') {
                        return;
                    }
                    callback({
                        draw: Number(params.draw ?? 0),
                        recordsTotal: 0,
                        recordsFiltered: 0,
                        data: [],
                    });
                });
        },
        columns: [
            { data: 'email' },
            { data: 'roles' },
            { data: 'firstName' },
            { data: 'lastName' },
            { data: 'cellphone' },
            { data: 'company' },
            {
                data: 'isMainAccount',
                render: (data: boolean) => yesNo(!!data),
            },
            {
                data: 'isVerified',
                render: (data: boolean) => yesNo(!!data),
            },
            {
                data: 'isUser',
                render: (data: boolean) => yesNo(!!data),
            },
            { data: 'validUntil' },
            {
                data: 'isActive',
                orderable: true,
                searchable: false,
                render: (data: boolean, _type: string, row: { id: number; toggleToken: string }) => {
                    const checked = data ? 'checked' : '';
                    return `
                        <div class="form-check form-switch m-0">
                            <input class="form-check-input adm-user-active-switch"
                                   type="checkbox"
                                   role="switch"
                                   data-id="${row.id}"
                                   data-token="${row.toggleToken}"
                                   ${checked}>
                        </div>
                    `;
                },
            },
            {
                data: 'passwordUrl',
                orderable: false,
                searchable: false,
                render: (url: string) =>
                    `<button type="button" class="button button-blue btn-sm adm-user-password-btn"
                             data-url="${url}" title="${labelPassword}">
                        <i class="icofont-key"></i>
                     </button>`,
            },
            {
                data: 'editUrl',
                orderable: false,
                searchable: false,
                render: (url: string) =>
                    `<button type="button" class="button button-blue btn-sm adm-user-edit-btn"
                             data-url="${url}" title="${labelEdit}">
                        <i class="icofont-edit"></i>
                     </button>`,
            },
            {
                data: null,
                orderable: false,
                searchable: false,
                render: (_data: unknown, _type: string, row: { deleteUrl: string; deleteToken: string }) => `
                    <form method="post" action="${row.deleteUrl}" class="d-inline"
                          onsubmit="return confirm('${confirmDelete.replace(/'/g, "\\'")}');">
                        <input type="hidden" name="_token" value="${row.deleteToken}">
                        <button type="submit" class="button button-delete btn-sm" title="${labelDelete}">
                            <i class="icofont-trash"></i>
                        </button>
                    </form>
                `,
            },
        ],
    });

    const onOffcanvasHidden = (): void => {
        if (!reloadAfterOffcanvasHide) {
            return;
        }
        reloadAfterOffcanvasHide = false;
        requestTableReload();
    };
    editEl?.addEventListener('hidden.bs.offcanvas', onOffcanvasHidden);
    passwordEl?.addEventListener('hidden.bs.offcanvas', onOffcanvasHidden);

    $activeFilter.on('change', () => {
        updateActiveFilterLabel();
        requestTableReload();
    });

    $roleFilter.on('change', () => {
        requestTableReload();
    });

    $table.on('change', '.adm-user-active-switch', function () {
        const $input = $(this);
        const id = $input.data('id');
        const token = String($input.data('token') ?? '');
        const url = toggleTemplate.replace('__ID__', String(id));

        $.ajax({
            url,
            method: 'POST',
            data: { _token: token },
        })
            .done((response) => {
                if (!response?.ok) {
                    $input.prop('checked', !$input.prop('checked'));
                    return;
                }
                requestTableReload();
            })
            .fail(() => {
                $input.prop('checked', !$input.prop('checked'));
                alert('Status konnte nicht geändert werden.');
            });
    });

    $table.on('click', '.adm-user-edit-btn', function () {
        const url = String($(this).data('url') ?? '');
        loadInto(url, editBody, editOffcanvas);
    });

    $table.on('click', '.adm-user-password-btn', function () {
        const url = String($(this).data('url') ?? '');
        loadInto(url, passwordBody, passwordOffcanvas);
    });

    $(document).on('submit', '#admUserEditForm', function (event) {
        event.preventDefault();
        submitOffcanvasForm(this as HTMLFormElement, editBody, editOffcanvas);
    });

    $(document).on('submit', '#admUserPasswordForm', function (event) {
        event.preventDefault();
        submitOffcanvasForm(this as HTMLFormElement, passwordBody, passwordOffcanvas);
    });

    $(document).on('click', '.adm-password-toggle-btn', function () {
        const $btn = $(this);
        const $input = $btn.closest('.adm-password-toggle').find('input').first();
        const $icon = $btn.find('i').first();
        const show = $input.attr('type') === 'password';

        $input.attr('type', show ? 'text' : 'password');
        $icon.toggleClass('fa-eye', !show);
        $icon.toggleClass('fa-eye-slash', show);
    });
});
