import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
	AlertTriangle,
	BarChart3,
	CheckCircle,
	Download,
	Edit,
	Package,
	Save,
	Server,
	Settings,
	Shield,
	Trash2,
	Users,
	X,
} from "lucide-react";
import { useEffect, useId, useState } from "react";
import { useAuth } from "../../contexts/AuthContext";
import { permissionsAPI } from "../../utils/api";

const RolesTab = () => {
	const [editingRole, setEditingRole] = useState(null);
	const [showAddModal, setShowAddModal] = useState(false);
	const queryClient = useQueryClient();
	const { refreshPermissions } = useAuth();

	// Listen for the header button event to open add modal
	useEffect(() => {
		const handleOpenAddModal = () => setShowAddModal(true);
		window.addEventListener("openAddRoleModal", handleOpenAddModal);
		return () =>
			window.removeEventListener("openAddRoleModal", handleOpenAddModal);
	}, []);

	// Fetch all role permissions
	const {
		data: roles,
		isLoading,
		error,
	} = useQuery({
		queryKey: ["rolePermissions"],
		queryFn: () => permissionsAPI.getRoles().then((res) => res.data),
	});

	// Update role permissions mutation
	const updateRoleMutation = useMutation({
		mutationFn: ({ role, permissions }) =>
			permissionsAPI.updateRole(role, permissions),
		onSuccess: () => {
			queryClient.invalidateQueries(["rolePermissions"]);
			setEditingRole(null);
			// Refresh user permissions to apply changes immediately
			refreshPermissions();
		},
	});

	// Delete role mutation
	const deleteRoleMutation = useMutation({
		mutationFn: (role) => permissionsAPI.deleteRole(role),
		onSuccess: () => {
			queryClient.invalidateQueries(["rolePermissions"]);
		},
	});

	const handleSavePermissions = async (role, permissions) => {
		try {
			await updateRoleMutation.mutateAsync({ role, permissions });
		} catch (error) {
			console.error("Failed to update permissions:", error);
		}
	};

	const handleDeleteRole = async (role) => {
		if (
			window.confirm(
				`Are you sure you want to delete the "${role}" role? This action cannot be undone.`,
			)
		) {
			try {
				await deleteRoleMutation.mutateAsync(role);
			} catch (error) {
				console.error("Failed to delete role:", error);
			}
		}
	};

	if (isLoading) {
		return (
			<div className="flex items-center justify-center h-64">
				<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"></div>
			</div>
		);
	}

	if (error) {
		return (
			<div className="bg-danger-50 border border-danger-200 rounded-md p-4">
				<div className="flex">
					<AlertTriangle className="h-5 w-5 text-danger-400" />
					<div className="ml-3">
						<h3 className="text-sm font-medium text-danger-800">
							Error loading permissions
						</h3>
						<p className="mt-1 text-sm text-danger-700">{error.message}</p>
					</div>
				</div>
			</div>
		);
	}

	return (
		<div className="space-y-6">
			{/* Roles Matrix Table */}
			<div className="bg-white dark:bg-secondary-800 shadow overflow-hidden sm:rounded-lg">
				<div className="overflow-x-auto">
					<table className="min-w-full divide-y divide-secondary-200 dark:divide-secondary-600">
						<thead className="bg-secondary-50 dark:bg-secondary-700">
							<tr>
								<th className="px-6 py-3 text-left text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider">
									Permission
								</th>
								{roles &&
									Array.isArray(roles) &&
									roles.map((r) => (
										<th
											key={r.role}
											className="px-6 py-3 text-left text-xs font-medium text-secondary-500 dark:text-secondary-300 uppercase tracking-wider"
										>
											<div className="flex items-center gap-2">
												<span className="capitalize">
													{r.role.replace(/_/g, " ")}
												</span>
												<button
													type="button"
													onClick={() => setEditingRole(r.role)}
													className="text-secondary-400 hover:text-secondary-600 dark:text-secondary-400 dark:hover:text-secondary-200"
													title="Edit role permissions"
												>
													<Edit className="h-4 w-4" />
												</button>
											</div>
										</th>
									))}
							</tr>
						</thead>
						<tbody className="bg-white dark:bg-secondary-800 divide-y divide-secondary-200 dark:divide-secondary-600">
							{roles &&
								Array.isArray(roles) &&
								roles.length > 0 &&
								Object.keys(roles[0])
									.filter((k) => k.startsWith("can_"))
									.map((permKey) => (
										<tr
											key={permKey}
											className="hover:bg-secondary-50 dark:hover:bg-secondary-700"
										>
											<td className="px-6 py-3 text-sm font-medium text-secondary-700 dark:text-secondary-200 whitespace-nowrap">
												{permKey
													.replace(/^can_/, "")
													.split("_")
													.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
													.join(" ")}
											</td>
											{roles.map((r) => (
												<td
													key={`${r.role}-${permKey}`}
													className="px-6 py-3 whitespace-nowrap"
												>
													{r[permKey] ? (
														<div className="flex items-center text-green-600">
															<CheckCircle className="h-4 w-4" />
														</div>
													) : (
														<div className="flex items-center text-red-600">
															<X className="h-4 w-4" />
														</div>
													)}
												</td>
											))}
										</tr>
									))}
						</tbody>
					</table>
				</div>
			</div>

			{/* Inline editor for selected role */}
			{editingRole && roles && Array.isArray(roles) && (
				<div className="space-y-4">
					{roles
						.filter((r) => r.role === editingRole)
						.map((r) => (
							<RolePermissionsCard
								key={`editor-${r.role}`}
								role={r}
								isEditing={true}
								onEdit={() => {}}
								onCancel={() => setEditingRole(null)}
								onSave={handleSavePermissions}
								onDelete={handleDeleteRole}
							/>
						))}
				</div>
			)}

			{/* Add Role Modal */}
			<AddRoleModal
				isOpen={showAddModal}
				onClose={() => setShowAddModal(false)}
				onSuccess={() => {
					queryClient.invalidateQueries(["rolePermissions"]);
					setShowAddModal(false);
				}}
			/>
		</div>
	);
};

// Role Permissions Card Component
const RolePermissionsCard = ({
	role,
	isEditing,
	onEdit,
	onCancel,
	onSave,
	onDelete,
}) => {
	const [permissions, setPermissions] = useState(role);

	// Sync permissions state with role prop when it changes
	useEffect(() => {
		setPermissions(role);
	}, [role]);

	const permissionFields = [
		{
			key: "can_view_dashboard",
			label: "View Dashboard",
			icon: BarChart3,
			description: "Access to the main dashboard",
		},
		{
			key: "can_view_hosts",
			label: "View Hosts",
			icon: Server,
			description: "See host information and status",
		},
		{
			key: "can_manage_hosts",
			label: "Manage Hosts",
			icon: Edit,
			description: "Add, edit, and delete hosts",
		},
		{
			key: "can_view_packages",
			label: "View Packages",
			icon: Package,
			description: "See package information",
		},
		{
			key: "can_manage_packages",
			label: "Manage Packages",
			icon: Settings,
			description: "Edit package details",
		},
		{
			key: "can_view_users",
			label: "View Users",
			icon: Users,
			description: "See user list and details",
		},
		{
			key: "can_manage_users",
			label: "Manage Users",
			icon: Shield,
			description: "Add, edit, and delete users",
		},
		{
			key: "can_view_reports",
			label: "View Reports",
			icon: BarChart3,
			description: "Access to reports and analytics",
		},
		{
			key: "can_export_data",
			label: "Export Data",
			icon: Download,
			description: "Download data and reports",
		},
		{
			key: "can_manage_settings",
			label: "Manage Settings",
			icon: Settings,
			description: "System configuration access",
		},
	];

	const handlePermissionChange = (key, value) => {
		setPermissions((prev) => ({
			...prev,
			[key]: value,
		}));
	};

	const handleSave = () => {
		onSave(role.role, permissions);
	};

	const isBuiltInRole = role.role === "admin" || role.role === "user";

	return (
		<div className="bg-white dark:bg-secondary-800 shadow rounded-lg">
			<div className="px-6 py-4 border-b border-secondary-200 dark:border-secondary-600">
				<div className="flex items-center justify-between">
					<div className="flex items-center">
						<Shield className="h-5 w-5 text-primary-600 mr-3" />
						<h3 className="text-lg font-medium text-secondary-900 dark:text-white capitalize">
							{role.role}
						</h3>
						{isBuiltInRole && (
							<span className="ml-2 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary-100 text-primary-800">
								Built-in Role
							</span>
						)}
					</div>
					<div className="flex items-center space-x-2">
						{isEditing ? (
							<>
								<button
									type="button"
									onClick={handleSave}
									className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700"
								>
									<Save className="h-4 w-4 mr-1" />
									Save
								</button>
								<button
									type="button"
									onClick={onCancel}
									className="inline-flex items-center px-3 py-1 border border-secondary-300 dark:border-secondary-600 text-sm font-medium rounded-md text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 hover:bg-secondary-50 dark:hover:bg-secondary-600"
								>
									<X className="h-4 w-4 mr-1" />
									Cancel
								</button>
								{!isBuiltInRole && (
									<button
										type="button"
										onClick={() => onDelete(role.role)}
										className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700"
									>
										<Trash2 className="h-4 w-4 mr-1" />
										Delete
									</button>
								)}
							</>
						) : (
							<>
								<button
									type="button"
									onClick={onEdit}
									disabled={isBuiltInRole}
									className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed"
								>
									<Edit className="h-4 w-4 mr-1" />
									Edit
								</button>
								{!isBuiltInRole && (
									<button
										type="button"
										onClick={() => onDelete(role.role)}
										className="inline-flex items-center px-3 py-1 border border-transparent text-sm font-medium rounded-md text-white bg-red-600 hover:bg-red-700"
									>
										<Trash2 className="h-4 w-4 mr-1" />
										Delete
									</button>
								)}
							</>
						)}
					</div>
				</div>
			</div>

			<div className="px-6 py-4">
				<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
					{permissionFields.map((field) => {
						const Icon = field.icon;
						const isChecked = permissions[field.key];

						return (
							<div key={field.key} className="flex items-start">
								<div className="flex items-center h-5">
									<input
										id={`${role.role}-${field.key}`}
										type="checkbox"
										checked={isChecked}
										onChange={(e) =>
											handlePermissionChange(field.key, e.target.checked)
										}
										disabled={
											!isEditing ||
											(isBuiltInRole && field.key === "can_manage_users")
										}
										className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 rounded disabled:opacity-50"
									/>
								</div>
								<div className="ml-3">
									<div className="flex items-center">
										<Icon className="h-4 w-4 text-secondary-400 mr-2" />
										<label
											htmlFor={`${role.role}-${field.key}`}
											className="text-sm font-medium text-secondary-900 dark:text-white"
										>
											{field.label}
										</label>
									</div>
									<p className="text-xs text-secondary-500 mt-1">
										{field.description}
									</p>
								</div>
							</div>
						);
					})}
				</div>
			</div>
		</div>
	);
};

// Add Role Modal Component
const AddRoleModal = ({ isOpen, onClose, onSuccess }) => {
	const roleNameInputId = useId();
	const [formData, setFormData] = useState({
		role: "",
		can_view_dashboard: true,
		can_view_hosts: true,
		can_manage_hosts: false,
		can_view_packages: true,
		can_manage_packages: false,
		can_view_users: false,
		can_manage_users: false,
		can_view_reports: true,
		can_export_data: false,
		can_manage_settings: false,
	});
	const [isLoading, setIsLoading] = useState(false);
	const [error, setError] = useState("");

	const handleSubmit = async (e) => {
		e.preventDefault();
		setIsLoading(true);
		setError("");

		try {
			await permissionsAPI.updateRole(formData.role, formData);
			onSuccess();
		} catch (err) {
			setError(err.response?.data?.error || "Failed to create role");
		} finally {
			setIsLoading(false);
		}
	};

	const handleInputChange = (e) => {
		const { name, value, type, checked } = e.target;
		setFormData({
			...formData,
			[name]: type === "checkbox" ? checked : value,
		});
	};

	if (!isOpen) return null;

	return (
		<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
			<div className="bg-white dark:bg-secondary-800 rounded-lg p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
				<h3 className="text-lg font-medium text-secondary-900 dark:text-white mb-4">
					Add New Role
				</h3>

				<form onSubmit={handleSubmit} className="space-y-4">
					<div>
						<label
							htmlFor={roleNameInputId}
							className="block text-sm font-medium text-secondary-700 dark:text-secondary-200 mb-1"
						>
							Role Name
						</label>
						<input
							id={roleNameInputId}
							type="text"
							name="role"
							required
							value={formData.role}
							onChange={handleInputChange}
							className="block w-full border-secondary-300 dark:border-secondary-600 rounded-md shadow-sm focus:ring-primary-500 focus:border-primary-500 bg-white dark:bg-secondary-700 text-secondary-900 dark:text-white"
							placeholder="e.g., host_manager, readonly"
						/>
						<p className="mt-1 text-xs text-secondary-500 dark:text-secondary-400">
							Use lowercase with underscores (e.g., host_manager)
						</p>
					</div>

					<div className="space-y-3">
						<h4 className="text-sm font-medium text-secondary-900 dark:text-white">
							Permissions
						</h4>
						{[
							{ key: "can_view_dashboard", label: "View Dashboard" },
							{ key: "can_view_hosts", label: "View Hosts" },
							{ key: "can_manage_hosts", label: "Manage Hosts" },
							{ key: "can_view_packages", label: "View Packages" },
							{ key: "can_manage_packages", label: "Manage Packages" },
							{ key: "can_view_users", label: "View Users" },
							{ key: "can_manage_users", label: "Manage Users" },
							{ key: "can_view_reports", label: "View Reports" },
							{ key: "can_export_data", label: "Export Data" },
							{ key: "can_manage_settings", label: "Manage Settings" },
						].map((permission) => (
							<div key={permission.key} className="flex items-center">
								<input
									id={`add-role-${permission.key}`}
									type="checkbox"
									name={permission.key}
									checked={formData[permission.key]}
									onChange={handleInputChange}
									className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-secondary-300 rounded"
								/>
								<label
									htmlFor={`add-role-${permission.key}`}
									className="ml-2 block text-sm text-secondary-700 dark:text-secondary-200"
								>
									{permission.label}
								</label>
							</div>
						))}
					</div>

					{error && (
						<div className="bg-danger-50 dark:bg-danger-900 border border-danger-200 dark:border-danger-700 rounded-md p-3">
							<p className="text-sm text-danger-700 dark:text-danger-300">
								{error}
							</p>
						</div>
					)}

					<div className="flex justify-end space-x-3">
						<button
							type="button"
							onClick={onClose}
							className="px-4 py-2 text-sm font-medium text-secondary-700 dark:text-secondary-200 bg-white dark:bg-secondary-700 border border-secondary-300 dark:border-secondary-600 rounded-md hover:bg-secondary-50 dark:hover:bg-secondary-600"
						>
							Cancel
						</button>
						<button
							type="submit"
							disabled={isLoading}
							className="px-4 py-2 text-sm font-medium text-white bg-primary-600 border border-transparent rounded-md hover:bg-primary-700 disabled:opacity-50"
						>
							{isLoading ? "Creating..." : "Create Role"}
						</button>
					</div>
				</form>
			</div>
		</div>
	);
};

export default RolesTab;
