<script lang="ts">
	import { rolesAPI, type CompanyRole } from '$lib/api/dashboard/admin/roles';
	import {
		rolePermissionsAPI,
		type RolePermission
	} from '$lib/api/dashboard/admin/role-permissions';
	import { permissionsAPI, type Permission } from '$lib/api/dashboard/admin/permissions';
	import { companyStore } from '$lib/stores/company.svelte';
	import { Button } from '$lib/components/ui/button';
	import { Input } from '$lib/components/ui/input';
	import { Textarea } from '$lib/components/ui/textarea';
	import { Switch } from '$lib/components/ui/switch';
	import {
		Table,
		TableBody,
		TableCell,
		TableHead,
		TableHeader,
		TableRow
	} from '$lib/components/ui/table';
	import * as Dialog from '$lib/components/ui/dialog';
	import { Label } from '$lib/components/ui/label';
	import {
		Select,
		SelectContent,
		SelectItem,
		SelectTrigger
	} from '$lib/components/ui/select';
	import { Badge } from '$lib/components/ui/badge';
	import { Checkbox } from '$lib/components/ui/checkbox';
	import { Plus, Trash2, Shield, Key, Pencil } from 'lucide-svelte';
	import { toast } from 'svelte-sonner';
	import { refreshPermissions } from '$lib/auth';

	let roles = $state<CompanyRole[]>([]);
	let selectedRole = $state<CompanyRole | null>(null);
	let rolePermissions = $state<RolePermission[]>([]);
	let allPermissions = $state<Permission[]>([]);
	let availablePermissions = $state<Permission[]>([]);
	let permissionsByModule = $state<Map<string, Permission[]>>(new Map());
	let loading = $state(true);
	let loadingPermissions = $state(false);

	// Dialog state
	let showPermissionsDialog = $state(false);
	let showRoleDialog = $state(false);
	let selectedPermissionIds = $state<number[]>([]);
	let permissionSearchQuery = $state('');
	let editingRole = $state<CompanyRole | null>(null);
	let roleFormData = $state({
		name: '',
		code: '',
		description: '',
		is_active: true
	});

	const companyId = $derived(companyStore.activeCompany?.id);

	// Cargar datos cuando companyId esté disponible
	$effect(() => {
		if (companyId) {
			loadRoles();
			loadAllPermissions();
		}
	});

	async function loadRoles() {
		if (!companyId) return;

		try {
			loading = true;
			const response = await rolesAPI.list(companyId);
			if (response.error) {
				toast.error(response.error);
				return;
			}
			roles = response.data?.items || [];
			if (roles.length > 0 && !selectedRole) {
				await selectRole(roles[0]);
			}
		} catch (error) {
			toast.error('Error al cargar roles');
			console.error(error);
		} finally {
			loading = false;
		}
	}

	async function loadAllPermissions() {
		try {
			const response = await permissionsAPI.list({ page_size: 1000 });
			allPermissions = response.items || [];
			if (selectedRole) {
				updateAvailablePermissions();
			}
		} catch (error) {
			toast.error('Error al cargar permisos');
			console.error(error);
		}
	}

	async function selectRole(role: CompanyRole) {
		if (!companyId) return;

		selectedRole = role;
		loadingPermissions = true;

		try {
			const response = await rolePermissionsAPI.listByRole(role.id, companyId);
			rolePermissions = response.permissions;
			updateAvailablePermissions();
		} catch (error) {
			toast.error('Error al cargar permisos del rol');
			console.error(error);
		} finally {
			loadingPermissions = false;
		}
	}

	function updateAvailablePermissions() {
		const assignedIds = rolePermissions.map((rp) => rp.permission_id);
		availablePermissions = allPermissions.filter((p) => !assignedIds.includes(p.id));
		
		updatePermissionsByModule();
	}

	function updatePermissionsByModule() {
		const grouped = new Map<string, Permission[]>();
		
		// Filtrar por búsqueda
		const filtered = availablePermissions.filter((p) => {
			if (!permissionSearchQuery.trim()) return true;
			const search = permissionSearchQuery.toLowerCase();
			return (
				p.code.toLowerCase().includes(search) ||
				p.description?.toLowerCase().includes(search) ||
				p.action.toLowerCase().includes(search)
			);
		});
		
		filtered.forEach((p) => {
			if (!grouped.has(p.module)) {
				grouped.set(p.module, []);
			}
			grouped.get(p.module)!.push(p);
		});
		
		permissionsByModule = grouped;
	}

	function openAddDialog() {
		const assignedIds = rolePermissions.map((rp) => rp.permission_id);
		const availablePermissions = allPermissions.filter((p) => !assignedIds.includes(p.id));
		selectedPermissionIds = [];
		showPermissionsDialog = true;
	}

	function openCreateRoleDialog() {
		editingRole = null;
		roleFormData = { name: '', code: '', description: '', is_active: true };
		showRoleDialog = true;
	}

	function openEditRoleDialog(role: CompanyRole) {
		editingRole = role;
		roleFormData = {
			name: role.name,
			code: role.code,
			description: role.description || '',
			is_active: role.is_active
		};
		showRoleDialog = true;
	}

	async function handleRoleSubmit() {
		if (!companyId) return;

		try {
			if (editingRole) {
				const response = await rolesAPI.update(editingRole.id, companyId, roleFormData);
				if (response.error) {
					toast.error(response.error);
					return;
				}
				toast.success('Rol actualizado correctamente');
				// Si el rol editado es el seleccionado, actualizar la referencia
				if (selectedRole?.id === editingRole.id) {
					selectedRole = { ...selectedRole, ...roleFormData };
				}
			} else {
				const response = await rolesAPI.create(companyId, roleFormData);
				if (response.error) {
					toast.error(response.error);
					return;
				}
				toast.success('Rol creado correctamente');
				// Seleccionar el nuevo rol automáticamente
				selectedRole = response.data || null;
			}
			showRoleDialog = false;
			await loadRoles();
		} catch (error: any) {
			const message =
				error?.response?.data?.detail ||
				error?.message ||
				(editingRole ? 'Error al actualizar rol' : 'Error al crear rol');
			toast.error(message);
			console.error(error);
		}
	}

	async function handleDeleteRole(role: CompanyRole) {
		if (!companyId) return;
		if (!confirm(`¿Estás seguro de eliminar el rol "${role.name}"?`)) return;

		try {
			const response = await rolesAPI.delete(role.id, companyId);
			if (response.error) {
				toast.error(response.error);
				return;
			}
			toast.success('Rol eliminado correctamente');
			// Si el rol eliminado es el seleccionado, deseleccionar
			if (selectedRole?.id === role.id) {
				selectedRole = null;
			}
			await loadRoles();
		} catch (error) {
			toast.error('Error al eliminar rol');
			console.error(error);
		}
	}

	async function handleAssignPermissions() {
		if (!companyId || !selectedRole || selectedPermissionIds.length === 0) return;

		try {
			await rolePermissionsAPI.assignMultiple(selectedRole.id, companyId, selectedPermissionIds);
			toast.success('Permisos asignados correctamente');
			showPermissionsDialog = false;
			await refreshPermissions();
			await selectRole(selectedRole);
		} catch (error) {
			toast.error('Error al asignar permisos');
			console.error(error);
		}
	}

	async function handleRemovePermission(permissionId: number) {
		if (!companyId || !selectedRole) return;
		if (!confirm('¿Estás seguro de remover este permiso?')) return;

		try {
			await rolePermissionsAPI.remove(selectedRole.id, permissionId, companyId);
			toast.success('Permiso removido correctamente');
			await refreshPermissions();
			await selectRole(selectedRole);
		} catch (error) {
			toast.error('Error al remover permiso');
			console.error(error);
		}
	}

	function togglePermission(permissionId: number) {
		if (selectedPermissionIds.includes(permissionId)) {
			selectedPermissionIds = selectedPermissionIds.filter((id) => id !== permissionId);
		} else {
			selectedPermissionIds = [...selectedPermissionIds, permissionId];
		}
	}

</script>

<div class="container mx-auto py-6">
	<div class="mb-6">
		<h1 class="text-3xl font-bold">Roles y Permisos</h1>
		<p class="text-muted-foreground">Gestiona los roles de la compañía y sus permisos</p>
	</div>

	<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
		<!-- Roles List -->
		<div class="lg:col-span-1">
			<div class="border rounded-lg p-4">
				<div class="flex items-center justify-between mb-4">
					<h2 class="text-lg font-semibold flex items-center gap-2">
						<Shield class="h-5 w-5" />
						Roles
					</h2>
					<Button size="sm" onclick={openCreateRoleDialog}>
						<Plus class="h-4 w-4" />
					</Button>
				</div>

				{#if loading}
					<p class="text-muted-foreground text-center py-4">Cargando...</p>
				{:else if roles.length === 0}
					<div class="text-center py-8">
						<p class="text-muted-foreground mb-4">No hay roles disponibles</p>
						<Button size="sm" onclick={openCreateRoleDialog}>
							<Plus class="mr-2 h-4 w-4" />
							Crear primer rol
						</Button>
					</div>
				{:else}
					<div class="space-y-2">
						{#each roles as role (role.id)}
							<div
								class="flex items-center gap-2 p-2 rounded-lg border {selectedRole?.id ===
								role.id
									? 'bg-primary/10 border-primary'
									: 'hover:bg-accent'}"
							>
								<Button
									variant="ghost"
									class="flex-1 justify-start h-auto p-2"
									onclick={() => selectRole(role)}
								>
									<div class="flex flex-col items-start gap-1 w-full">
										<div class="flex items-center gap-2 w-full">
											<Shield class="h-4 w-4 flex-shrink-0" />
											<span class="font-medium text-sm truncate">{role.name}</span>
										</div>
										{#if !role.is_active}
											<Badge variant="secondary" class="text-xs">Inactivo</Badge>
										{/if}
									</div>
								</Button>
								<div class="flex gap-1">
									<Button
										variant="ghost"
										size="sm"
										class="h-8 w-8 p-0"
										onclick={() => openEditRoleDialog(role)}
									>
										<Pencil class="h-3 w-3" />
									</Button>
									<Button
										variant="ghost"
										size="sm"
										class="h-8 w-8 p-0"
										onclick={() => handleDeleteRole(role)}
									>
										<Trash2 class="h-3 w-3" />
									</Button>
								</div>
							</div>
						{/each}
					</div>
				{/if}
			</div>
		</div>

		<!-- Permissions List -->
		<div class="lg:col-span-2">
			{#if selectedRole}
				<div class="border rounded-lg">
					<div class="p-4 border-b flex items-center justify-between">
						<div>
							<h2 class="text-lg font-semibold flex items-center gap-2">
								<Key class="h-5 w-5" />
								Permisos de "{selectedRole.name}"
							</h2>
							<p class="text-sm text-muted-foreground">
								{rolePermissions.length} permisos asignados
							</p>
						</div>
						<Button onclick={openAddDialog} disabled={availablePermissions.length === 0}>
							<Plus class="mr-2 h-4 w-4" />
							Agregar Permisos
						</Button>
					</div>

					<Table>
						<TableHeader>
							<TableRow>
								<TableHead>Módulo</TableHead>
								<TableHead>Acción</TableHead>
								<TableHead>Descripción</TableHead>
								<TableHead class="text-right">Acciones</TableHead>
							</TableRow>
						</TableHeader>
						<TableBody>
							{#if loadingPermissions}
								<TableRow>
									<TableCell colspan={4} class="text-center py-8">
										Cargando permisos...
									</TableCell>
								</TableRow>
							{:else if rolePermissions.length === 0}
								<TableRow>
									<TableCell colspan={4} class="text-center py-8">
										Este rol no tiene permisos asignados
									</TableCell>
								</TableRow>
							{:else}
								{#each rolePermissions as rp (rp.id)}
									<TableRow>
										<TableCell>
											<Badge variant="outline">{rp.permission?.module}</Badge>
										</TableCell>
										<TableCell>{rp.permission?.action}</TableCell>
										<TableCell class="text-muted-foreground">
											{rp.permission?.description || '-'}
										</TableCell>
										<TableCell class="text-right">
											<Button
												variant="ghost"
												size="sm"
												onclick={() => handleRemovePermission(rp.permission_id)}
											>
												<Trash2 class="h-4 w-4" />
											</Button>
										</TableCell>
									</TableRow>
								{/each}
							{/if}
						</TableBody>
					</Table>
				</div>
			{:else}
				<div class="border rounded-lg p-12 text-center">
					<Shield class="h-12 w-12 mx-auto mb-4 text-muted-foreground" />
					<p class="text-muted-foreground">Selecciona un rol para ver sus permisos</p>
				</div>
			{/if}
		</div>
	</div>
</div>

<!-- Add Permissions Dialog -->
<Dialog.Root bind:open={showPermissionsDialog}>
	<Dialog.Content class="max-w-2xl max-h-[80vh]">
		<Dialog.Header>
			<Dialog.Title>Agregar Permisos a "{selectedRole?.name}"</Dialog.Title>
		</Dialog.Header>

		<div class="overflow-y-auto max-h-96 py-4">
		<div class="px-4 pb-2">
			<Input
				type="text"
				placeholder="Buscar permisos..."
				bind:value={permissionSearchQuery}
				oninput={() => updatePermissionsByModule()}
				class="w-full"
			/>
		</div>

		{#if availablePermissions.length === 0}
				<p class="text-center text-muted-foreground py-8">
					No hay permisos disponibles para asignar
				</p>
			{:else}
				<div class="space-y-4">																									
					{#each [...permissionsByModule] as [module, permissions] (module)}
						<div class="border rounded-lg p-4">
							<h3 class="font-semibold mb-3 flex items-center gap-2">
								<Badge>{module}</Badge>
								<span class="text-xs text-muted-foreground">({permissions.length} permisos, {new Set(permissions.map(p => p.id)).size} únicos)</span>
							</h3>
							<div class="space-y-2">
								{#each permissions as permission (permission.id)}
									<div class="flex items-start space-x-3">
										<Checkbox
											id="perm-{permission.id}"
											checked={selectedPermissionIds.includes(permission.id)}
											onCheckedChange={() => togglePermission(permission.id)}
										/>
										<div class="flex-1">
											<Label
												for="perm-{permission.id}"
												class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
											>
												{permission.description || permission.code}
											</Label>
											<div class="flex items-center gap-2 mt-1">
												<code class="text-xs bg-muted px-1.5 py-0.5 rounded">{permission.code}</code>
											</div>
										</div>
									</div>
								{/each}
							</div>
						</div>
					{/each}
				</div>
			{/if}
		</div>

		<Dialog.Footer>
			<Button variant="outline" onclick={() => (showPermissionsDialog = false)}>Cancelar</Button>
			<Button onclick={handleAssignPermissions} disabled={selectedPermissionIds.length === 0}>
				Asignar {selectedPermissionIds.length} permisos
			</Button>
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>

<!-- Create/Edit Role Dialog -->
<Dialog.Root bind:open={showRoleDialog}>
	<Dialog.Content>
		<Dialog.Header>
			<Dialog.Title>
				{editingRole ? 'Editar Rol' : 'Nuevo Rol'}
			</Dialog.Title>
		</Dialog.Header>

		<div class="grid gap-4 py-4">
			<div class="grid gap-2">
				<Label for="name">Nombre</Label>
				<Input id="name" bind:value={roleFormData.name} placeholder="Administrador" />
			</div>

			<div class="grid gap-2">
				<Label for="code">Código</Label>
				<Input id="code" bind:value={roleFormData.code} placeholder="ADMIN" />
			</div>

			<div class="grid gap-2">
				<Label for="description">Descripción</Label>
				<Textarea
					id="description"
					bind:value={roleFormData.description}
					placeholder="Rol con acceso completo al sistema"
				/>
			</div>

			<div class="flex items-center space-x-2">
				<Switch id="is_active" bind:checked={roleFormData.is_active} />
				<Label for="is_active">Activo</Label>
			</div>
		</div>

		<Dialog.Footer>
			<Button variant="outline" onclick={() => (showRoleDialog = false)}>Cancelar</Button>
			<Button onclick={handleRoleSubmit}>
				{editingRole ? 'Actualizar' : 'Crear'}
			</Button>
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>
