import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  FileDown,
  Loader2,
  Mail,
  Plus,
  Search,
  User,
  UserPlus,
  X,
} from "lucide-react";
import * as React from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { commonStickyTableHeaderClass } from "../../../../../common/ui/table";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "../../../components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../../components/ui/table";
import { toast } from "../../../components/ui/use-toast";
import {
  exportUsersCSV,
  fetchTenant,
  fetchUsers,
  type UserSummary,
  updateUser,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";

function TenantUsersPage() {
  const params = useParams<{ tenantId: string }>();
  const navigate = useNavigate();
  const tenantId = params.tenantId ?? "";
  const queryClient = useQueryClient();
  const [addMembersOpen, setAddMembersOpen] = React.useState(false);
  const [memberSearch, setMemberSearch] = React.useState("");
  const [queuedMembers, setQueuedMembers] = React.useState<UserSummary[]>([]);

  // 테넌트의 슬러그(tenantSlug)를 먼저 가져옴
  const tenantQuery = useQuery({
    queryKey: ["tenant", tenantId],
    queryFn: () => fetchTenant(tenantId),
    enabled: tenantId.length > 0,
  });

  const tenantSlug = tenantQuery.data?.slug;

  // 해당 슬러그로 사용자 검색
  const usersQuery = useQuery({
    queryKey: ["users", { tenantSlug }],
    queryFn: () => fetchUsers(100, 0, undefined, tenantSlug),
    enabled: !!tenantSlug,
  });

  const memberSearchTerm = memberSearch.trim();
  const memberSearchQuery = useQuery({
    queryKey: ["tenant-member-search", tenantSlug, memberSearchTerm],
    queryFn: () => fetchUsers(20, 0, memberSearchTerm),
    enabled: addMembersOpen && memberSearchTerm.length >= 2,
  });

  const exportMutation = useMutation({
    mutationFn: (includeIds: boolean) =>
      exportUsersCSV("", tenantSlug ?? "", includeIds),
    onSuccess: ({ blob, filename }) => {
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);
    },
    onError: () => {
      toast.error(
        t("msg.admin.users.export_error", "사용자 내보내기에 실패했습니다."),
      );
    },
  });

  const removeTenantMutation = useMutation({
    mutationFn: ({ userId, slug }: { userId: string; slug: string }) =>
      updateUser(userId, { tenantSlug: slug, isRemoveTenant: true }),
    onSuccess: () => {
      toast.success(
        t(
          "msg.admin.tenants.members.remove_success",
          "조직에서 제외되었습니다.",
        ),
      );
      usersQuery.refetch();
      queryClient.invalidateQueries({ queryKey: ["tenant", tenantId] });
    },
    onError: (err: AxiosError<{ error?: string }>) => {
      toast.error(
        err.response?.data?.error ||
          t("msg.admin.tenants.members.remove_error", "제외 실패"),
      );
    },
  });

  const addMembersMutation = useMutation({
    mutationFn: async (members: UserSummary[]) => {
      if (!tenantSlug || members.length === 0) return;
      await Promise.all(
        members.map((member) =>
          updateUser(member.id, { tenantSlug, isAddTenant: true }),
        ),
      );
    },
    onSuccess: () => {
      const count = queuedMembers.length;
      toast.success(
        t(
          "msg.admin.tenants.members.add_success",
          "{{count}}명의 구성원이 추가되었습니다.",
          { count },
        ),
      );
      setQueuedMembers([]);
      setMemberSearch("");
      setAddMembersOpen(false);
      usersQuery.refetch();
      queryClient.invalidateQueries({ queryKey: ["tenant", tenantId] });
    },
    onError: (err: AxiosError<{ error?: string }>) => {
      toast.error(
        err.response?.data?.error ||
          t("msg.admin.tenants.members.add_error", "구성원 추가 실패"),
      );
    },
  });

  const _handleRemoveMember = (userId: string, userName: string) => {
    if (!tenantSlug) return;
    if (
      window.confirm(
        t(
          "msg.admin.tenants.members.remove_confirm",
          "'{{name}}'님을 이 조직에서 제외하시겠습니까?",
          { name: userName },
        ),
      )
    ) {
      removeTenantMutation.mutate({ userId, slug: tenantSlug });
    }
  };

  const users = usersQuery.data?.items ?? [];
  const existingUserIds = React.useMemo(
    () => new Set(users.map((user) => user.id)),
    [users],
  );
  const queuedUserIds = React.useMemo(
    () => new Set(queuedMembers.map((user) => user.id)),
    [queuedMembers],
  );
  const searchResults = memberSearchQuery.data?.items ?? [];

  const queueMember = (member: UserSummary) => {
    if (existingUserIds.has(member.id) || queuedUserIds.has(member.id)) {
      return;
    }
    setQueuedMembers((current) => [...current, member]);
  };

  const removeQueuedMember = (memberId: string) => {
    setQueuedMembers((current) =>
      current.filter((member) => member.id !== memberId),
    );
  };

  return (
    <Card className="mt-6 bg-[var(--color-panel)] flex-1 flex flex-col min-h-0 overflow-hidden">
      <CardHeader className="flex-shrink-0 flex flex-row items-center justify-between">
        <CardTitle className="flex items-center gap-2">
          <User size={18} className="text-primary" />
          {t("ui.admin.tenants.members.title", "Tenant Members ({{count}})", {
            count: users.length,
          })}
        </CardTitle>
        <div className="flex flex-wrap items-center justify-end gap-2">
          <Button
            variant="outline"
            size="sm"
            className="gap-2"
            disabled={!tenantSlug || exportMutation.isPending}
            data-testid="tenant-users-export-menu-item"
            onClick={() => exportMutation.mutate(false)}
          >
            <FileDown size={16} />
            {t("ui.common.export_without_ids", "UUID 제외 내보내기")}
          </Button>
          <Button
            variant="outline"
            size="sm"
            className="gap-2"
            disabled={!tenantSlug || exportMutation.isPending}
            data-testid="tenant-users-export-with-ids-menu-item"
            onClick={() => exportMutation.mutate(true)}
          >
            <FileDown size={16} />
            {t("ui.common.export_with_ids", "UUID 포함 내보내기")}
          </Button>
          <Button
            variant="outline"
            size="sm"
            className="gap-2"
            disabled={!tenantSlug}
            data-testid="tenant-member-add-existing-btn"
            onClick={() => setAddMembersOpen(true)}
          >
            <UserPlus size={16} />
            {t("ui.admin.tenants.members.add_existing", "기존 멤버 배정")}
          </Button>
          <Button size="sm" asChild className="gap-2">
            <Link to={`/users/new?tenantSlug=${tenantSlug}`}>
              <Plus size={16} />
              {t("ui.admin.tenants.members.create_new", "신규 멤버 생성")}
            </Link>
          </Button>
        </div>
      </CardHeader>
      <Dialog open={addMembersOpen} onOpenChange={setAddMembersOpen}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>
              {t("ui.admin.tenants.members.add_existing", "기존 멤버 배정")}
            </DialogTitle>
            <DialogDescription>
              {t(
                "ui.admin.tenants.members.add_existing_description",
                "검색 결과를 선택해 추가 명단에 담은 뒤 한 번에 배정합니다.",
              )}
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="relative">
              <Search
                size={16}
                className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
              />
              <Input
                value={memberSearch}
                onChange={(event) => setMemberSearch(event.target.value)}
                className="h-9 pl-9"
                placeholder={t(
                  "ui.admin.tenants.members.search_placeholder",
                  "이름 또는 이메일 검색",
                )}
                data-testid="tenant-member-search-input"
              />
            </div>
            <div className="rounded-md border">
              <div className="max-h-56 overflow-auto">
                {memberSearchTerm.length < 2 ? (
                  <div className="px-3 py-6 text-center text-sm text-muted-foreground">
                    {t(
                      "ui.admin.tenants.members.search_min_length",
                      "두 글자 이상 입력하세요.",
                    )}
                  </div>
                ) : memberSearchQuery.isFetching ? (
                  <div className="flex items-center justify-center gap-2 px-3 py-6 text-sm text-muted-foreground">
                    <Loader2 size={16} className="animate-spin" />
                    {t("ui.common.searching", "검색 중...")}
                  </div>
                ) : searchResults.length === 0 ? (
                  <div className="px-3 py-6 text-center text-sm text-muted-foreground">
                    {t("ui.common.no_results", "검색 결과가 없습니다.")}
                  </div>
                ) : (
                  <div className="divide-y">
                    {searchResults.map((user) => {
                      const disabled =
                        existingUserIds.has(user.id) ||
                        queuedUserIds.has(user.id);
                      return (
                        <button
                          key={user.id}
                          type="button"
                          className="flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-muted/50 disabled:cursor-not-allowed disabled:opacity-50"
                          disabled={disabled}
                          onClick={() => queueMember(user)}
                        >
                          <span className="min-w-0">
                            <span className="block truncate font-medium">
                              {user.name}
                            </span>
                            <span className="block truncate text-xs text-muted-foreground">
                              {user.email}
                            </span>
                          </span>
                          <Plus size={16} className="flex-shrink-0" />
                        </button>
                      );
                    })}
                  </div>
                )}
              </div>
            </div>
            <div
              className="min-h-20 rounded-md border bg-muted/20 p-3"
              data-testid="tenant-member-add-queue"
            >
              {queuedMembers.length === 0 ? (
                <div className="flex h-14 items-center justify-center text-sm text-muted-foreground">
                  {t(
                    "ui.admin.tenants.members.queue_empty",
                    "추가할 구성원을 선택하세요.",
                  )}
                </div>
              ) : (
                <div className="flex flex-wrap gap-2">
                  {queuedMembers.map((user) => (
                    <span
                      key={user.id}
                      className="inline-flex max-w-full items-center gap-2 rounded-md border bg-background px-2 py-1 text-sm"
                    >
                      <span className="max-w-52 truncate">{user.name}</span>
                      <button
                        type="button"
                        className="text-muted-foreground hover:text-foreground"
                        onClick={() => removeQueuedMember(user.id)}
                        aria-label={t(
                          "ui.admin.tenants.members.queue_remove",
                          "추가 명단에서 제거",
                        )}
                      >
                        <X size={14} />
                      </button>
                    </span>
                  ))}
                </div>
              )}
            </div>
          </div>
          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setAddMembersOpen(false)}
              disabled={addMembersMutation.isPending}
            >
              {t("ui.common.cancel", "취소")}
            </Button>
            <Button
              onClick={() => addMembersMutation.mutate(queuedMembers)}
              disabled={
                queuedMembers.length === 0 || addMembersMutation.isPending
              }
              data-testid="tenant-member-add-submit-btn"
            >
              {addMembersMutation.isPending && (
                <Loader2 size={16} className="animate-spin" />
              )}
              {t("ui.admin.tenants.members.add_queued", "선택 구성원 추가")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
      <CardContent className="flex-1 flex flex-col min-h-0 pt-0">
        <div className="flex-1 rounded-md border overflow-hidden flex flex-col">
          <div className="flex-1 overflow-auto relative custom-scrollbar">
            <Table>
              <TableHeader className={commonStickyTableHeaderClass}>
                <TableRow>
                  <TableHead>
                    {t("ui.admin.tenants.members.table.name", "NAME")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.members.table.email", "EMAIL")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.members.table.role", "ROLE")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.members.table.status", "STATUS")}
                  </TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {usersQuery.isLoading ? (
                  <TableRow>
                    <TableCell colSpan={4} className="text-center py-20">
                      <div className="flex flex-col items-center gap-2">
                        <Loader2
                          className="animate-spin text-muted-foreground"
                          size={24}
                        />
                        <span className="text-sm text-muted-foreground">
                          {t("ui.common.loading", "Loading...")}
                        </span>
                      </div>
                    </TableCell>
                  </TableRow>
                ) : users.length === 0 ? (
                  <TableRow>
                    <TableCell
                      colSpan={4}
                      className="text-center py-8 text-muted-foreground"
                    >
                      {t(
                        "msg.admin.tenants.members.empty",
                        "소속된 사용자가 없습니다.",
                      )}
                    </TableCell>
                  </TableRow>
                ) : (
                  users.map((user) => (
                    <TableRow
                      key={user.id}
                      className="cursor-pointer hover:bg-muted/50 transition-colors"
                      onClick={() => navigate(`/users/${user.id}`)}
                    >
                      <TableCell className="font-semibold">
                        {user.name}
                      </TableCell>
                      <TableCell>
                        <div className="flex items-center gap-1 text-xs">
                          <Mail size={12} className="text-muted-foreground" />
                          {user.email}
                        </div>
                      </TableCell>
                      <TableCell>
                        <Badge variant="outline" className="capitalize">
                          {t(
                            `ui.common.role.${user.role}`,
                            user.role.replace("_", " "),
                          )}
                        </Badge>
                      </TableCell>
                      <TableCell>
                        <Badge
                          variant={
                            user.status === "active" ? "default" : "muted"
                          }
                        >
                          {t(`ui.common.status.${user.status}`, user.status)}
                        </Badge>
                      </TableCell>
                    </TableRow>
                  ))
                )}
              </TableBody>
            </Table>
          </div>
        </div>
      </CardContent>
    </Card>
  );
}

export default TenantUsersPage;
