import { FormCheckbox } from '@admin/components/ui/forms/form-checkbox';
import { FormSection } from '@admin/components/ui/forms/form-section';
import { formHelpClassName } from '@admin/components/ui/field-styles';
import { formatPermissionName } from '@admin/lib/format-permission-name';
import { cn } from '@admin/lib/utils';

export type PermissionModule = {
    key: string;
    label: string;
    permissions: string[];
};

export type PermissionSectionGroup = 'general' | 'granular' | 'custom';

export type PermissionSection = {
    key: string;
    label: string;
    description?: string | null;
    summary_permission?: string | null;
    modules: PermissionModule[];
    permissions: string[];
    is_custom?: boolean;
    is_granular?: boolean;
    group?: PermissionSectionGroup;
};

type PermissionMatrixProps = {
    sections: PermissionSection[];
    selected: string[];
    onChange: (permissions: string[]) => void;
    disabled?: boolean;
};

const GROUP_LABELS: Record<PermissionSectionGroup, string> = {
    general: 'General access',
    granular: 'Granular permissions',
    custom: 'Custom permission groups',
};

function togglePermission(selected: string[], permission: string, checked: boolean): string[] {
    if (checked) {
        return selected.includes(permission) ? selected : [...selected, permission];
    }

    return selected.filter((value) => value !== permission);
}

function toggleMany(selected: string[], permissions: string[], checked: boolean): string[] {
    if (checked) {
        return [...new Set([...selected, ...permissions])];
    }

    return selected.filter((permission) => !permissions.includes(permission));
}

function sectionSelectionCount(section: PermissionSection, selected: string[]): number {
    return section.permissions.filter((permission) => selected.includes(permission)).length;
}

function moduleSelectionCount(module: PermissionModule, selected: string[]): number {
    return module.permissions.filter((permission) => selected.includes(permission)).length;
}

function sectionTitle(section: PermissionSection): string {
    if (section.is_custom) {
        return section.label;
    }

    return section.label;
}

function renderPermissionGrid(
    section: PermissionSection,
    permissions: string[],
    selected: string[],
    onChange: (permissions: string[]) => void,
    disabled: boolean,
) {
    return (
        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3">
            {permissions.map((permission) => (
                <FormCheckbox
                    key={permission}
                    id={`permission-${section.key}-${permission}`}
                    label={formatPermissionName(permission)}
                    checked={selected.includes(permission)}
                    disabled={disabled}
                    onChange={(event) => onChange(togglePermission(selected, permission, event.target.checked))}
                />
            ))}
        </div>
    );
}

export function PermissionMatrix({ sections, selected, onChange, disabled = false }: PermissionMatrixProps) {
    let previousGroup: PermissionSectionGroup | undefined;

    return (
        <div className="permission-matrix admin-no-translate notranslate space-y-4" translate="no">
            {sections.map((section) => {
                const sectionSelectedCount = sectionSelectionCount(section, selected);
                const allSectionSelected = sectionSelectedCount === section.permissions.length;
                const someSectionSelected = sectionSelectedCount > 0 && !allSectionSelected;
                const summaryChecked = section.summary_permission
                    ? selected.includes(section.summary_permission)
                    : allSectionSelected;
                const showGroupHeading = section.group !== undefined && section.group !== previousGroup;
                if (section.group !== undefined) {
                    previousGroup = section.group;
                }

                return (
                    <div key={section.key}>
                        {showGroupHeading && (
                            <div className="mb-4 mt-2">
                                <h4 className="text-base font-semibold text-gray-800 dark:text-white">
                                    {GROUP_LABELS[section.group!]}
                                </h4>
                                {section.group === 'granular' && (
                                    <p className={cn('mt-1 mb-0', formHelpClassName)}>
                                        Assign individual module permissions without using general access shortcuts.
                                    </p>
                                )}
                            </div>
                        )}

                        <FormSection
                            title={section.is_custom ? `Custom group: ${sectionTitle(section)}` : sectionTitle(section)}
                            action={
                                !disabled ? (
                                    <button
                                        type="button"
                                        className="ti-btn ti-btn-sm ti-btn-soft-primary"
                                        onClick={() => onChange(toggleMany(selected, section.permissions, !allSectionSelected))}
                                    >
                                        {allSectionSelected ? 'Clear section' : 'Select section'}
                                    </button>
                                ) : undefined
                            }
                        >
                            {section.description && <p className={cn('mb-4', formHelpClassName)}>{section.description}</p>}

                            {section.summary_permission && (
                                <div className="mb-4 rounded-sm border border-gray-200 p-4 dark:border-white/10">
                                    <FormCheckbox
                                        id={`summary-${section.key}`}
                                        label={formatPermissionName(section.summary_permission)}
                                        checked={summaryChecked}
                                        disabled={disabled}
                                        onChange={(event) =>
                                            onChange(toggleMany(selected, section.permissions, event.target.checked))
                                        }
                                    />
                                    <p className={cn('mt-2 ms-6', formHelpClassName)}>
                                        General access shortcut for this section. You can also grant individual permissions below.
                                    </p>
                                </div>
                            )}

                            <p className={cn('mb-4', formHelpClassName)}>
                                {someSectionSelected
                                    ? `${sectionSelectedCount} of ${section.permissions.length} selected in this section`
                                    : `${section.permissions.length} permissions in this section`}
                            </p>

                            {section.is_granular ? (
                                renderPermissionGrid(section, section.permissions, selected, onChange, disabled)
                            ) : (
                                <div className="space-y-5">
                                    {section.modules.map((module) => {
                                        const moduleSelectedCount = moduleSelectionCount(module, selected);
                                        const allModuleSelected = moduleSelectedCount === module.permissions.length;

                                        return (
                                            <div key={`${section.key}-${module.key}`}>
                                                <div className="mb-3 flex flex-wrap items-center justify-between gap-2">
                                                    <h6 className="text-sm font-semibold text-gray-700 dark:text-white">
                                                        {module.label}
                                                    </h6>
                                                    {!disabled && (
                                                        <button
                                                            type="button"
                                                            className="ti-btn ti-btn-sm ti-btn-soft-secondary"
                                                            onClick={() =>
                                                                onChange(
                                                                    toggleMany(
                                                                        selected,
                                                                        module.permissions,
                                                                        !allModuleSelected,
                                                                    ),
                                                                )
                                                            }
                                                        >
                                                            {allModuleSelected ? 'Clear module' : 'Select module'}
                                                        </button>
                                                    )}
                                                </div>
                                                {renderPermissionGrid(section, module.permissions, selected, onChange, disabled)}
                                            </div>
                                        );
                                    })}
                                </div>
                            )}
                        </FormSection>
                    </div>
                );
            })}
        </div>
    );
}
