// \src\components\admin\roles\RoleForm.tsx

'use client';

import { useState, useEffect, useMemo, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import toast from 'react-hot-toast';
import { getApiErrorMessage } from '@/lib/utils/apiError';

// ─── Types ────────────────────────────────────────────────────────────────────

interface Permission {
  id: string;
  name: string;
  description: string | null;
  module: string;
  action: string;
}

interface RoleData {
  id: string;
  name: string;
  label: string;
  description: string | null;
  is_system?: boolean;
  is_active?: boolean;
  permissions?: Permission[];
  created_at?: string;
  employee_count?: number;
}

interface RoleFormProps {
  mode: 'create' | 'edit';
  initialData?: RoleData | null;
}

// ─── Pure helpers (module-level — never recreated on render) ──────────────────

function getModuleDisplayName(module: string): string {
  return module.charAt(0).toUpperCase() + module.slice(1);
}

function getActionDisplayName(action: string): string {
  const name = action.replace(/_/g, ' ');
  return `Can ${name.charAt(0).toUpperCase() + name.slice(1)}`;
}

// ─── Shared styles (module-level constants) ───────────────────────────────────

const INPUT_STYLE = {
  background: 'var(--color-surface-alt)',
  border: '1px solid var(--color-border)',
  color: 'var(--color-text)',
} as const;

const LABEL_STYLE  = { color: 'var(--color-text-secondary)'  } as const;
const ERROR_STYLE  = { color: 'var(--color-danger)'           } as const;

// ─── Component ────────────────────────────────────────────────────────────────

export default function RoleForm({ mode, initialData }: RoleFormProps) {
  const router    = useRouter();
  const isEditing = mode === 'edit';

  // Stable ID so the fetch effect doesn't re-run when parent re-renders
  // and passes a structurally equal but referentially different object.
  const roleId = initialData?.id;

  const [formData, setFormData] = useState({
    name:        initialData?.name        || '',
    label:       initialData?.label       || '',
    description: initialData?.description || '',
    is_system:   initialData?.is_system   || false,
    is_active:   initialData?.is_active   !== undefined ? initialData.is_active : true,
  });

  const [selectedPermissions, setSelectedPermissions] = useState<Set<string>>(new Set());
  const [allPermissions,      setAllPermissions]      = useState<Permission[]>([]);
  const [loading,             setLoading]             = useState(false);
  const [loadingPermissions,  setLoadingPermissions]  = useState(true);
  const [errors,              setErrors]              = useState<Record<string, string>>({});

  // ── Derived state (memoized — not recomputed on every render) ─────────────
  const groupedPermissions = useMemo(
    () =>
      allPermissions.reduce<Record<string, Permission[]>>((acc, p) => {
        (acc[p.module] ??= []).push(p);
        return acc;
      }, {}),
    [allPermissions],
  );

  // ── Fetch permissions on mount (and when role ID changes in edit mode) ────
  useEffect(() => {
    let cancelled = false;

    async function fetchData() {
      setLoadingPermissions(true);
      try {
        const requests: Promise<Response | null>[] = [
          fetch('/api/roles/permissions'),
          isEditing && roleId ? fetch(`/api/roles/${roleId}/permissions`) : Promise.resolve(null),
        ];

        const [permRes, rolePermRes] = await Promise.all(requests);

        if (cancelled) return;

        if (permRes?.ok) {
          const d = await permRes.json();
          setAllPermissions(d.data || []);
        }

        if (isEditing && rolePermRes?.ok) {
          const d = await rolePermRes.json();
          setSelectedPermissions(new Set<string>(d.data.map((p: Permission) => p.id)));
        }
      } catch (err) {
        if (cancelled) return;
        console.error('Failed to fetch permissions:', err);
        toast.error('Failed to load permissions');
      } finally {
        if (!cancelled) setLoadingPermissions(false);
      }
    }

    fetchData();
    return () => { cancelled = true; };
  }, [isEditing, roleId]); // ← stable primitive instead of object reference

  // ── Field change ──────────────────────────────────────────────────────────
  const handleChange = useCallback((field: string, value: string | boolean) => {
    setFormData(prev => ({ ...prev, [field]: value }));
    setErrors(prev => (prev[field] ? { ...prev, [field]: '' } : prev));
  }, []);

  // ── Permission toggles ────────────────────────────────────────────────────
  const handlePermissionToggle = useCallback((id: string) => {
    setSelectedPermissions(prev => {
      const next = new Set(prev);
      if (next.has(id)) { next.delete(id); } else { next.add(id); }
      return next;
    });
  }, []);

  // Single handler used by both the checkbox column header and the text button
  const handleModuleToggle = useCallback((moduleName: string) => {
    const modulePermissions = groupedPermissions[moduleName] || [];
    const allSelected = modulePermissions.every(p => selectedPermissions.has(p.id));

    setSelectedPermissions(prev => {
      const next = new Set(prev);
      modulePermissions.forEach(p => {
        if (allSelected) { next.delete(p.id); } else { next.add(p.id); }
      });
      return next;
    });
  }, [groupedPermissions, selectedPermissions]);

  const handleSelectAll = useCallback(() => {
    setSelectedPermissions(new Set(allPermissions.map(p => p.id)));
    toast.success(`All ${allPermissions.length} permissions selected`);
  }, [allPermissions]);

  const handleClearAll = useCallback(() => {
    setSelectedPermissions(new Set());
    toast.success('All permissions cleared');
  }, []);

  // ── Module selection state helpers ────────────────────────────────────────
  const isModuleFullySelected = useCallback((moduleName: string) => {
    const perms = groupedPermissions[moduleName] || [];
    return perms.length > 0 && perms.every(p => selectedPermissions.has(p.id));
  }, [groupedPermissions, selectedPermissions]);

  const isModulePartiallySelected = useCallback((moduleName: string) => {
    const perms = groupedPermissions[moduleName] || [];
    const count = perms.filter(p => selectedPermissions.has(p.id)).length;
    return count > 0 && count < perms.length;
  }, [groupedPermissions, selectedPermissions]);

  // ── Submit ────────────────────────────────────────────────────────────────
  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setErrors({});
    setLoading(true);

    try {
      const url    = isEditing ? `/api/roles/${roleId}` : '/api/roles';
      const method = isEditing ? 'PUT' : 'POST';

      const res  = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...formData, permissionIds: [...selectedPermissions] }),
      });
      const data = await res.json();

      if (!res.ok || !data.success) {
        if (data.errors) {
          const fieldErrors: Record<string, string> = {};
          if (Array.isArray(data.errors)) {
            data.errors.forEach((err: { path: string[]; message: string }) => {
              if (err.path?.[0]) fieldErrors[err.path[0]] = err.message;
            });
          }
          setErrors(fieldErrors);
          toast.error('Please fix the validation errors');
        } else {
          toast.error(getApiErrorMessage(data, 'Failed to save role'));
        }
        return;
      }

      toast.success(data.message || (isEditing ? 'Role updated successfully' : 'Role created successfully'));
      router.push('/admin/dashboard/employees/roles');
      router.refresh();
    } catch (err) {
      console.error('[RoleForm]', err);
      toast.error('Network error — please try again');
    } finally {
      setLoading(false);
    }
  }

  // ── Render ────────────────────────────────────────────────────────────────
  return (
    <div className="p-6 md:p-8" style={{
      background:   'var(--color-surface)',
      border:       '1px solid var(--color-border)',
      borderRadius: 'var(--radius-card)',
      boxShadow:    'var(--shadow-card-md)',
      maxWidth:     '1200px',
      width:        '100%',
    }}>
      <form onSubmit={handleSubmit}>
        <div className="space-y-6">

          {/* Role Name + Display Name */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label htmlFor="name" className="block text-sm font-medium mb-1.5" style={LABEL_STYLE}>
                Role Name (System) <span className="text-red-500">*</span>
              </label>
              <input
                id="name"
                type="text"
                required
                value={formData.name}
                onChange={(e) => handleChange('name', e.target.value)}
                placeholder="e.g., admin, manager, staff"
                className={`w-full px-4 py-2.5 rounded-lg text-sm outline-none transition-all focus:ring-2 focus:ring-cta/20 ${errors.name ? 'border-red-500' : ''}`}
                style={INPUT_STYLE}
              />
              <p className="text-xs mt-1" style={{ color: 'var(--color-text-tertiary)' }}>
                System identifier (lowercase, use hyphens for spaces)
              </p>
              {errors.name && <p className="text-xs mt-1" style={ERROR_STYLE}>{errors.name}</p>}
            </div>

            <div>
              <label htmlFor="label" className="block text-sm font-medium mb-1.5" style={LABEL_STYLE}>
                Display Name <span className="text-red-500">*</span>
              </label>
              <input
                id="label"
                type="text"
                required
                value={formData.label}
                onChange={(e) => handleChange('label', e.target.value)}
                placeholder="e.g., Administrator, Manager"
                className={`w-full px-4 py-2.5 rounded-lg text-sm outline-none transition-all focus:ring-2 focus:ring-cta/20 ${errors.label ? 'border-red-500' : ''}`}
                style={INPUT_STYLE}
              />
              <p className="text-xs mt-1" style={{ color: 'var(--color-text-tertiary)' }}>
                Human-readable display name
              </p>
              {errors.label && <p className="text-xs mt-1" style={ERROR_STYLE}>{errors.label}</p>}
            </div>
          </div>

          {/* Description */}
          <div>
            <label htmlFor="description" className="block text-sm font-medium mb-1.5" style={LABEL_STYLE}>
              Description
            </label>
            <textarea
              id="description"
              rows={3}
              value={formData.description || ''}
              onChange={(e) => handleChange('description', e.target.value)}
              placeholder="What does this role do?"
              className="w-full px-4 py-2.5 rounded-lg text-sm outline-none transition-all focus:ring-2 focus:ring-cta/20 resize-none"
              style={INPUT_STYLE}
            />
          </div>

          {/* Status Toggles */}
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label className="block text-sm font-medium mb-1.5" style={LABEL_STYLE}>
                System Role
              </label>
              <div className="flex items-center gap-3">
                <button
                  type="button"
                  onClick={() => handleChange('is_system', !formData.is_system)}
                  className="px-4 py-2 rounded-lg text-sm font-medium transition-all"
                  style={{
                    background: formData.is_system ? 'var(--color-warning)' : 'var(--color-surface-alt)',
                    border:     formData.is_system ? 'none' : '1px solid var(--color-border)',
                    color:      formData.is_system ? 'white' : 'var(--color-text-secondary)',
                  }}
                >
                  {formData.is_system ? '✅ System Role' : '❌ Not System'}
                </button>
                <span className="text-xs" style={{ color: 'var(--color-text-tertiary)' }}>
                  System roles cannot be deleted
                </span>
              </div>
            </div>

            <div>
              <label className="block text-sm font-medium mb-1.5" style={LABEL_STYLE}>
                Active Status
              </label>
              <div className="flex items-center gap-3">
                <button
                  type="button"
                  onClick={() => handleChange('is_active', !formData.is_active)}
                  className="px-4 py-2 rounded-lg text-sm font-medium transition-all"
                  style={{
                    background: formData.is_active ? 'var(--color-success)' : 'var(--color-surface-alt)',
                    border:     formData.is_active ? 'none' : '1px solid var(--color-border)',
                    color:      formData.is_active ? 'white' : 'var(--color-text-secondary)',
                  }}
                >
                  {formData.is_active ? '✅ Active' : '❌ Inactive'}
                </button>
                <span className="text-xs" style={{ color: 'var(--color-text-tertiary)' }}>
                  Inactive roles cannot be assigned
                </span>
              </div>
            </div>
          </div>

          {/* Permissions */}
          <div>
            <div className="flex justify-between items-center mb-4">
              <label className="text-sm font-medium" style={LABEL_STYLE}>
                Permissions
              </label>
              <div className="flex gap-2">
                <button
                  type="button"
                  onClick={handleSelectAll}
                  className="px-3 py-1.5 text-xs font-medium rounded-lg transition-all hover:opacity-80"
                  style={{
                    background: 'var(--color-cta-light)',
                    color:      'var(--color-cta)',
                    border:     '1px solid var(--color-border)',
                  }}
                >
                  ✓ Select All ({allPermissions.length})
                </button>
                <button
                  type="button"
                  onClick={handleClearAll}
                  className="px-3 py-1.5 text-xs font-medium rounded-lg transition-all hover:opacity-80"
                  style={{
                    background: 'var(--color-surface-alt)',
                    color:      'var(--color-danger)',
                    border:     '1px solid var(--color-border)',
                  }}
                >
                  ✗ Clear All
                </button>
              </div>
            </div>

            <div className="mb-4">
              <span className="text-xs px-2 py-1 rounded-full" style={{
                background: 'var(--color-cta-light)',
                color:      'var(--color-cta)',
              }}>
                {selectedPermissions.size} / {allPermissions.length} permissions selected
              </span>
            </div>

            {loadingPermissions ? (
              <div className="space-y-4">
                {[1, 2, 3].map((i) => (
                  <div key={i} className="rounded-lg p-4 animate-pulse" style={{ background: 'var(--color-surface-alt)' }}>
                    <div className="h-6 w-32 rounded mb-3" style={{ background: 'var(--color-border)' }} />
                    <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
                      {[1, 2, 3, 4].map((j) => (
                        <div key={j} className="h-8 rounded" style={{ background: 'var(--color-border)' }} />
                      ))}
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="space-y-4">
                {Object.entries(groupedPermissions).map(([moduleName, permissions]) => (
                  <div
                    key={moduleName}
                    className="rounded-lg overflow-hidden"
                    style={{
                      background: 'var(--color-surface-alt)',
                      border:     '1px solid var(--color-border)',
                    }}
                  >
                    {/* Module Header */}
                    <div
                      className="flex items-center justify-between px-4 py-3"
                      style={{
                        background:   'var(--color-surface)',
                        borderBottom: '1px solid var(--color-border)',
                      }}
                    >
                      <div className="flex items-center gap-3">
                        {/* Checkbox icon — clicking toggles entire module */}
                        <button
                          type="button"
                          onClick={() => handleModuleToggle(moduleName)}
                          className="flex items-center gap-2 text-sm font-semibold hover:opacity-70 transition-opacity"
                          style={{ color: 'var(--color-text)' }}
                        >
                          {isModuleFullySelected(moduleName) ? (
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <rect x="3" y="3" width="18" height="18" rx="2" fill="var(--color-cta)" stroke="var(--color-cta)"/>
                              <polyline points="9 12 11 14 15 10" stroke="white" strokeWidth="2"/>
                            </svg>
                          ) : isModulePartiallySelected(moduleName) ? (
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor"/>
                              <line x1="8" y1="12" x2="16" y2="12" stroke="currentColor" strokeWidth="2"/>
                            </svg>
                          ) : (
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                              <rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor"/>
                            </svg>
                          )}
                          <span>{getModuleDisplayName(moduleName)}</span>
                        </button>

                        <span className="text-xs px-2 py-0.5 rounded-full" style={{
                          background: 'var(--color-surface-alt)',
                          color:      'var(--color-text-tertiary)',
                        }}>
                          {permissions.length} permissions
                        </span>
                      </div>

                      {/* FIX: was inline logic duplicating handleModuleToggle — now reuses it */}
                      <button
                        type="button"
                        onClick={() => handleModuleToggle(moduleName)}
                        className="text-xs px-2 py-1 rounded transition-all hover:opacity-70"
                        style={{ color: 'var(--color-cta)' }}
                      >
                        {isModuleFullySelected(moduleName) ? 'Clear' : 'Select All'}
                      </button>
                    </div>

                    {/* Permissions Grid */}
                    <div className="p-4">
                      <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2">
                        {permissions.map((permission) => (
                          <label
                            key={permission.id}
                            className="flex items-center gap-2 text-sm cursor-pointer hover:opacity-70 transition-opacity px-3 py-2 rounded-lg"
                            style={{
                              color:      'var(--color-text-secondary)',
                              background: selectedPermissions.has(permission.id)
                                ? 'var(--color-cta-light)'
                                : 'transparent',
                            }}
                          >
                            <input
                              type="checkbox"
                              checked={selectedPermissions.has(permission.id)}
                              onChange={() => handlePermissionToggle(permission.id)}
                              className="rounded focus:ring-cta/20 w-4 h-4"
                              style={{ accentColor: 'var(--color-cta)' }}
                            />
                            <span>{getActionDisplayName(permission.action)}</span>
                          </label>
                        ))}
                      </div>
                    </div>
                  </div>
                ))}

                {Object.keys(groupedPermissions).length === 0 && (
                  <div className="text-center py-8 rounded-lg" style={{
                    background: 'var(--color-surface-alt)',
                    border:     '1px solid var(--color-border)',
                  }}>
                    <p className="text-sm" style={{ color: 'var(--color-text-muted)' }}>
                      No permissions available. Please create permissions first.
                    </p>
                  </div>
                )}
              </div>
            )}
          </div>

          {/* Form Actions */}
          <div className="flex gap-3 pt-4 border-t" style={{ borderColor: 'var(--color-border)' }}>
            <button
              type="submit"
              disabled={loading}
              className="px-6 py-2.5 rounded-lg text-sm font-medium transition-all disabled:opacity-50 hover:opacity-90"
              style={{ background: 'var(--color-cta)', color: 'white' }}
            >
              {loading ? (
                <span className="flex items-center gap-2">
                  <svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
                    <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none"/>
                    <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
                  </svg>
                  Saving...
                </span>
              ) : (isEditing ? 'Update Role' : 'Create Role')}
            </button>
            <button
              type="button"
              onClick={() => router.back()}
              className="px-6 py-2.5 rounded-lg text-sm font-medium transition-all hover:opacity-80"
              style={{
                background: 'var(--color-surface-alt)',
                color:      'var(--color-text)',
                border:     '1px solid var(--color-border)',
              }}
            >
              Cancel
            </button>
          </div>

        </div>
      </form>
    </div>
  );
}