import Form from '@admin/components/form/Form';
import { Button } from '@admin/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@admin/components/ui/card';
import { Checkbox } from '@admin/components/ui/checkbox';
import { Input } from '@admin/components/ui/input';
import { Label } from '@admin/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@admin/components/ui/radio-group';
import { yupResolver } from '@hookform/resolvers/yup';
import { usePage } from '@inertiajs/react';
import { Plus } from 'lucide-react';
import { useMemo } from 'react';
import { useFormContext } from 'react-hook-form';
import * as yup from 'yup';

type ScopeType = 'global' | 'local' | 'branch' | 'country';

// Validation schema
const roleSchema = yup.object({
    name: yup.string().required('Role name is required').trim(),
    permissions: yup.array().min(1, 'Please select at least one permission').required('Please select at least one permission'),
});

interface RoleFormWithHookFormProps {
    modulePermissions?: any;
    initialData?: any;
    onSubmit: (data: any) => void;
    submitButtonText: string;
    isEdit?: boolean;
    isView?: boolean;
}

// Form fields component that uses React Hook Form context
function RoleFormFields({ modulePermissions, isEdit = false, isView = false }: { modulePermissions?: any; isEdit?: boolean; isView?: boolean }) {
    const { permissions } = usePage<any>().props;
    const {
        watch,
        setValue,
        formState: { errors },
    } = useFormContext();
    
    const formData = watch();

    // Use permissions from props (grouped by module/category)
    const groupedPermissions = permissions || {};
    const allPermissions = Object.values(groupedPermissions).flatMap((group: any) => 
        Array.isArray(group) ? group.map((p: any) => p.slug) : []
    );

    // For backward compatibility, also support modulePermissions structure
    const allModules = modulePermissions?.platform || {};
    const modulePermissions_allPermissions = Object.values(allModules).flatMap((permsObj: any) => Object.values(permsObj)) as string[];
    
    // Merge both permission sources
    const finalAllPermissions = [...allPermissions, ...modulePermissions_allPermissions];
    
    const moduleCategories = {
        platform: Object.keys(allModules),
    };

    // Function to get permissions for a module based on current tab
    const getModulePermissions = (module: string, category: string) => {
        if (category === 'platform') {
            return allModules[module] || {};
        }
        return {};
    };

    // Generate slug from name
    const generateSlug = (name: string) => {
        return name
            .toLowerCase()
            .trim()
            .replace(/[^a-z0-9\s-]/g, '') // Remove special characters
            .replace(/\s+/g, '-') // Replace spaces with hyphens
            .replace(/-+/g, '-') // Replace multiple hyphens with single hyphen
            .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
    };

    // Auto-generate slug when name changes (only for create mode)
    const roleSlug = useMemo(() => {
        return isEdit ? formData.slug : generateSlug(formData.name || '');
    }, [formData.name, formData.slug, isEdit]);

    // Toggle individual permission
    const togglePermission = (slug: string, checked: boolean) => {
        const currentPermissions = formData.permissions || [];
        const newPermissions = checked ? [...currentPermissions, slug] : currentPermissions.filter((p: string) => p !== slug);
        setValue('permissions', newPermissions);

        // Find which module this permission belongs to across all categories
        const findModuleForPermission = () => {
            // search platform
            const platformMatch = Object.keys(allModules).find((module) => Object.values(allModules[module]).includes(slug));
            if (platformMatch) return platformMatch;
            // search other categories
            for (const cat of Object.keys(modulePermissions || {})) {
                const catModules = modulePermissions[cat] || {};
                const match = Object.keys(catModules).find((module) => Object.values(catModules[module]).includes(slug));
                if (match) return match;
            }
            return undefined;
        };

        const moduleForThisPermission = findModuleForPermission();

        if (moduleForThisPermission) {
            const currentScopes = formData.moduleScopes || {};

            if (checked) {
                // Set default scope to 'global' when permission is first selected
                if (!currentScopes[moduleForThisPermission]) {
                    setValue('moduleScopes', {
                        ...currentScopes,
                        [moduleForThisPermission]: { scope: 'global', is_show: 1 },
                    });
                }
            } else {
                // Check if module still has any permissions selected
                const modulePerms = Object.values(
                    getModulePermissions(
                        moduleForThisPermission,
                        Object.keys(allModules).includes(moduleForThisPermission)
                            ? 'platform'
                            : Object.keys(modulePermissions?.productivity || {}).includes(moduleForThisPermission)
                              ? 'productivity'
                              : Object.keys(modulePermissions?.communication || {}).includes(moduleForThisPermission)
                                ? 'communication'
                                : 'platform',
                    ),
                ) as string[];

                const hasOtherPermissions = modulePerms.some((permSlug) => permSlug !== slug && newPermissions.includes(permSlug));

                // If no permissions left for this module, remove the scope
                if (!hasOtherPermissions) {
                    const { [moduleForThisPermission]: removed, ...remainingScopes } = currentScopes;
                    setValue('moduleScopes', remainingScopes);
                }
            }
        }
    };

    // Toggle all permissions of a module
    const toggleModule = (module: string, checked: boolean, category: string) => {
        const modulePerms = Object.values(getModulePermissions(module, category));
        const currentPermissions = formData.permissions || [];
        const newPermissions = checked
            ? Array.from(new Set([...currentPermissions, ...modulePerms]))
            : currentPermissions.filter((p: string) => !modulePerms.includes(p));
        setValue('permissions', newPermissions);

        const currentScopes = formData.moduleScopes || {};

        if (checked) {
            // Set default scope to 'global' when module is selected
            if (!currentScopes[module]) {
                setValue('moduleScopes', {
                    ...currentScopes,
                    [module]: { scope: 'global', is_show: 1 },
                });
            }
        } else {
            // Remove scope when module is deselected
            const { [module]: removed, ...remainingScopes } = currentScopes;
            setValue('moduleScopes', remainingScopes);
        }
    };

    // Set scope for a module
    const setModuleScope = (module: string, scope: ScopeType) => {
        const currentScopes = formData.moduleScopes || {};
        const existing = currentScopes[module] || { scope: 'global', is_show: 1 };
        setValue('moduleScopes', {
            ...currentScopes,
            [module]: { ...existing, scope },
        });
    };

    // Handle role name change
    const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const value = e.target.value;
        setValue('name', value);
        if (!isEdit) {
            setValue('slug', generateSlug(value));
        }
    };

    // Helpers
    const isModuleSelected = (module: string, category: string) => {
        const modulePerms = Object.values(getModulePermissions(module, category)) as string[];
        return modulePerms.every((slug: string) => (formData.permissions || []).includes(slug));
    };

    const isModuleIndeterminate = (module: string, category: string) => {
        const modulePerms = Object.values(getModulePermissions(module, category)) as string[];
        const selectedCount = modulePerms.filter((slug: string) => (formData.permissions || []).includes(slug)).length;
        return selectedCount > 0 && selectedCount < modulePerms.length;
    };

    return (
        <div className="space-y-4">
            {/* Permissions Section */}
            <Card className="border shadow-none">
                <CardHeader className="px-2 pt-2 pb-3">
                    <CardTitle className="text-lg sm:text-xl">Role Information</CardTitle>
                </CardHeader>
                <CardContent className="pb-1">
                    <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
                        {/* Role Name */}
                        <div>
                            <Label htmlFor="role-name" className="mb-2 block text-sm font-medium">
                                Role Name *
                            </Label>
                            <Input
                                id="role-name"
                                name="name"
                                placeholder="Admin"
                                value={formData.name || ''}
                                onChange={handleNameChange}
                                disabled={isView}
                                className={`text-base sm:text-lg ${errors.name ? 'border-red-500 focus:border-red-500' : ''}`}
                            />
                            {errors.name && <p className="mt-2 text-sm text-red-600">{(errors.name as any)?.message}</p>}
                        </div>

                        {/* Role Slug */}
                        <div>
                            <Label htmlFor="role-slug" className="mb-2 block text-sm font-medium">
                                Slug
                            </Label>
                            <Input
                                id="role-slug"
                                value={roleSlug}
                                disabled
                                className="bg-gray-50 text-base text-gray-600 sm:text-lg"
                                placeholder="Auto-generated from role name"
                            />
                            <p className="mt-1 text-xs text-gray-500">
                                {isEdit ? 'Slug cannot be changed when editing' : 'This field is automatically generated from the role name'}
                            </p>
                        </div>
                    </div>
                </CardContent>
            </Card>

            {/* Permission Sections */}

            <div id="permissions" className="space-y-4">
                {Object.entries(moduleCategories).map(([categoryKey, modules]) => {
                    const categoryPermissions = modules.flatMap((module) => Object.values(getModulePermissions(module, categoryKey))) as string[];
                    const categoryAllSelected = categoryPermissions.every((slug) => (formData.permissions || []).includes(slug));
                    const categorySomeSelected =
                        categoryPermissions.some((slug) => (formData.permissions || []).includes(slug)) && !categoryAllSelected;
                    const selectedCount = (formData.permissions || []).filter((p: string) => categoryPermissions.includes(p)).length;

                    return (
                        <Card key={categoryKey} className="space-y-4 px-5 py-4">
                            {/* Section Header */}
                            <div className="pb-3">
                                <div className="flex flex-wrap items-start justify-between gap-2">
                                    <div className="">
                                        <h3 className="text-xl font-semibold capitalize">{categoryKey}</h3>
                                        <p className="text-sm text-gray-600">
                                            <span className="text-gray-600">{selectedCount || 0} Permissions selected</span>
                                        </p>
                                        {errors.permissions && <p className="mt-1 text-sm text-red-600">{(errors.permissions as any)?.message}</p>}
                                    </div>
                                    <Button
                                        type="button"
                                        disabled={isView}
                                        variant="outline"
                                        size="sm"
                                        onClick={(e: React.MouseEvent) => {
                                            e.preventDefault();
                                            const currentPermissions = formData.permissions || [];
                                            const newPermissions = categoryAllSelected
                                                ? currentPermissions.filter((p: string) => !categoryPermissions.includes(p))
                                                : Array.from(new Set([...currentPermissions, ...categoryPermissions]));
                                            setValue('permissions', newPermissions);

                                            const currentScopes = formData.moduleScopes || {};

                                            if (!categoryAllSelected) {
                                                // Set default scope to 'global' for newly selected modules
                                                const newScopes = { ...currentScopes };

                                                modules.forEach((module) => {
                                                    if (!newScopes[module]) {
                                                        newScopes[module] = { scope: 'global', is_show: 1 };
                                                    }
                                                });

                                                setValue('moduleScopes', newScopes);
                                            } else {
                                                // Remove scopes for deselected modules
                                                const newScopes = { ...currentScopes };
                                                modules.forEach((module) => {
                                                    delete newScopes[module];
                                                });
                                                setValue('moduleScopes', newScopes);
                                            }
                                        }}
                                        className={`text-xs sm:w-auto sm:text-sm ${
                                            categoryAllSelected ? 'border-red-500 text-red-600 hover:bg-red-50' : ''
                                        }`}
                                    >
                                        {categoryAllSelected ? 'Deselect All' : 'Select All'}
                                    </Button>
                                </div>
                            </div>

                            {/* Module Cards */}
                            <div className="grid w-full grid-cols-1 gap-4 sm:gap-3 md:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-3">
                                {modules.map((module) => {
                                    const perms = Object.entries(getModulePermissions(module, categoryKey));
                                    const moduleSlugs = perms.map(([_, slug]) => slug);
                                    const hasPermissions = moduleSlugs.some((slug) => (formData.permissions || []).includes(slug));

                                    return (
                                        <Card key={module} className="p-0 shadow-none">
                                            <div className="mb-3 p-2 px-3 pb-3">
                                                <div className="flex items-start justify-between gap-3">
                                                    <CardTitle className="px-0 text-base font-semibold sm:text-lg">
                                                        <div className="break-words">{module}</div>
                                                    </CardTitle>
                                                    <div className="flex items-center gap-2">
                                                        <Checkbox
                                                            disabled={isView}
                                                            checked={isModuleSelected(module, categoryKey)}
                                                            onCheckedChange={(checked: boolean) => toggleModule(module, checked, categoryKey)}
                                                            className="shrink-0 text-blue-600"
                                                        />
                                                        <button
                                                            type="button"
                                                            disabled={isView}
                                                            onClick={() => toggleModule(module, !isModuleSelected(module, categoryKey), categoryKey)}
                                                            className={`text-sm font-medium ${isView ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`}
                                                            aria-disabled={isView}
                                                        >
                                                            Select All
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                            <CardContent className="flex h-full flex-col space-y-4 pb-3">
                                                {/* Permissions in grid */}
                                                <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
                                                    {perms.map(([name, slug]) => (
                                                        <label key={slug as string} className="flex cursor-pointer items-start space-x-2 text-sm">
                                                            <Checkbox
                                                                disabled={isView}
                                                                checked={(formData.permissions || []).includes(slug as string)}
                                                                onCheckedChange={(checked: boolean) => togglePermission(slug as string, checked)}
                                                                className="mt-0.5 shrink-0 text-blue-600"
                                                            />
                                                            <button
                                                                type="button"
                                                                disabled={isView}
                                                                aria-disabled={isView}
                                                                onClick={() =>
                                                                    togglePermission(
                                                                        slug as string,
                                                                        !(formData.permissions || []).includes(slug as string),
                                                                    )
                                                                }
                                                                className={`leading-relaxed break-words ${isView ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}`}
                                                            >
                                                                {name}
                                                            </button>
                                                        </label>
                                                    ))}
                                                </div>

                                                {/* Scope Selection - only shown when module has permissions */}
                                                {hasPermissions && (
                                                    <div className="mt-auto">
                                                        <div className="flex w-full items-center justify-between gap-1 border-t pt-3">
                                                            <Label className="">Access Scope :</Label>
                                                            <RadioGroup
                                                                disabled={isView}
                                                                value={
                                                                    typeof (formData.moduleScopes || {})[module] === 'object'
                                                                        ? (formData.moduleScopes || {})[module]?.scope || 'global'
                                                                        : (formData.moduleScopes || {})[module] || 'global'
                                                                }
                                                                onValueChange={(value: ScopeType) => setModuleScope(module, value)}
                                                                className="flex items-center gap-4"
                                                            >
                                                                {[
                                                                    {
                                                                        label: 'Global',
                                                                        value: 'global',
                                                                        description: 'Access to all resources',
                                                                    },
                                                                    {
                                                                        label: 'Specific (Self and assigned)',
                                                                        value: 'local',
                                                                        description: 'Access to specific resources',
                                                                    },
                                                                ].map((scope) => (
                                                                    <label
                                                                        key={scope.value}
                                                                        className="flex cursor-pointer items-start space-x-2 text-xs sm:text-sm"
                                                                        htmlFor={`${module}-${scope.value}`}
                                                                    >
                                                                        <RadioGroupItem
                                                                            id={`${module}-${scope.value}`}
                                                                            disabled={isView}
                                                                            value={scope.value}
                                                                            className={`mt-1 shrink-0 text-brand-600 ${isView ? 'cursor-not-allowed opacity-50' : ''}`}
                                                                        />
                                                                        <div className="">
                                                                            <p
                                                                                className={`leading-relaxed capitalize ${isView ? 'cursor-not-allowed opacity-50' : ''}`}
                                                                            >
                                                                                {scope.label}
                                                                            </p>
                                                                        </div>
                                                                    </label>
                                                                ))}
                                                            </RadioGroup>
                                                            <div></div>
                                                        </div>
                                                    </div>
                                                )}
                                            </CardContent>
                                        </Card>
                                    );
                                })}
                            </div>
                        </Card>
                    );
                })}
            </div>

            {/* Submit button */}
            {!isView && (
                <div className="flex gap-3 sm:flex-row sm:justify-end">
                    <Button type="button" variant="outline" onClick={() => history.back()} className="w-full sm:w-auto">
                        Close
                    </Button>

                    <Button type="submit" className="w-full bg-success text-white hover:bg-brand-800 sm:w-auto">
                        <Plus className="h-4 w-4" />
                        {isEdit ? 'Update Role' : 'Create Role'}
                    </Button>
                </div>
            )}
        </div>
    );
}

export default function RoleForm({
    modulePermissions,
    initialData = {},
    onSubmit,
    submitButtonText,
    isEdit = false,
    isView = false,
}: RoleFormWithHookFormProps) {
    // export default function RoleForm({ modulePermissions, initialData = {}, onSubmit, submitButtonText, isEdit = false }: RoleFormWithHookFormProps) {
    const normalizeModuleScopes = (scopes: any) => {
        if (!scopes) return {};
        const normalized: Record<string, { scope: ScopeType; is_show: number }> = {};
        Object.entries(scopes).forEach(([module, value]: [string, any]) => {
            if (typeof value === 'string') {
                normalized[module] = { scope: value as ScopeType, is_show: 1 };
            } else if (value && typeof value === 'object') {
                const scopeVal = (value.scope as ScopeType) || 'global';
                const isShowVal = value.is_show === 0 ? 0 : 1;
                normalized[module] = { scope: scopeVal, is_show: isShowVal };
            } else {
                normalized[module] = { scope: 'global', is_show: 1 };
            }
        });
        return normalized;
    };

    // Ensure we apply normalized moduleScopes after spreading initialData so it can't be overwritten by raw initialData.moduleScopes
    const defaultValues = {
        name: '',
        slug: '',
        permissions: [],
        ...initialData,
        moduleScopes: normalizeModuleScopes(initialData.moduleScopes || initialData.module_scopes || {}),
    };

    const handleFormSubmit = async (data: any) => {
        // Check if scopes are selected for modules with permissions
        const allModules = modulePermissions?.modules || {};
        const selectedModules = Object.entries(allModules)
            .filter(([module]) => Object.values(allModules[module]).some((slug) => data.permissions.includes(slug)))
            .map(([module]) => module);

        const missingScopes = selectedModules.filter((module) => !data.moduleScopes?.[module]);

        // if (missingScopes.length > 0) {
        //     toast.error('Scope Validation Error', {
        //         description: `Please select access scope for: ${missingScopes.join(', ')}`,
        //     });
        //     return;
        // }

        // Add slug to the data
        const submitData = {
            ...data,
            slug: isEdit
                ? data.slug
                : data.name
                      .toLowerCase()
                      .trim()
                      .replace(/[^a-z0-9\s-]/g, '')
                      .replace(/\s+/g, '-')
                      .replace(/-+/g, '-')
                      .replace(/^-|-$/g, ''),
        };

        onSubmit(submitData);
    };

    return (
        <Form defaultValues={defaultValues} resolver={yupResolver(roleSchema)} submitHandler={handleFormSubmit} formClassNames="space-y-6">
            <RoleFormFields modulePermissions={modulePermissions} isEdit={isEdit} isView={isView} />
        </Form>
    );
}
