'use client';
import React, { useRef } from 'react';
import { useRouter } from 'next/navigation';
import { useTranslations, useLocale } from 'next-intl';
import Link from "next/link";
import { Ellipsis, Ban as BanIcon, Plus } from 'lucide-react';
import {
  Dataset,
  DatasetToolbar,
  DatasetCol,
  DatasetFilters,
  DatasetTable,
  DatasetAction,
  DatasetActionBar
} from "@/components/ui/dataset";
import { SelectControl } from '@/components/form/control/select.control';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger
} from '@/components/ui/tooltip';
import {
  DropdownMenu,
  DropdownMenuItem,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuSeparator
} from '@/components/ui/dropdown-menu';
import { UserBanDialog, UserBanDialogRef } from "@/components/dashboard/user/user-ban-dialog";
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { UserListQuerySchema } from '@/server/modules/user/user.validators';
import { useQueryStates } from '@/lib/hooks/use-query-states';
import { client, useSession } from '@/lib/auth/auth-client';
import type { AppRouterOutput } from '@/lib/trpc/router';
import { api } from '@/lib/trpc/client';
import { cn } from '@/lib/utils/cn';
import formatDate from "@/lib/utils/format-date";
import { formatRelativeTime } from '@/lib/utils/format';
import { UserRole, UserRoleHelpers } from '@/server/modules/user/user-role.enum';
import { Routes } from '@/config/routes';

type User = NonNullable<AppRouterOutput['user']['get']>;

export const UserList: React.FC = () => {
  const router = useRouter();
  const locale = useLocale();
  const t = useTranslations();
  const [params, setParams] = useQueryStates(UserListQuerySchema, {
    history: 'replace',
    scroll: false,
    shallow: true,
    clearOnDefault: true
  });

  const { refetch: refetchSession } = useSession();
  const banDialogRef = useRef<UserBanDialogRef>(null);

  const { data: impersonatedBy = null, isLoading: isImpersonatedLoading } = api.auth.impersonatedBy.useQuery();

  const { data: count = 0 } = api.user.count.useQuery({
    search: params.search || undefined,
    role: params.role || undefined
  });

  const { data: users = [], refetch: refetchList } = api.user.list.useQuery({
    with: ["avatar", "lastSession"],
    search: params.search || undefined,
    role: params.role || undefined,
    offset: params.page * params.perPage,
    limit: params.perPage,
    orderBy: params.orderBy,
    orderDir: params.orderDir
  });

  return (
    <Dataset<User>
      selection
      data={users}
      total={count}
      page={params.page}
      perPage={params.perPage}
      orderBy={params.orderBy}
      orderDir={params.orderDir}
      onPageChange={(page) => setParams({ page })}
      onPerPageChange={(perPage) => setParams({ perPage })}
      onOrderByChange={(orderBy) => setParams({ orderBy })}
      onOrderDirChange={(orderDir) => setParams({ orderDir })}
    >
      <DatasetToolbar>
        <DatasetFilters search filters={params} onChange={setParams}>
          <SelectControl label='Role' name='role'>
            <SelectControl.Trigger className="w-full">
              <SelectControl.Value placeholder='Select a role' />
            </SelectControl.Trigger>

            <SelectControl.Content>
              {Object.entries(UserRole).map(([, role]) => {
                return (
                  <SelectControl.Item key={role} value={role}>
                    {UserRoleHelpers.getLabel(role)}
                  </SelectControl.Item>
                );
              })}
            </SelectControl.Content>
          </SelectControl>
        </DatasetFilters>

        <div className="flex items-center gap-2">
          <Button asChild variant="outline" size="sm">
            <Link href={Routes.DASHBOARD.USER_CREATE}>
              <Plus className="h-4 w-4" />
              {t('dashboard.user.actions.create')}
            </Link>
          </Button>
        </div>
      </DatasetToolbar>

      <DatasetTable>
        <DatasetCol<User, 'name'>
          enableSorting
          label={t('dashboard.user.list.fields.name.label')}
          name='name'
          render={(name, user) => {
            return (
              <div className='flex items-center space-x-3'>
                <Avatar className='h-8 w-8'>
                  <AvatarImage src={user.avatar?.url || undefined} />
                  <AvatarFallback>
                    {name?.charAt(0)?.toUpperCase() || user.email.charAt(0).toUpperCase()}
                  </AvatarFallback>
                </Avatar>

                <div className={cn({ 'text-muted-foreground': user.banned })}>
                  <div className='flex items-center gap-1 font-medium'>
                    {user.banned && <BanIcon size={15} />}

                    {user.name || 'Unavngivet'}
                  </div>
                  <div className='text-muted-foreground text-sm'>
                    {user.email}
                  </div>
                </div>
              </div>
            );
          }}
        />

        <DatasetCol<User, 'role'>
          enableSorting
          label={t('dashboard.user.list.fields.role.label')}
          name='role'
          render={(role) => {
            return (
              <Badge>{UserRoleHelpers.getLabel(role)}</Badge>
            );
          }}
        />

        <DatasetCol<User, 'banned'>
          enableSorting
          label={t('dashboard.user.list.fields.status.label')}
          name='banned'
          render={(banned, user) => {
            if (!banned) {
              return (
                <Badge variant='outline' className='text-green-600'>
                  Aktiv
                </Badge>
              );
            }

            return (
              <div className='space-y-1'>
                <Badge variant='destructive'>Bannet</Badge>
                {user.banReason && (
                  <div className='text-muted-foreground text-xs'>
                    {user.banReason}
                  </div>
                )}
              </div>
            );
          }}
        />

        <DatasetCol<User, 'createdAt'>
          enableSorting
          label={t('dashboard.user.list.fields.createdAt.label')}
          name='createdAt'
          render={(createdAt) => formatDate(createdAt, { locale, day: "numeric", month: "long", year: "numeric" })}
        />

        <DatasetCol<User, 'lastSession'>
          label={t('dashboard.user.list.fields.lastSession.label')}
          name='lastSession'
          render={(lastSession) => {
            const session = Array.isArray(lastSession) ? lastSession[0] : undefined;

            if (!session) {
              return;
            }

            const exact = formatDate(session.createdAt, {
              locale,
              day: "numeric",
              month: "long",
              year: "numeric",
              hour: '2-digit',
              minute: '2-digit',
              hour12: false
            });

            return (
              <Tooltip>
                <TooltipTrigger asChild>
                  <span>
                    {formatRelativeTime(session.createdAt, locale)}
                  </span>
                </TooltipTrigger>
                <TooltipContent>
                  <p>{exact}</p>
                </TooltipContent>
              </Tooltip>
            );
          }}
        />

        <DatasetCol<User, 'id'>
          label={t('dashboard.user.list.fields.actions.label')}
          name='id'
          render={(id, user) => {
            return (
              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <Button
                    className='data-[state=open]:bg-muted flex size-8 p-0'
                    variant='ghost'
                    aria-label='Open menu'
                  >
                    <Ellipsis className='size-4' aria-hidden='true' />
                  </Button>
                </DropdownMenuTrigger>

                <DropdownMenuContent>
                  <DropdownMenuItem
                    onClick={() => router.push(Routes.DASHBOARD.USER_EDIT(id))}
                  >
                    {t('dashboard.user.actions.edit')}
                  </DropdownMenuItem>

                  {!isImpersonatedLoading &&
                    !impersonatedBy &&
                    !user.banned && (
                      <DropdownMenuItem
                        onClick={async () => {
                          await client.admin.impersonateUser({
                            userId: id
                          });

                          refetchSession();

                          router.push(Routes.HOME);
                        }}
                      >
                        {t('dashboard.user.actions.impersonate')}
                      </DropdownMenuItem>
                    )}

                  <DropdownMenuSeparator />

                  {user.banned && (
                    <DropdownMenuItem
                      onClick={async () => {
                        await client.admin.unbanUser({
                          userId: id
                        });

                        await refetchList();
                      }}
                    >
                      {t('dashboard.user.actions.unban')}
                    </DropdownMenuItem>
                  )}

                  {!user.banned && (
                    <DropdownMenuItem
                      variant='destructive'
                      onClick={async () => {
                        banDialogRef.current?.open([user]);
                      }}
                    >
                      <BanIcon /> {t('dashboard.user.actions.ban')}
                    </DropdownMenuItem>
                  )}
                </DropdownMenuContent>
              </DropdownMenu>
            );
          }}
        />
      </DatasetTable>

      <DatasetActionBar>
        <DatasetAction<User>
          size='icon'
          variant='destructive'
          onClick={(rows) => {
            banDialogRef.current?.open(rows.map((r) => r.original));
          }}
        >
          <BanIcon />
        </DatasetAction>
      </DatasetActionBar>

      <UserBanDialog ref={banDialogRef} />
    </Dataset>
  );
};
