/**
 * Staff Roles Settings Page
 *
 * Create and manage staff roles with granular permissions.
 * Roles control what menu items and features are accessible to staff members.
 */

import React, { useState, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useOutletContext } from 'react-router-dom';
import { Shield, Plus, X, Pencil, Trash2, Users, Lock, Check, GripVertical } from 'lucide-react';
import { Business, User, StaffRole } from '../../types';
import {
  useStaffRoles,
  useAvailablePermissions,
  useCreateStaffRole,
  useUpdateStaffRole,
  useDeleteStaffRole,
  useReorderStaffRoles,
} from '../../hooks/useStaffRoles';
import { RolePermissionsEditor } from '../../components/staff/RolePermissions';

const StaffRolesSettings: React.FC = () => {
  const { t } = useTranslation();
  const { user } = useOutletContext<{
    business: Business;
    user: User;
  }>();

  const { data: staffRoles = [], isLoading } = useStaffRoles();
  const { data: availablePermissions } = useAvailablePermissions();
  const createStaffRole = useCreateStaffRole();
  const updateStaffRole = useUpdateStaffRole();
  const deleteStaffRole = useDeleteStaffRole();
  const reorderStaffRoles = useReorderStaffRoles();

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [draggedRoleId, setDraggedRoleId] = useState<number | null>(null);
  const [dragOverRoleId, setDragOverRoleId] = useState<number | null>(null);
  const draggedRef = useRef<number | null>(null);
  const [editingRole, setEditingRole] = useState<StaffRole | null>(null);
  const [formData, setFormData] = useState({
    name: '',
    description: '',
    permissions: {} as Record<string, boolean>,
  });
  const [error, setError] = useState<string | null>(null);

  const isOwner = user.role === 'owner';
  // Only owners can manage roles (staff with permissions can view but not edit)
  const canManageRoles = isOwner;

  // Merge menu, settings, and dangerous permissions for display
  const allPermissions = useMemo(() => {
    if (!availablePermissions) return { menu: {}, settings: {}, dangerous: {} };
    return {
      menu: availablePermissions.menu_permissions || {},
      settings: availablePermissions.settings_permissions || {},
      dangerous: availablePermissions.dangerous_permissions || {},
    };
  }, [availablePermissions]);

  const openCreateModal = () => {
    setEditingRole(null);
    setFormData({
      name: '',
      description: '',
      permissions: {},
    });
    setError(null);
    setIsModalOpen(true);
  };

  const openEditModal = (role: StaffRole) => {
    setEditingRole(role);
    setFormData({
      name: role.name,
      description: role.description || '',
      permissions: { ...role.permissions },
    });
    setError(null);
    setIsModalOpen(true);
  };

  const closeModal = () => {
    setIsModalOpen(false);
    setEditingRole(null);
    setError(null);
  };

  const handlePermissionsChange = (newPermissions: Record<string, boolean>) => {
    setFormData((prev) => ({
      ...prev,
      permissions: newPermissions,
    }));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    try {
      if (editingRole) {
        await updateStaffRole.mutateAsync({
          id: editingRole.id,
          name: formData.name,
          description: formData.description,
          permissions: formData.permissions,
        });
      } else {
        await createStaffRole.mutateAsync({
          name: formData.name,
          description: formData.description,
          permissions: formData.permissions,
        });
      }
      closeModal();
    } catch (err: any) {
      const message = err.response?.data?.error || err.response?.data?.name?.[0] || 'Failed to save role';
      setError(message);
    }
  };

  const handleDelete = async (role: StaffRole) => {
    if (!role.can_delete) {
      alert(
        role.is_default
          ? t('settings.staffRoles.cannotDeleteDefault', 'Default roles cannot be deleted.')
          : t('settings.staffRoles.cannotDeleteInUse', 'Remove all staff from this role before deleting.')
      );
      return;
    }

    if (window.confirm(t('settings.staffRoles.confirmDelete', `Are you sure you want to delete the "${role.name}" role?`))) {
      try {
        await deleteStaffRole.mutateAsync(role.id);
      } catch (err: any) {
        alert(err.response?.data?.error || 'Failed to delete role');
      }
    }
  };

  const countEnabledPermissions = (permissions: Record<string, boolean>) => {
    return Object.values(permissions).filter(Boolean).length;
  };

  // Drag and drop handlers
  const handleDragStart = (e: React.DragEvent, roleId: number) => {
    e.dataTransfer.setData('text/plain', String(roleId));
    e.dataTransfer.effectAllowed = 'move';
    draggedRef.current = roleId;
    setDraggedRoleId(roleId);
  };

  const handleDragEnd = () => {
    setDraggedRoleId(null);
    setDragOverRoleId(null);
    draggedRef.current = null;
  };

  const handleDragOver = (e: React.DragEvent, roleId: number) => {
    e.preventDefault();
    e.stopPropagation();
    e.dataTransfer.dropEffect = 'move';
    if (draggedRef.current && draggedRef.current !== roleId) {
      setDragOverRoleId(roleId);
    }
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDragOverRoleId(null);
  };

  const handleDrop = async (e: React.DragEvent, targetRoleId: number) => {
    e.preventDefault();
    e.stopPropagation();

    const draggedId = draggedRef.current;
    setDragOverRoleId(null);

    if (!draggedId || draggedId === targetRoleId) {
      return;
    }

    // Reorder the roles
    const currentOrder = staffRoles.map(r => r.id);
    const draggedIndex = currentOrder.indexOf(draggedId);
    const targetIndex = currentOrder.indexOf(targetRoleId);

    if (draggedIndex === -1 || targetIndex === -1) {
      return;
    }

    // Remove dragged item and insert at target position
    const newOrder = [...currentOrder];
    newOrder.splice(draggedIndex, 1);
    newOrder.splice(targetIndex, 0, draggedId);

    try {
      await reorderStaffRoles.mutateAsync(newOrder);
    } catch (err) {
      // Silently fail - the UI will remain unchanged
    }
  };

  if (!canManageRoles) {
    return (
      <div className="text-center py-12">
        <Shield size={48} className="mx-auto mb-4 text-gray-300 dark:text-gray-600" />
        <p className="text-gray-500 dark:text-gray-400">
          {t('settings.staffRoles.noAccess', 'Only the business owner can manage staff roles.')}
        </p>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div>
        <h2 className="text-2xl font-bold text-gray-900 dark:text-white flex items-center gap-3">
          <Shield className="text-indigo-500" />
          {t('settings.staffRoles.title', 'Staff Roles')}
        </h2>
        <p className="text-gray-500 dark:text-gray-400 mt-1">
          {t('settings.staffRoles.subtitle', 'Create roles to control what staff members can access in your business.')}
        </p>
      </div>

      {/* Roles List */}
      <section className="bg-white dark:bg-gray-800 p-6 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm">
        <div className="flex items-center justify-between mb-6">
          <div>
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              {t('settings.staffRoles.yourRoles', 'Your Staff Roles')}
            </h3>
            <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
              {t('settings.staffRoles.rolesDescription', 'Assign staff members to roles to control their permissions.')}
            </p>
          </div>
          <button
            onClick={openCreateModal}
            className="flex items-center gap-2 px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 transition-colors font-medium text-sm"
          >
            <Plus size={16} />
            {t('settings.staffRoles.createRole', 'Create Role')}
          </button>
        </div>

        {isLoading ? (
          <div className="flex items-center justify-center py-8">
            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-brand-600"></div>
          </div>
        ) : staffRoles.length === 0 ? (
          <div className="text-center py-8 text-gray-500 dark:text-gray-400">
            <Shield size={40} className="mx-auto mb-2 opacity-30" />
            <p>{t('settings.staffRoles.noRoles', 'No staff roles configured.')}</p>
            <p className="text-sm mt-1">{t('settings.staffRoles.createFirst', 'Create your first role to manage staff permissions.')}</p>
          </div>
        ) : (
          <div
            className="space-y-3"
            onDragOver={(e) => e.preventDefault()}
          >
            {staffRoles.map((role) => (
              <div
                key={role.id}
                draggable="true"
                onDragStart={(e) => handleDragStart(e, role.id)}
                onDragEnd={handleDragEnd}
                onDragOver={(e) => handleDragOver(e, role.id)}
                onDragLeave={(e) => handleDragLeave(e)}
                onDrop={(e) => handleDrop(e, role.id)}
                className={`p-4 bg-gray-50 dark:bg-gray-900/50 rounded-lg border transition-all select-none ${
                  dragOverRoleId === role.id
                    ? 'border-brand-500 border-2 bg-brand-50 dark:bg-brand-900/20'
                    : draggedRoleId === role.id
                    ? 'border-gray-300 dark:border-gray-600 opacity-50'
                    : 'border-gray-200 dark:border-gray-700'
                }`}
              >
                <div className="flex items-start justify-between">
                  <div className="flex items-start gap-3 flex-1 min-w-0">
                    {/* Drag Handle */}
                    <div
                      className="w-6 h-10 flex items-center justify-center shrink-0 cursor-grab active:cursor-grabbing text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 touch-none"
                      title={t('settings.staffRoles.dragToReorder', 'Drag to reorder')}
                    >
                      <GripVertical size={18} />
                    </div>
                    <div className={`w-10 h-10 rounded-lg flex items-center justify-center shrink-0 ${
                      role.is_default
                        ? 'bg-indigo-100 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400'
                        : 'bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400'
                    }`}>
                      <Shield size={20} />
                    </div>
                    <div className="flex-1 min-w-0">
                      <h4 className="font-medium text-gray-900 dark:text-white flex items-center gap-2 flex-wrap">
                        {role.name}
                        {role.is_default && (
                          <span className="px-1.5 py-0.5 text-[10px] font-medium bg-indigo-100 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400 rounded">
                            {t('common.default', 'Default')}
                          </span>
                        )}
                      </h4>
                      <p className="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-3 mt-0.5">
                        <span className="flex items-center gap-1">
                          <Users size={14} />
                          {t('settings.staffRoles.staffAssigned', '{{count}} staff', { count: role.staff_count })}
                        </span>
                        <span className="flex items-center gap-1">
                          <Check size={14} />
                          {t('settings.staffRoles.permissionsEnabled', '{{count}} permissions', {
                            count: countEnabledPermissions(role.permissions),
                          })}
                        </span>
                      </p>
                      {role.description && (
                        <p className="text-sm text-gray-600 dark:text-gray-300 mt-1 line-clamp-2">
                          {role.description}
                        </p>
                      )}
                    </div>
                  </div>
                  <div className="flex items-center gap-2 shrink-0 ml-2" onDragStart={(e) => e.preventDefault()}>
                    <button
                      onClick={() => openEditModal(role)}
                      draggable="false"
                      className="p-2 text-gray-400 hover:text-brand-600 dark:hover:text-brand-400 transition-colors"
                      title={t('common.edit', 'Edit')}
                    >
                      <Pencil size={16} />
                    </button>
                    <button
                      onClick={() => handleDelete(role)}
                      draggable="false"
                      disabled={deleteStaffRole.isPending || !role.can_delete}
                      className={`p-2 transition-colors disabled:opacity-50 ${
                        role.can_delete
                          ? 'text-gray-400 hover:text-red-600 dark:hover:text-red-400'
                          : 'text-gray-300 dark:text-gray-600 cursor-not-allowed'
                      }`}
                      title={
                        role.is_default
                          ? t('settings.staffRoles.cannotDeleteDefault', 'Default roles cannot be deleted')
                          : role.staff_count > 0
                          ? t('settings.staffRoles.cannotDeleteInUse', 'Remove all staff first')
                          : t('common.delete', 'Delete')
                      }
                    >
                      {role.can_delete ? <Trash2 size={16} /> : <Lock size={16} />}
                    </button>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </section>

      {/* Create/Edit Modal */}
      {isModalOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white dark:bg-gray-800 rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-hidden flex flex-col">
            <div className="flex items-center justify-between p-6 border-b border-gray-100 dark:border-gray-700 shrink-0">
              <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
                {editingRole
                  ? t('settings.staffRoles.editRole', 'Edit Role')
                  : t('settings.staffRoles.createRole', 'Create Role')}
              </h3>
              <button
                onClick={closeModal}
                className="p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
              >
                <X className="h-5 w-5" />
              </button>
            </div>

            <form onSubmit={handleSubmit} className="flex-1 overflow-y-auto">
              <div className="p-6 space-y-6">
                {error && (
                  <div className="p-3 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm">
                    {error}
                  </div>
                )}

                {/* Basic Info */}
                <div className="space-y-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                      {t('settings.staffRoles.roleName', 'Role Name')} *
                    </label>
                    <input
                      type="text"
                      value={formData.name}
                      onChange={(e) => setFormData({ ...formData, name: e.target.value })}
                      required
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-500 focus:border-brand-500"
                      placeholder={t('settings.staffRoles.roleNamePlaceholder', 'e.g., Front Desk, Senior Stylist')}
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
                      {t('settings.staffRoles.roleDescription', 'Description')}
                    </label>
                    <textarea
                      value={formData.description}
                      onChange={(e) => setFormData({ ...formData, description: e.target.value })}
                      rows={2}
                      className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-500 focus:border-brand-500 resize-none"
                      placeholder={t('settings.staffRoles.roleDescriptionPlaceholder', 'Describe what this role can do...')}
                    />
                  </div>
                </div>

                {/* Permissions Editor */}
                <RolePermissionsEditor
                  permissions={formData.permissions}
                  onChange={handlePermissionsChange}
                  availablePermissions={allPermissions}
                />
              </div>

              <div className="flex justify-end gap-3 p-6 border-t border-gray-100 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/50 shrink-0">
                <button
                  type="button"
                  onClick={closeModal}
                  className="px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded-lg transition-colors"
                >
                  {t('common.cancel', 'Cancel')}
                </button>
                <button
                  type="submit"
                  disabled={createStaffRole.isPending || updateStaffRole.isPending}
                  className="px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
                >
                  {editingRole ? t('common.save', 'Save') : t('common.create', 'Create')}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}
    </div>
  );
};

export default StaffRolesSettings;
