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 {
        watch,
        setValue,
        formState: { errors },
    } = useFormContext();
    // Removed activeTab state as we're using sections now
    const formData = watch();

    // Extract all modules and their permissions for the "all" tab
    const allApps = modulePermissions || {};
    const allPermissions = Object.values(allApps)
        .flatMap((app: any) => Object.values(app))
        .flatMap((group: any) => Object.values(group)) as string[];
    
    // Organize modules by categories based on the new structure (App → Group → Permissions)
    const moduleCategories = Object.keys(allApps).reduce((acc, appName) => {
        acc[appName] = Object.keys(allApps[appName]);
        return acc;
    }, {} as Record<string, string[]>);

    // Function to get permissions for a group within an app
    const getGroupPermissions = (appName: string, groupName: string) => {
        return allApps[appName]?.[groupName] || {};
    };

    // 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 app and group this permission belongs to
        const findAppAndGroupForPermission = () => {
            for (const appName of Object.keys(allApps)) {
                for (const groupName of Object.keys(allApps[appName])) {
                    const groupPerms = allApps[appName][groupName];
                    if (Object.values(groupPerms).includes(slug)) {
                        return { appName, groupName };
                    }
                }
            }
            return null;
        };

        const location = findAppAndGroupForPermission();

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

            if (checked) {
                // Set default scope to 'global' when permission is first selected
                if (!currentScopes[groupName]) {
                    setValue('moduleScopes', {
                        ...currentScopes,
                        [groupName]: { scope: 'global', is_show: 1 },
                    });
                }
            } else {
                // Check if group still has any permissions selected
                const groupPerms = Object.values(getGroupPermissions(location.appName, groupName)) as string[];
                const hasOtherPermissions = groupPerms.some((permSlug) => permSlug !== slug && newPermissions.includes(permSlug));

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

    // Toggle all permissions of a group
    const toggleGroup = (appName: string, groupName: string, checked: boolean) => {
        const groupPerms = Object.values(getGroupPermissions(appName, groupName));
        const currentPermissions = formData.permissions || [];
        const newPermissions = checked
            ? Array.from(new Set([...currentPermissions, ...groupPerms]))
            : currentPermissions.filter((p: string) => !groupPerms.includes(p));
        setValue('permissions', newPermissions);

        const currentScopes = formData.moduleScopes || {};

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

    // Set scope for a group
    const setGroupScope = (groupName: string, scope: ScopeType) => {
        const currentScopes = formData.moduleScopes || {};
        const existing = currentScopes[groupName] || { scope: 'global', is_show: 1 };
        setValue('moduleScopes', {
            ...currentScopes,
            [groupName]: { ...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 isGroupSelected = (appName: string, groupName: string) => {
        const groupPerms = Object.values(getGroupPermissions(appName, groupName)) as string[];
        return groupPerms.every((slug: string) => (formData.permissions || []).includes(slug));
    };

    const isGroupIndeterminate = (appName: string, groupName: string) => {
        const groupPerms = Object.values(getGroupPermissions(appName, groupName)) as string[];
        const selectedCount = groupPerms.filter((slug: string) => (formData.permissions || []).includes(slug)).length;
        return selectedCount > 0 && selectedCount < groupPerms.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(([appName, groups]) => {
                    const appPermissions = groups.flatMap((group) => Object.values(getGroupPermissions(appName, group))) as string[];
                    const appAllSelected = appPermissions.every((slug) => (formData.permissions || []).includes(slug));
                    const appSomeSelected =
                        appPermissions.some((slug) => (formData.permissions || []).includes(slug)) && !appAllSelected;
                    const selectedCount = (formData.permissions || []).filter((p: string) => appPermissions.includes(p)).length;

                    return (
                        <Card key={appName} className="space-y-4 px-5 py-4">
                            {/* App 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">{appName}</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 = appAllSelected
                                                ? currentPermissions.filter((p: string) => !appPermissions.includes(p))
                                                : Array.from(new Set([...currentPermissions, ...appPermissions]));
                                            setValue('permissions', newPermissions);

                                            const currentScopes = formData.moduleScopes || {};

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

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

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

                            {/* Group 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">
                                {groups.map((groupName) => {
                                    const perms = Object.entries(getGroupPermissions(appName, groupName));
                                    const groupSlugs = perms.map(([_, slug]) => slug);
                                    const hasPermissions = groupSlugs.some((slug) => (formData.permissions || []).includes(slug));

                                    return (
                                        <Card key={groupName} 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="wrap-break-word">{groupName}</div>
                                                    </CardTitle>
                                                    <div className="flex items-center gap-2">
                                                        <Checkbox
                                                            disabled={isView}
                                                            checked={isGroupSelected(appName, groupName)}
                                                            onCheckedChange={(checked: boolean) => toggleGroup(appName, groupName, checked)}
                                                            className="shrink-0 text-blue-600"
                                                        />
                                                        <button
                                                            type="button"
                                                            disabled={isView}
                                                            onClick={() => toggleGroup(appName, groupName, !isGroupSelected(appName, groupName))}
                                                            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 wrap-break-word ${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 || {})[groupName] === 'object'
                                                                        ? (formData.moduleScopes || {})[groupName]?.scope || 'global'
                                                                        : (formData.moduleScopes || {})[groupName] || 'global'
                                                                }
                                                                onValueChange={(value: ScopeType) => setGroupScope(groupName, 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={`${groupName}-${scope.value}`}
                                                                    >
                                                                        <RadioGroupItem
                                                                            id={`${groupName}-${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 groups with permissions
        const allApps = modulePermissions || {};
        const selectedGroups: string[] = [];
        
        // Find all groups that have selected permissions
        Object.entries(allApps).forEach(([appName, groups]) => {
            Object.entries(groups as any).forEach(([groupName, permissions]) => {
                const groupPerms = Object.values(permissions as any) as string[];
                if (groupPerms.some((slug) => data.permissions.includes(slug))) {
                    selectedGroups.push(groupName);
                }
            });
        });

        const missingScopes = selectedGroups.filter((group) => !data.moduleScopes?.[group]);

        // 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>
    );
}
