import React, {useCallback, useEffect, useRef, useState} from 'react';
import {usePage} from '@inertiajs/react';
import axios from 'axios';
import toast from 'react-hot-toast';

interface Role {
    id: number;
    name: string;
    permissions: string[];
}

function groupPermissions(perms: string[]): Record<string, string[]> {
    const groups: Record<string, string[]> = {};
    for (const perm of perms) {
        const group = perm.split('_')[0];
        if (!groups[group]) groups[group] = [];
        groups[group].push(perm);
    }
    return groups;
}

function IndeterminateCheckbox({
                                   checked,
                                   indeterminate,
                                   onChange,
                                   className,
                               }: {
    checked: boolean;
    indeterminate: boolean;
    onChange: () => void;
    className?: string;
}) {
    const ref = useRef<HTMLInputElement>(null);
    useEffect(() => {
        if (ref.current) ref.current.indeterminate = indeterminate;
    }, [indeterminate]);
    return (
        <input ref={ref} type="checkbox" checked={checked} onChange={onChange} className={className}/>
    );
}

export default function RolesAndPermissions() {
    const {auth} = usePage<{ auth: { user: { api_token: string } } }>().props;
    const token = auth?.user?.api_token;
    const authHeaders = {headers: {Authorization: `Bearer ${token}`}};

    const [roles, setRoles] = useState<Role[]>([]);
    const [allPermissions, setAllPermissions] = useState<string[]>([]);
    const [selectedRole, setSelectedRole] = useState<Role | null>(null);
    const [loading, setLoading] = useState(false);

    // Modal state
    let [editingRole, setEditingRole] = useState<Role | null>(null);
    const [roleName, setRoleName] = useState('');
    const [draftPermissions, setDraftPermissions] = useState<string[]>([]);
    const [saving, setSaving] = useState(false);

    const fetchData = useCallback(async () => {
        setLoading(true);
        try {
            const [rolesRes, permsRes] = await Promise.all([
                axios.get('/api/roles', authHeaders),
                axios.get('/api/permissions', authHeaders),
            ]);
            const rolesData: Role[] = rolesRes.data.result;
            setRoles(rolesData);
            setAllPermissions(permsRes.data.result);
            if (rolesData.length > 0) setSelectedRole(rolesData[0]);
        } catch {
            toast.error('Failed to load roles and permissions');
        } finally {
            setLoading(false);
        }
    }, []);

    useEffect(() => {
        fetchData();
    }, [fetchData]);

    const closeModal = () =>
        (document.querySelector('[data-hs-overlay="#modal"]') as HTMLElement | null)?.click();

    const openCreateModal = () => {
        setEditingRole(null);
        setRoleName('');
        setDraftPermissions([]);
    };

    const openEditModal = (role: Role) => {
        setEditingRole(role);
        setRoleName(role.name);
        setDraftPermissions([...role.permissions]);
    };

    const togglePermission = (perm: string) =>
        setDraftPermissions(prev =>
            prev.includes(perm) ? prev.filter(p => p !== perm) : [...prev, perm],
        );

    const toggleGroup = (groupPerms: string[]) => {
        const allChecked = groupPerms.every(p => draftPermissions.includes(p));
        if (allChecked) {
            setDraftPermissions(prev => prev.filter(p => !groupPerms.includes(p)));
        } else {
            setDraftPermissions(prev => [...new Set([...prev, ...groupPerms])]);
        }
    };

    const saveRole = async () => {
        if (!roleName.trim()) {
            toast.error('Role name is required');
            return;
        }
        setSaving(true);
        try {
            if (editingRole) {
                const {data} = await axios.put(
                    `/api/roles/${editingRole.id}`,
                    {name: roleName, permissions: draftPermissions},
                    authHeaders,
                );
                const updated: Role = data.result;
                setRoles(prev => prev.map(r => (r.id === editingRole.id ? updated : r)));
                setSelectedRole(prev => (prev?.id === editingRole.id ? updated : prev));
                toast.success('Role updated successfully');
            } else {
                const {data} = await axios.post(
                    '/api/roles',
                    {name: roleName, permissions: draftPermissions},
                    authHeaders,
                );
                const created: Role = data.result;
                setRoles(prev => [...prev, created]);
                setSelectedRole(created);
                toast.success('Role created successfully');
            }
            closeModal();
        } catch (e: any) {
            const msg = e.response?.data?.errors
                ? Object.values<string[]>(e.response.data.errors).flat().join(' ')
                : e.response?.data?.message ?? 'Failed to save role';
            toast.error(msg);
        } finally {
            setSaving(false);
        }
    };

    const deleteRole = async (role: Role) => {
        if (!confirm(`Delete role "${role.name}"? This cannot be undone.`)) return;
        try {
            await axios.delete(`/api/roles/${role.id}`, authHeaders);
            const remaining = roles.filter(r => r.id !== role.id);
            setRoles(remaining);
            setSelectedRole(selectedRole?.id === role.id ? (remaining[0] ?? null) : selectedRole);
            toast.success('Role deleted');
        } catch {
            toast.error('Failed to delete role');
        }
    };

    const permissionGroups = groupPermissions(allPermissions);

    return (
        <div className="bg-white rounded-lg shadow">
            <div className="p-6">
                {/* Header */}
                <div className="flex justify-between items-center mb-5">
                    <div>
                        <h2 className="text-lg font-semibold text-gray-800">Roles &amp; Permissions</h2>
                        <p className="text-sm text-gray-500 mt-0.5">
                            Manage system roles and their associated permissions.
                        </p>
                    </div>
                    <div className="flex justify-end">
                        <button
                            type="button"
                            data-hs-overlay="#modal"
                            onClick={() => selectedRole && openEditModal(selectedRole)}
                            disabled={!selectedRole}
                            className="ti-btn ti-btn-danger py-2 px-3 whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed"
                        >
                            <i className="ri ri-edit-line mr-2"></i> Edit Permissions
                        </button>
                        <button
                            type="button"
                            data-hs-overlay="#modal"
                            onClick={openCreateModal}
                            className="ti-btn ti-btn-primary py-2 px-3 whitespace-nowrap"
                        >
                            <i className="ri ri-edit-line mr-2"></i> New Role
                        </button>
                    </div>

                </div>

                {loading ? (
                    <div className="flex justify-center items-center py-16">
                        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600"></div>
                    </div>
                ) : (
                    <div className="grid grid-cols-12 gap-4">
                        {/* Roles list */}
                        <div className="col-span-3">
                            <div className="border border-gray-200 rounded-lg overflow-hidden">
                                <div className="bg-gray-50 px-3 py-2 border-b border-gray-200">
                                    <span className="text-xs font-semibold text-gray-500 uppercase tracking-wide">
                                        Roles ({roles.length})
                                    </span>
                                </div>
                                <ul className="divide-y divide-gray-100">
                                    {roles.map(role => (
                                        <li
                                            key={role.id}
                                            onClick={() => setSelectedRole(role)}
                                            className={`px-3 py-2.5 cursor-pointer flex justify-between items-center group hover:bg-gray-50 transition-colors ${
                                                selectedRole?.id === role.id
                                                    ? 'bg-indigo-50 border-l-2 border-indigo-500'
                                                    : ''
                                            }`}
                                        >
                                            <div className="min-w-0">
                                                <p className={`text-sm font-medium truncate ${selectedRole?.id === role.id ? 'text-indigo-700' : 'text-gray-700'}`}>
                                                    {role.name}
                                                </p>
                                                <p className="text-xs text-gray-400">
                                                    {role.permissions.length} permission{role.permissions.length !== 1 ? 's' : ''}
                                                </p>
                                            </div>
                                            <div className="flex gap-1 flex-shrink-0 ml-1">
                                                <button
                                                    onClick={e => {
                                                        e.stopPropagation();
                                                        deleteRole(role);
                                                    }}
                                                    className="p-1.5 text-red-400 hover:text-white hover:bg-red-500 rounded transition-colors"
                                                    title="Delete role"
                                                >
                                                    <i className="ri ri-delete-bin-line text-sm"></i>
                                                </button>
                                            </div>
                                        </li>
                                    ))}
                                    {roles.length === 0 && (
                                        <li className="px-3 py-8 text-center text-sm text-gray-400">
                                            No roles found. Create one to get started.
                                        </li>
                                    )}
                                </ul>
                            </div>
                        </div>

                        {/* Permissions panel */}
                        <div className="col-span-9">
                            {selectedRole ? (
                                <div className="border border-gray-200 rounded-lg overflow-hidden">
                                    <div
                                        className="bg-gray-50 px-4 py-2.5 border-b border-gray-200 flex justify-between items-center">
                                        <div className="flex items-center gap-2">
                                            <span
                                                className="text-xs font-semibold text-gray-500 uppercase tracking-wide">Permissions</span>
                                            <span
                                                className="text-xs font-medium text-indigo-600 bg-indigo-50 px-2 py-0.5 rounded-full">
                                                {selectedRole.name}
                                            </span>
                                        </div>
                                        <span className="text-xs text-gray-400">
                                            {selectedRole.permissions.length} of {allPermissions.length} assigned
                                        </span>
                                    </div>
                                    <div className="p-4 grid grid-cols-2 gap-3 max-h-[560px] overflow-y-auto">
                                        {Object.entries(permissionGroups).map(([group, groupPerms]) => {
                                            const assignedCount = groupPerms.filter(p => selectedRole.permissions.includes(p)).length;
                                            return (
                                                <div key={group}
                                                     className="border border-gray-100 rounded-lg overflow-hidden">
                                                    <div
                                                        className="bg-gray-50 px-3 py-1.5 flex items-center justify-between border-b border-gray-100">
                                                        <span
                                                            className="text-xs font-semibold text-gray-700 capitalize">{group}</span>
                                                        <span
                                                            className={`text-xs px-1.5 py-0.5 rounded-full font-medium ${
                                                                assignedCount === groupPerms.length
                                                                    ? 'bg-green-100 text-green-700'
                                                                    : assignedCount > 0
                                                                        ? 'bg-yellow-100 text-yellow-700'
                                                                        : 'bg-gray-100 text-gray-500'
                                                            }`}>
                                                            {assignedCount}/{groupPerms.length}
                                                        </span>
                                                    </div>
                                                    <div className="px-3 py-2 space-y-1">
                                                        {groupPerms.map(perm => (
                                                            <div key={perm} className="flex items-center gap-2">
                                                                <span
                                                                    className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${
                                                                        selectedRole.permissions.includes(perm) ? 'bg-green-500' : 'bg-gray-300'
                                                                    }`}/>
                                                                <span
                                                                    className="text-xs text-gray-600 truncate">{perm}</span>
                                                            </div>
                                                        ))}
                                                    </div>
                                                </div>
                                            );
                                        })}
                                    </div>
                                </div>
                            ) : (
                                <div
                                    className="border border-dashed border-gray-200 rounded-lg flex flex-col items-center justify-center h-48 text-gray-400">
                                    <i className="fas fa-shield-alt text-3xl mb-2 opacity-30"></i>
                                    <p className="text-sm">Select a role to view its permissions</p>
                                </div>
                            )}
                        </div>
                    </div>
                )}
            </div>

            <div id="modal" className="hs-overlay hidden ti-modal">
                <div className="hs-overlay-open:mt-7 ti-modal-box mt-0 ease-out">
                    <div className="ti-modal-content">
                        {/* Modal header */}
                        <div className="ti-modal-header">
                            <h3 className="ti-modal-title">{editingRole ? `Edit Role: ${editingRole.name}` : 'Create New Role'}</h3>
                            <button
                                type="button"
                                className="hs-dropdown-toggle ti-modal-close-btn"
                                data-hs-overlay="#modal"
                            >
                                <span className="sr-only">Close</span>
                                <i className="ri-close-line"/>
                            </button>
                        </div>


                        {/* Modal body */}
                        <div className="ti-modal-body">
                            {/* Role name */}
                            <div>
                                <label className="block text-sm font-medium text-gray-700 mb-1">
                                    Role Name <span className="text-red-500">*</span>
                                </label>
                                <input
                                    type="text"
                                    value={roleName}
                                    onChange={e => setRoleName(e.target.value.toUpperCase())}
                                    placeholder="e.g. MANAGER"
                                    className="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent uppercase"
                                />
                                <p className="text-xs text-gray-400 mt-1">Role names are automatically
                                    uppercased.</p>
                            </div>

                            {/* Permissions */}
                            <div>
                                <div className="flex justify-between items-center mb-2">
                                    <label className="block text-sm font-medium text-gray-700">Permissions</label>
                                    <div className="flex gap-3 text-xs">
                                        <button type="button"
                                                onClick={() => setDraftPermissions([...allPermissions])}
                                                className="text-indigo-600 hover:underline">
                                            Select all
                                        </button>
                                        <button type="button" onClick={() => setDraftPermissions([])}
                                                className="text-gray-400 hover:underline">
                                            Clear all
                                        </button>
                                        <span
                                            className="text-gray-400">{draftPermissions.length}/{allPermissions.length} selected</span>
                                    </div>
                                </div>

                                <div className="space-y-2">
                                    {Object.entries(permissionGroups).map(([group, groupPerms]) => {
                                        const allChecked = groupPerms.every(p => draftPermissions.includes(p));
                                        const someChecked = groupPerms.some(p => draftPermissions.includes(p));
                                        return (
                                            <div key={group}
                                                 className="border border-gray-200 rounded-lg overflow-hidden">
                                                <label
                                                    className="flex items-center gap-2.5 px-3 py-2 bg-gray-50 border-b border-gray-100 cursor-pointer hover:bg-gray-100 transition-colors">
                                                    <IndeterminateCheckbox
                                                        checked={allChecked}
                                                        indeterminate={someChecked && !allChecked}
                                                        onChange={() => toggleGroup(groupPerms)}
                                                        className="rounded text-indigo-600 cursor-pointer"
                                                    />
                                                    <span
                                                        className="text-sm font-semibold text-gray-700 capitalize flex-1">{group}</span>
                                                    <span className="text-xs text-gray-400">
                                                        {groupPerms.filter(p => draftPermissions.includes(p)).length}/{groupPerms.length}
                                                    </span>
                                                </label>
                                                <div className="px-3 py-2 grid grid-cols-2 gap-x-4 gap-y-1">
                                                    {groupPerms.map(perm => (
                                                        <label key={perm}
                                                               className="flex items-center gap-2 cursor-pointer py-0.5 group/perm">
                                                            <input
                                                                type="checkbox"
                                                                checked={draftPermissions.includes(perm)}
                                                                onChange={() => togglePermission(perm)}
                                                                className="rounded text-indigo-600 cursor-pointer"
                                                            />
                                                            <span
                                                                className="text-xs text-gray-600 group-hover/perm:text-gray-900 transition-colors">{perm}</span>
                                                        </label>
                                                    ))}
                                                </div>
                                            </div>
                                        );
                                    })}
                                </div>
                            </div>
                        </div>

                        {/* Modal footer */}
                        <div className="ti-modal-footer">
                            <button
                                type="button"
                                data-hs-overlay="#modal"
                                className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded-lg hover:bg-white transition-colors"
                            >
                                Cancel
                            </button>
                            <button
                                onClick={saveRole}
                                disabled={saving}
                                className="px-4 py-2 text-sm bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-60 transition-colors font-medium"
                            >
                                {saving ? (
                                    <span className="flex items-center gap-1.5">
                                        <span
                                            className="animate-spin h-3 w-3 border-2 border-white border-t-transparent rounded-full inline-block"></span>
                                        Saving…
                                    </span>
                                ) : editingRole ? 'Save Changes' : 'Create Role'}
                            </button>
                        </div>
                    </div>
                </div>
            </div>

        </div>
    );
}

