import { useEffect, useState, useMemo } from 'react';
import type { ReactElement } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { ChevronDown, ChevronRight } from 'lucide-react';
import { Modal, FormField, PrimaryButton, SecondaryButton, MultiselectPaginatedSelect } from '@/components/shared';
import type { CreateRoleRequest } from '@/types/role';
import { useAppSelector } from '@/hooks/redux-hooks';

// Utility function to generate code from name
const generateCodeFromName = (name: string): string => {
  return name
    .toLowerCase()
    .trim()
    .replace(/[^a-z0-9\s]/g, '') // Remove special characters except spaces
    .replace(/\s+/g, '_') // Replace spaces with underscores
    .replace(/_+/g, '_') // Replace multiple underscores with single underscore
    .replace(/^_|_$/g, ''); // Remove leading/trailing underscores
};

// All available resources
const ALL_RESOURCES = [
  'users',
  // 'tenants',
  'roles',
  'permissions',
  // 'user_roles',
  // 'user_tenants',
  // 'sessions',
  // 'api_keys',
  // 'api_key_permissions',
  'projects',
  'document',
  'audit',
  'security',
  'workflow',
  'training',
  'capa',
  'supplier',
  'reports',
  'notifications',
  'files',
  'settings',
  // 'modules',
  'audit_logs',
  // 'event_logs',
  // 'health_history',
  'qms_connections',
  'qms_sync_jobs',
  'qms_sync_conflicts',
  'qms_entity_mappings',
  'ai',
  'qms',
];

// All available actions
const ALL_ACTIONS = ['create', 'read', 'update', 'delete'];

// Validation schema
const newRoleSchema = z.object({
  name: z.string().min(1, 'Role name is required'),
  code: z
    .string()
    .min(1, 'Code is required')
    .regex(
      /^[a-z]+(_[a-z]+)*$/,
      "Code must be lowercase and use '_' for separation (e.g. abc_def)"
    ),
  description: z.string().min(1, 'Description is required'),
  module_ids: z.array(z.string().uuid()).optional().nullable(),
  permissions: z.array(z.object({
    resource: z.string(),
    action: z.string(),
  })).optional().nullable(),
});

type NewRoleFormData = z.infer<typeof newRoleSchema>;

interface NewRoleModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSubmit: (data: CreateRoleRequest) => Promise<void>;
  isLoading?: boolean;
}

export const NewRoleModal = ({
  isOpen,
  onClose,
  onSubmit,
  isLoading = false,
}: NewRoleModalProps): ReactElement | null => {
  const permissions = useAppSelector((state) => state.auth.permissions);
  const roles = useAppSelector((state) => state.auth.roles);
  const tenant = useAppSelector((state) => state.auth.tenant);
  const isSuperAdmin = roles.includes('super_admin');
  const [selectedModules, setSelectedModules] = useState<string[]>([]);
  const [selectedPermissions, setSelectedPermissions] = useState<Array<{ resource: string; action: string }>>([]);
  const [expandedResources, setExpandedResources] = useState<Set<string>>(new Set());

  const {
    register,
    handleSubmit,
    setValue,
    watch,
    reset,
    setError,
    clearErrors,
    formState: { errors },
  } = useForm<NewRoleFormData>({
    resolver: zodResolver(newRoleSchema),
    defaultValues: {
      code: undefined,
      module_ids: [],
      permissions: [],
    },
  });

  const nameValue = watch('name');

  // Auto-generate code from name
  useEffect(() => {
    if (nameValue) {
      const generatedCode = generateCodeFromName(nameValue);
      setValue('code', generatedCode, { shouldValidate: true });
    }
  }, [nameValue, setValue]);

  // Reset form when modal closes
  useEffect(() => {
    if (!isOpen) {
      reset({
        name: '',
        code: undefined,
        description: '',
        module_ids: [],
        permissions: [],
      });
      setSelectedModules([]);
      setSelectedPermissions([]);
      clearErrors();
    }
  }, [isOpen, reset, clearErrors]);

  // Load modules from tenant assignedModules
  const loadModules = async (page: number, limit: number) => {
    const assignedModules = tenant?.assignedModules || [];
    const startIndex = (page - 1) * limit;
    const endIndex = startIndex + limit;
    const paginatedModules = assignedModules.slice(startIndex, endIndex);
    
    return {
      options: paginatedModules.map((module) => ({
        value: module.id,
        label: module.name,
      })),
      pagination: {
        page,
        limit,
        total: assignedModules.length,
        totalPages: Math.ceil(assignedModules.length / limit),
        hasMore: endIndex < assignedModules.length,
      },
    };
  };

  // Build available resources and actions based on user permissions
  const availableResourcesAndActions = useMemo(() => {
    const resourceMap = new Map<string, Set<string>>();

    permissions.forEach((perm) => {
      const { resource, action } = perm;

      if (resource === '*') {
        // If resource is *, show all resources
        ALL_RESOURCES.forEach((res) => {
          if (!resourceMap.has(res)) {
            resourceMap.set(res, new Set());
          }
          const actions = resourceMap.get(res)!;
          if (action === '*') {
            // If action is also *, add all actions
            ALL_ACTIONS.forEach((act) => actions.add(act));
          } else {
            actions.add(action);
          }
        });
      } else {
        // Specific resource
        if (!resourceMap.has(resource)) {
          resourceMap.set(resource, new Set());
        }
        const actions = resourceMap.get(resource)!;
        if (action === '*') {
          // If action is *, add all actions for this resource
          ALL_ACTIONS.forEach((act) => actions.add(act));
        } else {
          actions.add(action);
        }
      }
    });

    return resourceMap;
  }, [permissions]);

  // Check if a resource has any selected actions
  const hasSelectedActions = (resource: string, actions: Set<string>): boolean => {
    return Array.from(actions).some((action) => {
      return selectedPermissions.some((p) => {
        // Check for exact match
        if (p.resource === resource && p.action === action) return true;
        // Check for wildcard resource with exact action
        if (p.resource === '*' && p.action === action) return true;
        // Check for exact resource with wildcard action
        if (p.resource === resource && p.action === '*') return true;
        // Check for wildcard resource with wildcard action
        if (p.resource === '*' && p.action === '*') return true;
        return false;
      });
    });
  };

  // Toggle resource expansion
  const toggleResource = (resource: string) => {
    setExpandedResources((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(resource)) {
        newSet.delete(resource);
      } else {
        newSet.add(resource);
      }
      return newSet;
    });
  };

  // Handle permission checkbox change
  const handlePermissionChange = (resource: string, action: string, checked: boolean) => {
    setSelectedPermissions((prev) => {
      const newPerms = [...prev];
      if (checked) {
        // Add permission if not already exists
        if (!newPerms.some((p) => p.resource === resource && p.action === action)) {
          newPerms.push({ resource, action });
        }
      } else {
        // Remove permission
        return newPerms.filter((p) => !(p.resource === resource && p.action === action));
      }
      return newPerms;
    });
  };

  // Update form value when permissions change
  useEffect(() => {
    setValue('permissions', selectedPermissions.length > 0 ? selectedPermissions : []);
  }, [selectedPermissions, setValue]);

  const handleFormSubmit = async (data: NewRoleFormData): Promise<void> => {
    clearErrors();
    try {
      const submitData = {
        ...data,
        // Only include module_ids if user is not super_admin
        module_ids: isSuperAdmin ? undefined : (selectedModules.length > 0 ? selectedModules : undefined),
        permissions: selectedPermissions.length > 0 ? selectedPermissions : undefined,
      };
      await onSubmit(submitData as CreateRoleRequest);
    } catch (error: any) {
      // Handle validation errors from API
      if (error?.response?.data?.details && Array.isArray(error.response.data.details)) {
        const validationErrors = error.response.data.details;
        validationErrors.forEach((detail: { path: string; message: string }) => {
          if (
            detail.path === 'name' ||
            detail.path === 'code' ||
            detail.path === 'description' ||
            detail.path === 'module_ids' ||
            detail.path === 'permissions'
          ) {
            setError(detail.path as keyof NewRoleFormData, {
              type: 'server',
              message: detail.message,
            });
          }
        });
      } else {
        // Handle general errors
        const errorObj = error?.response?.data?.error;
        const errorMessage =
          (typeof errorObj === 'object' && errorObj !== null && 'message' in errorObj ? errorObj.message : null) ||
          (typeof errorObj === 'string' ? errorObj : null) ||
          error?.response?.data?.message ||
          error?.message ||
          'Failed to create role. Please try again.';
        setError('root', {
          type: 'server',
          message: typeof errorMessage === 'string' ? errorMessage : 'Failed to create role. Please try again.',
        });
      }
    }
  };

  return (
    <Modal
      isOpen={isOpen}
      onClose={onClose}
      title="Create Role"
      description="Define a new role by setting permissions and role type."
      maxWidth="lg"
      footer={
        <>
          <SecondaryButton
            type="button"
            onClick={onClose}
            disabled={isLoading}
            className="px-4 py-2.5 text-sm"
          >
            Cancel
          </SecondaryButton>
          <PrimaryButton
            type="button"
            onClick={handleSubmit(handleFormSubmit)}
            disabled={isLoading}
            size="default"
            className="px-4 py-2.5 text-sm"
          >
            {isLoading ? 'Creating...' : 'Create Role'}
          </PrimaryButton>
        </>
      }
    >
      <form onSubmit={handleSubmit(handleFormSubmit)} className="p-5 flex flex-col gap-0 max-h-[70vh] overflow-y-auto">
        {/* General Error Display */}
        {errors.root && (
          <div className="p-4 bg-[rgba(239,68,68,0.1)] border border-[#ef4444] rounded-md mb-4">
            <p className="text-sm text-[#ef4444]">{errors.root.message}</p>
          </div>
        )}

        {/* Role Name and Role Code Row */}
        <div className="grid grid-cols-2 gap-5 pb-4">
          <FormField
            label="Role Name"
            required
            placeholder="Enter Text Here"
            error={errors.name?.message}
            {...register('name')}
          />

          <FormField
            label="Role Code"
            required
            placeholder="Auto-generated from name"
            error={errors.code?.message}
            {...register('code')}
            disabled
            className="bg-[#f3f4f6] cursor-not-allowed"
          />
        </div>

        {/* Description */}
        <FormField
          label="Description"
          required
          placeholder="Enter Text Here"
          error={errors.description?.message}
          {...register('description')}
        />

        {/* Module Selection - Only show if user is not super_admin */}
        {!isSuperAdmin && (
          <MultiselectPaginatedSelect
            label="Modules"
            placeholder="Select modules"
            value={selectedModules}
            onValueChange={(values) => {
              setSelectedModules(values);
              setValue('module_ids', values.length > 0 ? values : []);
            }}
            onLoadOptions={loadModules}
            error={errors.module_ids?.message}
          />
        )}

        {/* Permissions Section */}
        <div className="pb-4">
          <label className="flex items-center gap-1.5 text-[13px] font-medium text-[#0e1b2a] mb-3">
            <span>Permissions</span>
          </label>
          {errors.permissions && (
            <p className="text-sm text-[#ef4444] mb-2">{errors.permissions.message}</p>
          )}
          <div className="border border-[rgba(0,0,0,0.08)] rounded-md p-4 max-h-96 overflow-y-auto">
            {Array.from(availableResourcesAndActions.entries()).length === 0 ? (
              <p className="text-sm text-[#6b7280]">No permissions available</p>
            ) : (
              <div className="space-y-2">
                {Array.from(availableResourcesAndActions.entries()).map(([resource, actions]) => {
                  const isExpanded = expandedResources.has(resource);
                  const hasSelected = hasSelectedActions(resource, actions);
                  return (
                    <div
                      key={resource}
                      className={`border border-[rgba(0,0,0,0.08)] rounded-md overflow-hidden transition-colors ${
                        hasSelected ? 'bg-[rgba(17,40,104,0.05)]' : 'bg-white'
                      }`}
                    >
                      <button
                        type="button"
                        onClick={() => toggleResource(resource)}
                        className="w-full flex items-center justify-between p-3 hover:bg-[rgba(0,0,0,0.02)] transition-colors"
                      >
                        <div className="flex items-center gap-2">
                          {isExpanded ? (
                            <ChevronDown className="w-4 h-4 text-[#0e1b2a]" />
                          ) : (
                            <ChevronRight className="w-4 h-4 text-[#0e1b2a]" />
                          )}
                          <span
                            className={`font-medium text-sm capitalize ${
                              hasSelected ? 'text-[#112868]' : 'text-[#0e1b2a]'
                            }`}
                          >
                            {resource.replace(/_/g, ' ')}
                          </span>
                          {hasSelected && (
                            <span className="text-xs text-[#112868] bg-[rgba(17,40,104,0.1)] px-2 py-0.5 rounded">
                              Selected
                            </span>
                          )}
                        </div>
                      </button>
                      {isExpanded && (
                        <div className="px-3 pb-3 pt-2 border-t border-[rgba(0,0,0,0.05)]">
                          <div className="flex flex-wrap gap-4">
                            {Array.from(actions).map((action) => {
                              const isChecked = selectedPermissions.some((p) => {
                                // Check for exact match
                                if (p.resource === resource && p.action === action) return true;
                                // Check for wildcard resource with exact action
                                if (p.resource === '*' && p.action === action) return true;
                                // Check for exact resource with wildcard action
                                if (p.resource === resource && p.action === '*') return true;
                                // Check for wildcard resource with wildcard action
                                if (p.resource === '*' && p.action === '*') return true;
                                return false;
                              });
                              return (
                                <label
                                  key={`${resource}-${action}`}
                                  className="flex items-center gap-2 cursor-pointer"
                                >
                                  <input
                                    type="checkbox"
                                    checked={isChecked}
                                    onChange={(e) => handlePermissionChange(resource, action, e.target.checked)}
                                    className="w-4 h-4 text-[#112868] border-[rgba(0,0,0,0.2)] rounded focus:ring-[#112868]/20"
                                  />
                                  <span className="text-sm text-[#0e1b2a] capitalize">{action}</span>
                                </label>
                              );
                            })}
                          </div>
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        </div>
      </form>
    </Modal>
  );
};
