import { useEffect, useState } from 'react';
import { mapToQueryResult, useUsers } from './api';

interface UsersTableProps {
    initialUrl: string;
}

interface SortState {
    column: 'name' | 'email' | 'created_at' | null;
    direction: 'asc' | 'desc' | null;
}

export function UsersTable({ initialUrl }: UsersTableProps) {
    const [searchInput, setSearchInput] = useState('');
    const [debouncedSearch, setDebouncedSearch] = useState('');
    const [page, setPage] = useState(1);
    const [sort, setSort] = useState<SortState>({ column: null, direction: null });

    useEffect(() => {
        const handle = window.setTimeout(() => {
            setDebouncedSearch(searchInput);
            setPage(1);
        }, 300);
        return () => window.clearTimeout(handle);
    }, [searchInput]);

    const query = useUsers(initialUrl, { page, search: debouncedSearch });
    const result = query.data ? mapToQueryResult(query.data) : null;

    function handleHeaderClick(column: SortState['column']) {
        setSort((current) => {
            if (current.column !== column) {
                return { column, direction: 'asc' };
            }
            if (current.direction === 'asc') {
                return { column, direction: 'desc' };
            }
            if (current.direction === 'desc') {
                return { column: null, direction: null };
            }
            return { column, direction: 'asc' };
        });
    }

    function ariaSortFor(column: SortState['column']): 'ascending' | 'descending' | 'none' {
        if (sort.column !== column) {
            return 'none';
        }
        if (sort.direction === 'asc') {
            return 'ascending';
        }
        if (sort.direction === 'desc') {
            return 'descending';
        }
        return 'none';
    }

    function sortIconFor(column: SortState['column']): string {
        if (sort.column !== column || sort.direction === null) {
            return 'fa-sort text-gray-300 dark:text-gray-600';
        }
        return sort.direction === 'asc' ? 'fa-sort-up' : 'fa-sort-down';
    }

    if (query.isError) {
        return (
            <div
                className="rounded-lg border border-red-200 bg-red-50 p-6 text-center text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300"
                role="alert"
            >
                <i className="fa-solid fa-triangle-exclamation mb-2 block text-2xl" aria-hidden="true"></i>
                <p className="font-medium">No se pudieron cargar los usuarios.</p>
                <p className="mt-1 text-sm opacity-80">Verifica tu conexión e inténtalo de nuevo.</p>
                <button
                    type="button"
                    onClick={() => {
                        void query.refetch();
                    }}
                    className="mt-4 inline-flex items-center gap-2 rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900"
                >
                    <i className="fa-solid fa-rotate" aria-hidden="true"></i>
                    Reintentar
                </button>
            </div>
        );
    }

    return (
        <div className="space-y-4">
            <div className="flex flex-wrap items-center gap-3">
                <label htmlFor="users-search" className="sr-only">
                    Buscar usuarios
                </label>
                <div className="relative flex-1 sm:max-w-sm">
                    <span className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-gray-400" aria-hidden="true">
                        <i className="fa-solid fa-magnifying-glass"></i>
                    </span>
                    <input
                        id="users-search"
                        type="search"
                        value={searchInput}
                        onChange={(event) => {
                            setSearchInput(event.target.value);
                        }}
                        placeholder="Buscar por nombre o correo..."
                        className="w-full rounded-lg border border-gray-300 bg-white py-2 pl-10 pr-3 text-sm text-gray-900 placeholder-gray-400 focus-visible:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary dark:border-white/10 dark:bg-white/5 dark:text-white dark:placeholder-gray-500"
                        aria-describedby="users-search-help"
                    />
                </div>
                <p id="users-search-help" className="text-xs text-gray-500 dark:text-gray-400">
                    {result === null ? 'Cargando…' : `${result.pagination.total} usuario(s) encontrado(s).`}
                </p>
            </div>

            <div className="relative overflow-x-auto rounded-xl border border-gray-200 bg-white dark:border-white/10 dark:bg-white/5">
                {query.isFetching && query.data ? (
                    <div
                        className="pointer-events-none absolute inset-0 z-10 flex items-center justify-center bg-white/60 backdrop-blur-sm dark:bg-gray-900/60"
                        aria-live="polite"
                    >
                        <span className="inline-flex items-center gap-2 rounded-full bg-primary px-3 py-1 text-xs font-medium text-white shadow">
                            <i className="fa-solid fa-spinner fa-spin" aria-hidden="true"></i>
                            Actualizando…
                        </span>
                    </div>
                ) : null}

                <table role="table" className="min-w-full divide-y divide-gray-200 text-sm dark:divide-white/10">
                    <thead>
                        <tr className="text-left text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400">
                            <th
                                scope="col"
                                role="columnheader"
                                aria-sort={ariaSortFor('name')}
                                className="px-6 py-4 font-medium"
                            >
                                <button
                                    type="button"
                                    onClick={() => {
                                        handleHeaderClick('name');
                                    }}
                                    className="inline-flex items-center gap-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
                                >
                                    Usuario
                                    <i className={`fa-solid ${sortIconFor('name')}`} aria-hidden="true"></i>
                                </button>
                            </th>
                            <th
                                scope="col"
                                role="columnheader"
                                aria-sort={ariaSortFor('email')}
                                className="px-6 py-4 font-medium"
                            >
                                <button
                                    type="button"
                                    onClick={() => {
                                        handleHeaderClick('email');
                                    }}
                                    className="inline-flex items-center gap-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
                                >
                                    Correo
                                    <i className={`fa-solid ${sortIconFor('email')}`} aria-hidden="true"></i>
                                </button>
                            </th>
                            <th scope="col" role="columnheader" className="px-6 py-4 font-medium">
                                Rol
                            </th>
                            <th scope="col" role="columnheader" className="px-6 py-4 font-medium">
                                Estado
                            </th>
                        </tr>
                    </thead>
                    <tbody className="divide-y divide-gray-100 dark:divide-white/5">
                        {query.isLoading ? (
                            <tr>
                                <td colSpan={4} className="px-6 py-12 text-center text-gray-500 dark:text-gray-400">
                                    <i className="fa-solid fa-spinner fa-spin mb-2 block text-2xl" aria-hidden="true"></i>
                                    Cargando usuarios…
                                </td>
                            </tr>
                        ) : result === null || result.users.length === 0 ? (
                            <tr>
                                <td colSpan={4} className="px-6 py-12 text-center text-gray-500 dark:text-gray-400">
                                    <i className="fa-solid fa-users mb-2 block text-2xl opacity-40" aria-hidden="true"></i>
                                    {debouncedSearch === ''
                                        ? 'No hay usuarios registrados.'
                                        : `No se encontraron usuarios para “${debouncedSearch}”.`}
                                </td>
                            </tr>
                        ) : (
                            result.users.map((user) => (
                                <tr key={user.id} className="hover:bg-gray-50 dark:hover:bg-white/5">
                                    <td className="px-6 py-4">
                                        <div className="flex items-center gap-3">
                                            <span className="flex size-9 shrink-0 items-center justify-center rounded-full bg-primary-light text-xs font-semibold text-primary-dark dark:bg-primary/20 dark:text-primary-light">
                                                {user.name
                                                    .split(' ')
                                                    .filter((part) => part.length > 0)
                                                    .slice(0, 2)
                                                    .map((part) => part[0]?.toUpperCase() ?? '')
                                                    .join('')}
                                            </span>
                                            <div>
                                                <p className="font-medium text-gray-900 dark:text-white">{user.name}</p>
                                                <p className="text-xs text-gray-500 dark:text-gray-400">{user.email}</p>
                                            </div>
                                        </div>
                                    </td>
                                    <td className="px-6 py-4 text-gray-600 dark:text-gray-300">{user.email}</td>
                                    <td className="px-6 py-4">
                                        <span className="rounded-full bg-primary-light px-2.5 py-1 text-xs font-medium text-primary-dark dark:bg-primary/20 dark:text-primary-light">
                                            {user.roles[0] ?? 'Sin rol'}
                                        </span>
                                    </td>
                                    <td className="px-6 py-4">
                                        {user.is_active ? (
                                            <span className="rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-400">
                                                Activo
                                            </span>
                                        ) : (
                                            <span className="rounded-full bg-gray-100 px-2.5 py-1 text-xs font-medium text-gray-600 dark:bg-white/10 dark:text-gray-300">
                                                Inactivo
                                            </span>
                                        )}
                                    </td>
                                </tr>
                            ))
                        )}
                    </tbody>
                </table>
            </div>

            {result !== null && result.pagination.lastPage > 1 ? (
                <nav
                    aria-label="Paginación de usuarios"
                    className="flex flex-wrap items-center justify-between gap-3"
                >
                    <p className="text-xs text-gray-500 dark:text-gray-400">
                        Página {result.pagination.currentPage} de {result.pagination.lastPage}
                    </p>
                    <ul className="inline-flex items-center gap-1">
                        <li>
                            <button
                                type="button"
                                onClick={() => {
                                    setPage((current) => Math.max(1, current - 1));
                                }}
                                disabled={result.pagination.currentPage <= 1}
                                className="inline-flex size-9 items-center justify-center rounded-md border border-gray-300 bg-white text-gray-600 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
                                aria-label="Página anterior"
                            >
                                <i className="fa-solid fa-chevron-left text-xs" aria-hidden="true"></i>
                            </button>
                        </li>
                        {Array.from({ length: result.pagination.lastPage }, (_, index) => index + 1).map((pageNumber) => {
                            const isCurrent = pageNumber === result.pagination.currentPage;
                            return (
                                <li key={pageNumber}>
                                    <button
                                        type="button"
                                        onClick={() => {
                                            setPage(pageNumber);
                                        }}
                                        aria-current={isCurrent ? 'page' : undefined}
                                        className={
                                            isCurrent
                                                ? 'inline-flex size-9 items-center justify-center rounded-md bg-primary text-sm font-semibold text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-900'
                                                : 'inline-flex size-9 items-center justify-center rounded-md border border-gray-300 bg-white text-sm text-gray-600 hover:bg-gray-50 dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary'
                                        }
                                    >
                                        {pageNumber}
                                    </button>
                                </li>
                            );
                        })}
                        <li>
                            <button
                                type="button"
                                onClick={() => {
                                    setPage((current) =>
                                        Math.min(result.pagination.lastPage, current + 1),
                                    );
                                }}
                                disabled={result.pagination.currentPage >= result.pagination.lastPage}
                                className="inline-flex size-9 items-center justify-center rounded-md border border-gray-300 bg-white text-gray-600 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary"
                                aria-label="Página siguiente"
                            >
                                <i className="fa-solid fa-chevron-right text-xs" aria-hidden="true"></i>
                            </button>
                        </li>
                    </ul>
                </nav>
            ) : null}
        </div>
    );
}
