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 { 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';

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

const SCOPES = [
    { label: 'Global', value: 'global' },
    { label: 'Specific', value: 'local' },
];

function RoleFormFields({ modulePermissions, isEdit = false, isView = false }: { modulePermissions: any; isEdit?: boolean; isView?: boolean }) {
    const { watch, setValue, formState: { errors } } = useFormContext();
    const formData = watch();

    const allApps = modulePermissions || {};

    const moduleCategories = Object.keys(allApps).reduce(
        (acc, appName) => { acc[appName] = Object.keys(allApps[appName]); return acc; },
        {} as Record<string, string[]>,
    );

    const getGroupPermissions = (appName: string, groupName: string) => allApps[appName]?.[groupName] || {};

    const generateSlug = (name: string) =>
        name.toLowerCase().trim()
            .replace(/[^a-z0-9\s-]/g, '')
            .replace(/\s+/g, '-')
            .replace(/-+/g, '-')
            .replace(/^-|-$/g, '');

    const roleSlug = useMemo(
        () => isEdit ? formData.slug : generateSlug(formData.name || ''),
        [formData.name, formData.slug, isEdit],
    );

    const togglePermission = (slug: string, checked: boolean) => {
        const current = formData.permissions || [];
        const next = checked ? [...current, slug] : current.filter((p: string) => p !== slug);
        setValue('permissions', next);

        const findGroup = () => {
            for (const appName of Object.keys(allApps)) {
                for (const groupName of Object.keys(allApps[appName])) {
                    if (Object.values(allApps[appName][groupName]).includes(slug)) return { appName, groupName };
                }
            }
            return null;
        };

        const loc = findGroup();
        if (loc) {
            const { groupName } = loc;
            const currentScopes = formData.moduleScopes || {};
            if (checked) {
                if (!currentScopes[groupName]) {
                    setValue('moduleScopes', { ...currentScopes, [groupName]: { scope: 'global', is_show: 1 } });
                }
            } else {
                const groupPerms = Object.values(getGroupPermissions(loc.appName, groupName)) as string[];
                const hasOther = groupPerms.some((s) => s !== slug && next.includes(s));
                if (!hasOther) {
                    const { [groupName]: _, ...rest } = currentScopes;
                    setValue('moduleScopes', rest);
                }
            }
        }
    };

    const toggleGroup = (appName: string, groupName: string, checked: boolean) => {
        const groupPerms = Object.values(getGroupPermissions(appName, groupName));
        const current = formData.permissions || [];
        const next = checked
            ? Array.from(new Set([...current, ...groupPerms]))
            : current.filter((p: string) => !groupPerms.includes(p));
        setValue('permissions', next);

        const currentScopes = formData.moduleScopes || {};
        if (checked) {
            if (!currentScopes[groupName]) {
                setValue('moduleScopes', { ...currentScopes, [groupName]: { scope: 'global', is_show: 1 } });
            }
        } else {
            const { [groupName]: _, ...rest } = currentScopes;
            setValue('moduleScopes', rest);
        }
    };

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

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

    const isGroupSelected = (appName: string, groupName: string) => {
        const slugs = Object.values(getGroupPermissions(appName, groupName)) as string[];
        return slugs.length > 0 && slugs.every((s) => (formData.permissions || []).includes(s));
    };

    return (
        <div className="space-y-3">
            {/* ── Role Information ── */}
            <Card className="border shadow-none">
                <CardHeader className="px-4 pt-3 pb-2">
                    <CardTitle className="text-sm font-semibold uppercase tracking-wide text-gray-500">Role Information</CardTitle>
                </CardHeader>
                <CardContent className="px-4 pb-3">
                    <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                        <div>
                            <Label htmlFor="role-name" className="mb-1 block text-xs font-medium text-gray-600">
                                Role Name *
                            </Label>
                            <Input
                                id="role-name"
                                name="name"
                                placeholder="e.g. Content Manager"
                                value={formData.name || ''}
                                onChange={handleNameChange}
                                disabled={isView}
                                className={`h-8 text-sm ${errors.name ? 'border-red-500' : ''}`}
                            />
                            {errors.name && <p className="mt-1 text-xs text-red-600">{(errors.name as any)?.message}</p>}
                        </div>
                        <div>
                            <Label htmlFor="role-slug" className="mb-1 block text-xs font-medium text-gray-600">
                                Slug
                            </Label>
                            <Input
                                id="role-slug"
                                value={roleSlug}
                                disabled
                                className="h-8 bg-gray-50 text-sm text-gray-500"
                            />
                        </div>
                    </div>
                </CardContent>
            </Card>

            {/* ── Permissions ── */}
            <div id="permissions" className="space-y-3">
                {errors.permissions && (
                    <p className="text-sm text-red-600">{(errors.permissions as any)?.message}</p>
                )}

                {Object.entries(moduleCategories).map(([appName, groups]) => {
                    const appPermissions = groups.flatMap((g) => Object.values(getGroupPermissions(appName, g))) as string[];
                    const appAllSelected = appPermissions.length > 0 && appPermissions.every((s) => (formData.permissions || []).includes(s));
                    const selectedCount = (formData.permissions || []).filter((p: string) => appPermissions.includes(p)).length;

                    return (
                        <Card key={appName} className="overflow-hidden border shadow-none">
                            {/* App header */}
                            <div className="flex items-center justify-between border-b bg-gray-50 px-4 py-2">
                                <div className="flex items-center gap-2">
                                    <h3 className="text-sm font-semibold capitalize">{appName}</h3>
                                    {selectedCount > 0 && (
                                        <span className="rounded-full bg-primary/10 px-2 py-0.5 text-[11px] font-medium text-primary">
                                            {selectedCount} selected
                                        </span>
                                    )}
                                </div>
                                <Button
                                    type="button"
                                    disabled={isView}
                                    variant="ghost"
                                    size="sm"
                                    onClick={(e: React.MouseEvent) => {
                                        e.preventDefault();
                                        const current = formData.permissions || [];
                                        const next = appAllSelected
                                            ? current.filter((p: string) => !appPermissions.includes(p))
                                            : Array.from(new Set([...current, ...appPermissions]));
                                        setValue('permissions', next);

                                        const currentScopes = formData.moduleScopes || {};
                                        if (!appAllSelected) {
                                            const newScopes = { ...currentScopes };
                                            groups.forEach((g) => { if (!newScopes[g]) newScopes[g] = { scope: 'global', is_show: 1 }; });
                                            setValue('moduleScopes', newScopes);
                                        } else {
                                            const newScopes = { ...currentScopes };
                                            groups.forEach((g) => { delete newScopes[g]; });
                                            setValue('moduleScopes', newScopes);
                                        }
                                    }}
                                    className={`h-6 px-2 text-xs ${appAllSelected ? 'text-red-600 hover:bg-red-50 hover:text-red-700' : 'text-gray-500 hover:text-gray-700'}`}
                                >
                                    {appAllSelected ? 'Deselect All' : 'Select All'}
                                </Button>
                            </div>

                            {/* Group grid */}
                            <div className="grid grid-cols-1 gap-2 p-3 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4">
                                {groups.map((groupName) => {
                                    const perms = Object.entries(getGroupPermissions(appName, groupName));
                                    const groupSlugs = perms.map(([, s]) => s as string);
                                    const hasPermissions = groupSlugs.some((s) => (formData.permissions || []).includes(s));
                                    const groupSelected = isGroupSelected(appName, groupName);
                                    const scopeValue = (() => {
                                        const v = (formData.moduleScopes || {})[groupName];
                                        return typeof v === 'object' ? v?.scope ?? 'global' : v ?? 'global';
                                    })();

                                    return (
                                        <div key={groupName} className="flex flex-col rounded-lg border bg-white">
                                            {/* Group header */}
                                            <div className="flex items-center justify-between gap-2 rounded-t-lg bg-gray-50 px-3 py-2">
                                                <div className="flex items-center gap-2 min-w-0">
                                                    <div className={`size-2 shrink-0 rounded-full ${hasPermissions ? 'bg-primary' : 'bg-gray-300'}`} />
                                                    <span className="truncate text-[13px] font-semibold text-gray-700">{groupName}</span>
                                                </div>
                                                <div className="flex shrink-0 items-center gap-2">
                                                    <button
                                                        type="button"
                                                        disabled={isView}
                                                        onClick={() => toggleGroup(appName, groupName, !groupSelected)}
                                                        className="text-xs text-gray-400 hover:text-gray-600 disabled:opacity-40"
                                                    >
                                                        {groupSelected ? 'None' : 'All'}
                                                    </button>
                                                    <Checkbox
                                                        disabled={isView}
                                                        checked={groupSelected}
                                                        onCheckedChange={(c: boolean) => toggleGroup(appName, groupName, c)}
                                                        className="h-4 w-4 shrink-0"
                                                    />
                                                </div>
                                            </div>

                                            {/* Permission rows */}
                                            <div className="flex flex-col px-1.5 py-1.5">
                                                {perms.map(([name, slug]) => {
                                                    const checked = (formData.permissions || []).includes(slug as string);
                                                    return (
                                                        <label
                                                            key={slug as string}
                                                            className={`flex cursor-pointer items-center gap-2.5 rounded px-2.5 py-1.5 transition-colors ${checked ? 'bg-primary/5' : 'hover:bg-gray-50'} ${isView ? 'cursor-not-allowed opacity-60' : ''}`}
                                                        >
                                                            <Checkbox
                                                                disabled={isView}
                                                                checked={checked}
                                                                onCheckedChange={(c: boolean) => togglePermission(slug as string, c)}
                                                                className="h-4 w-4 shrink-0"
                                                            />
                                                            <span className={`text-[13px] font-medium leading-none ${checked ? 'text-gray-800' : 'text-gray-500'}`}>
                                                                {name}
                                                            </span>
                                                        </label>
                                                    );
                                                })}
                                            </div>

                                            {/* Scope selector */}
                                            {hasPermissions && (
                                                <div className="mt-auto border-t px-3 py-2">
                                                    <RadioGroup
                                                        disabled={isView}
                                                        value={scopeValue}
                                                        onValueChange={(v) => setGroupScope(groupName, v as ScopeType)}
                                                        className="flex items-center gap-3"
                                                    >
                                                        {SCOPES.map((s) => (
                                                            <label
                                                                key={s.value}
                                                                htmlFor={`${groupName}-${s.value}`}
                                                                className={`flex cursor-pointer items-center gap-1.5 ${isView ? 'cursor-not-allowed opacity-50' : ''}`}
                                                            >
                                                                <RadioGroupItem
                                                                    id={`${groupName}-${s.value}`}
                                                                    value={s.value}
                                                                    disabled={isView}
                                                                    className="h-3.5 w-3.5 shrink-0"
                                                                />
                                                                <span className="text-xs text-gray-600">{s.label}</span>
                                                            </label>
                                                        ))}
                                                    </RadioGroup>
                                                </div>
                                            )}
                                        </div>
                                    );
                                })}
                            </div>
                        </Card>
                    );
                })}
            </div>

            {/* Submit */}
            {!isView && (
                <div className="flex gap-3 sm:justify-end">
                    <Button type="button" variant="outline" onClick={() => history.back()} className="sm:w-auto">
                        Cancel
                    </Button>
                    <Button type="submit" className="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) {
    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') {
                normalized[module] = { scope: (value.scope as ScopeType) || 'global', is_show: value.is_show === 0 ? 0 : 1 };
            } else {
                normalized[module] = { scope: 'global', is_show: 1 };
            }
        });
        return normalized;
    };

    const defaultValues = {
        name: '',
        slug: '',
        permissions: [],
        ...initialData,
        moduleScopes: normalizeModuleScopes(initialData.moduleScopes || initialData.module_scopes || {}),
    };

    const handleFormSubmit = async (data: any) => {
        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-3">
            <RoleFormFields modulePermissions={modulePermissions} isEdit={isEdit} isView={isView} />
        </Form>
    );
}
