import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  Crown,
  Plus,
  Search,
  ShieldCheck,
  UserPlus,
  Users,
} from "lucide-react";
import { useState } from "react";
import { useAuth } from "react-oidc-context";
import { 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,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../../components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  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 {
  addTenantAdmin,
  addTenantOwner,
  fetchTenantAdmins,
  fetchTenantOwners,
  fetchUsers,
  removeTenantAdmin,
  removeTenantOwner,
  type TenantAdmin,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";

type DialogMode = "owner" | "admin";

function mergePendingMembers(
  members: TenantAdmin[],
  pendingMembers: TenantAdmin[],
) {
  const existingIds = new Set(members.map((member) => member.id));
  return [
    ...members,
    ...pendingMembers.filter((member) => !existingIds.has(member.id)),
  ];
}

export function TenantAdminsAndOwnersTab() {
  const auth = useAuth();
  const navigate = useNavigate();
  const _currentUserId = auth.user?.profile.sub;
  const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>();
  const tenantId = tenantIdParam ?? "";
  const queryClient = useQueryClient();
  const [searchTerm, setSearchTerm] = useState("");
  const [dialogMode, setDialogMode] = useState<DialogMode | null>(null);
  const [pendingOwners, setPendingOwners] = useState<TenantAdmin[]>([]);
  const [pendingAdmins, setPendingAdmins] = useState<TenantAdmin[]>([]);

  const ownersQuery = useQuery({
    queryKey: ["tenant-owners", tenantId],
    queryFn: () => fetchTenantOwners(tenantId),
    enabled: !!tenantId,
  });

  const adminsQuery = useQuery({
    queryKey: ["tenant-admins", tenantId],
    queryFn: () => fetchTenantAdmins(tenantId),
    enabled: !!tenantId,
  });

  const usersQuery = useQuery({
    queryKey: ["admin-users-search", searchTerm],
    queryFn: () => fetchUsers(20, 0, searchTerm),
    enabled: dialogMode !== null && searchTerm.length >= 2,
  });

  const addOwnerMutation = useMutation({
    mutationFn: (userId: string) => addTenantOwner(tenantId, userId),
    onMutate: async (userId) => {
      await queryClient.cancelQueries({
        queryKey: ["tenant-owners", tenantId],
      });
      const previousOwners = queryClient.getQueryData<TenantAdmin[]>([
        "tenant-owners",
        tenantId,
      ]);

      // Optimistically add to the list to prevent immediate double clicks
      const addedUser = searchResults.find((u) => u.id === userId);
      if (addedUser) {
        const optimisticOwner = {
          id: userId,
          name: addedUser.name,
          email: addedUser.email,
        };
        setPendingOwners((old) =>
          old.some((owner) => owner.id === userId)
            ? old
            : [...old, optimisticOwner],
        );
        queryClient.setQueryData<TenantAdmin[]>(
          ["tenant-owners", tenantId],
          (old) => {
            if (!old) return [optimisticOwner];
            if (old.some((o) => o.id === userId)) return old;
            return [...old, optimisticOwner];
          },
        );
      }
      return { previousOwners };
    },
    onSuccess: () => {
      // Delay invalidation slightly to give the backend outbox time to process
      setTimeout(() => {
        queryClient.invalidateQueries({
          queryKey: ["tenant-owners", tenantId],
        });
      }, 1000);
      toast.success(
        t("msg.admin.tenants.owners.add_success", "소유자가 추가되었습니다."),
      );
      setSearchTerm("");
    },
    onError: (err: AxiosError<{ error?: string }>, userId, context) => {
      setPendingOwners((old) => old.filter((owner) => owner.id !== userId));
      if (context?.previousOwners) {
        queryClient.setQueryData(
          ["tenant-owners", tenantId],
          context.previousOwners,
        );
      }
      toast.error(
        err.response?.data?.error ||
          t("msg.common.error", "오류가 발생했습니다."),
      );
    },
  });

  const removeOwnerMutation = useMutation({
    mutationFn: (userId: string) => removeTenantOwner(tenantId, userId),
    onMutate: async (userId) => {
      await queryClient.cancelQueries({
        queryKey: ["tenant-owners", tenantId],
      });
      const previousOwners = queryClient.getQueryData<TenantAdmin[]>([
        "tenant-owners",
        tenantId,
      ]);
      setPendingOwners((old) => old.filter((owner) => owner.id !== userId));
      queryClient.setQueryData<TenantAdmin[]>(
        ["tenant-owners", tenantId],
        (old) => (old ? old.filter((o) => o.id !== userId) : []),
      );
      return { previousOwners };
    },
    onSuccess: () => {
      setTimeout(() => {
        queryClient.invalidateQueries({
          queryKey: ["tenant-owners", tenantId],
        });
      }, 1000);
      toast.success(
        t(
          "msg.admin.tenants.owners.remove_success",
          "소유자 권한이 회수되었습니다.",
        ),
      );
    },
    onError: (err: AxiosError<{ error?: string }>, _userId, context) => {
      if (context?.previousOwners) {
        queryClient.setQueryData(
          ["tenant-owners", tenantId],
          context.previousOwners,
        );
      }
      toast.error(
        err.response?.data?.error ||
          t("msg.common.error", "오류가 발생했습니다."),
      );
    },
  });

  const addAdminMutation = useMutation({
    mutationFn: (userId: string) => addTenantAdmin(tenantId, userId),
    onMutate: async (userId) => {
      await queryClient.cancelQueries({
        queryKey: ["tenant-admins", tenantId],
      });
      const previousAdmins = queryClient.getQueryData<TenantAdmin[]>([
        "tenant-admins",
        tenantId,
      ]);

      const addedUser = searchResults.find((u) => u.id === userId);
      if (addedUser) {
        const optimisticAdmin = {
          id: userId,
          name: addedUser.name,
          email: addedUser.email,
        };
        setPendingAdmins((old) =>
          old.some((admin) => admin.id === userId)
            ? old
            : [...old, optimisticAdmin],
        );
        queryClient.setQueryData<TenantAdmin[]>(
          ["tenant-admins", tenantId],
          (old) => {
            if (!old) return [optimisticAdmin];
            if (old.some((a) => a.id === userId)) return old;
            return [...old, optimisticAdmin];
          },
        );
      }
      return { previousAdmins };
    },
    onSuccess: () => {
      setTimeout(() => {
        queryClient.invalidateQueries({
          queryKey: ["tenant-admins", tenantId],
        });
      }, 1000);
      toast.success(
        t("msg.admin.tenants.admins.add_success", "관리자가 추가되었습니다."),
      );
      setSearchTerm("");
    },
    onError: (err: AxiosError<{ error?: string }>, userId, context) => {
      setPendingAdmins((old) => old.filter((admin) => admin.id !== userId));
      if (context?.previousAdmins) {
        queryClient.setQueryData(
          ["tenant-admins", tenantId],
          context.previousAdmins,
        );
      }
      toast.error(
        err.response?.data?.error ||
          t("msg.common.error", "오류가 발생했습니다."),
      );
    },
  });

  const removeAdminMutation = useMutation({
    mutationFn: (userId: string) => removeTenantAdmin(tenantId, userId),
    onMutate: async (userId) => {
      await queryClient.cancelQueries({
        queryKey: ["tenant-admins", tenantId],
      });
      const previousAdmins = queryClient.getQueryData<TenantAdmin[]>([
        "tenant-admins",
        tenantId,
      ]);
      setPendingAdmins((old) => old.filter((admin) => admin.id !== userId));
      queryClient.setQueryData<TenantAdmin[]>(
        ["tenant-admins", tenantId],
        (old) => (old ? old.filter((a) => a.id !== userId) : []),
      );
      return { previousAdmins };
    },
    onSuccess: () => {
      setTimeout(() => {
        queryClient.invalidateQueries({
          queryKey: ["tenant-admins", tenantId],
        });
      }, 1000);
      toast.success(
        t("msg.admin.tenants.admins.remove_success", "권한이 회수되었습니다."),
      );
    },
    onError: (err: AxiosError<{ error?: string }>, _userId, context) => {
      if (context?.previousAdmins) {
        queryClient.setQueryData(
          ["tenant-admins", tenantId],
          context.previousAdmins,
        );
      }
      toast.error(
        err.response?.data?.error ||
          t("msg.common.error", "오류가 발생했습니다."),
      );
    },
  });

  const handleAddUser = (userId: string) => {
    if (dialogMode === "owner") {
      addOwnerMutation.mutate(userId);
    } else if (dialogMode === "admin") {
      addAdminMutation.mutate(userId);
    }
  };

  const _handleRemoveOwner = (userId: string, userName: string) => {
    if (
      window.confirm(
        t(
          "msg.admin.tenants.owners.remove_confirm",
          "소유자를 삭제하시겠습니까?",
          { name: userName },
        ),
      )
    ) {
      removeOwnerMutation.mutate(userId);
    }
  };

  const _handleRemoveAdmin = (userId: string, userName: string) => {
    if (
      window.confirm(
        t(
          "msg.admin.tenants.admins.remove_confirm",
          "관리자를 삭제하시겠습니까?",
          { name: userName },
        ),
      )
    ) {
      removeAdminMutation.mutate(userId);
    }
  };

  if (!tenantId) return null;

  const serverOwners = ownersQuery.data || [];
  const serverAdmins = adminsQuery.data || [];
  const currentOwners = mergePendingMembers(serverOwners, pendingOwners);
  const currentAdmins = mergePendingMembers(serverAdmins, pendingAdmins);
  const searchResults = usersQuery.data?.items || [];
  const isDialogOpen = dialogMode !== null;

  const dialogTitle =
    dialogMode === "owner"
      ? t("ui.admin.tenants.owners.dialog_title", "새 소유자 추가")
      : t("ui.admin.tenants.admins.dialog_title", "새 관리자 추가");

  const dialogDescription =
    dialogMode === "owner"
      ? t(
          "ui.admin.tenants.owners.dialog_description",
          "이름 또는 이메일로 사용자를 검색하세요.",
        )
      : t(
          "ui.admin.tenants.admins.dialog_description",
          "이름 또는 이메일로 사용자를 검색하세요.",
        );

  return (
    <div className="space-y-8 mt-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
      <div className="flex-1 flex flex-col lg:flex-row gap-8 min-h-0">
        {/* Owners Card */}
        <Card className="flex-1 flex flex-col min-h-0 border-none shadow-sm bg-[var(--color-panel)]">
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-7 flex-shrink-0">
            <div className="space-y-1">
              <CardTitle className="text-2xl font-bold flex items-center gap-2">
                <Crown className="h-6 w-6 text-yellow-500" />
                {t("ui.admin.tenants.owners.title", "테넌트 소유자")}
              </CardTitle>
              <CardDescription className="text-muted-foreground">
                {t(
                  "msg.admin.tenants.owners.subtitle",
                  "이 테넌트의 최상위 권한을 가진 소유자(조직장) 목록입니다.",
                )}
              </CardDescription>
            </div>
            <Button
              className="bg-primary text-primary-foreground hover:bg-primary/90"
              onClick={() => setDialogMode("owner")}
            >
              <UserPlus className="mr-2 h-4 w-4" />
              {t("ui.admin.tenants.owners.add_button", "소유자 추가")}
            </Button>
          </CardHeader>
          <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 className="w-[250px] font-bold">
                        {t("ui.admin.tenants.owners.table_name", "이름")}
                      </TableHead>
                      <TableHead className="font-bold">
                        {t("ui.admin.tenants.owners.table_email", "이메일")}
                      </TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {ownersQuery.isLoading ? (
                      <TableRow>
                        <TableCell colSpan={2} className="h-32 text-center">
                          <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary mx-auto" />
                        </TableCell>
                      </TableRow>
                    ) : currentOwners.length === 0 ? (
                      <TableRow>
                        <TableCell
                          colSpan={2}
                          className="h-32 text-center text-muted-foreground"
                        >
                          <div className="flex flex-col items-center gap-2">
                            <Users className="h-8 w-8 opacity-20" />
                            <p>
                              {t(
                                "msg.admin.tenants.owners.empty",
                                "등록된 소유자가 없습니다.",
                              )}
                            </p>
                          </div>
                        </TableCell>
                      </TableRow>
                    ) : (
                      currentOwners.map((owner) => (
                        <TableRow
                          key={owner.id}
                          className="hover:bg-muted/30 transition-colors group cursor-pointer"
                          onClick={() => navigate(`/users/${owner.id}`)}
                        >
                          <TableCell className="font-medium">
                            <div className="flex items-center gap-3">
                              <div className="h-8 w-8 rounded-lg bg-secondary flex items-center justify-center text-secondary-foreground font-bold text-xs">
                                {owner.name.charAt(0)}
                              </div>
                              <span>{owner.name}</span>
                            </div>
                          </TableCell>
                          <TableCell className="text-muted-foreground italic">
                            {owner.email}
                          </TableCell>
                        </TableRow>
                      ))
                    )}
                  </TableBody>
                </Table>
              </div>
            </div>
          </CardContent>
        </Card>

        {/* Admins Card */}
        <Card className="flex-1 flex flex-col min-h-0 border-none shadow-sm bg-[var(--color-panel)]">
          <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-7 flex-shrink-0">
            <div className="space-y-1">
              <CardTitle className="text-2xl font-bold flex items-center gap-2">
                <ShieldCheck className="h-6 w-6 text-primary" />
                {t("ui.admin.tenants.admins.title", "테넌트 관리자")}
              </CardTitle>
              <CardDescription className="text-muted-foreground">
                {t(
                  "msg.admin.tenants.admins.subtitle",
                  "이 테넌트의 자원을 관리할 수 있는 사용자 목록입니다.",
                )}
              </CardDescription>
            </div>
            <Button
              className="bg-primary text-primary-foreground hover:bg-primary/90"
              onClick={() => setDialogMode("admin")}
            >
              <UserPlus className="mr-2 h-4 w-4" />
              {t("ui.admin.tenants.admins.add_button", "관리자 추가")}
            </Button>
          </CardHeader>
          <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 className="w-[250px] font-bold">
                        {t("ui.admin.tenants.admins.table_name", "이름")}
                      </TableHead>
                      <TableHead className="font-bold">
                        {t("ui.admin.tenants.admins.table_email", "이메일")}
                      </TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {adminsQuery.isLoading ? (
                      <TableRow>
                        <TableCell colSpan={2} className="h-32 text-center">
                          <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary mx-auto" />
                        </TableCell>
                      </TableRow>
                    ) : currentAdmins.length === 0 ? (
                      <TableRow>
                        <TableCell
                          colSpan={2}
                          className="h-32 text-center text-muted-foreground"
                        >
                          <div className="flex flex-col items-center gap-2">
                            <Users className="h-8 w-8 opacity-20" />
                            <p>
                              {t(
                                "msg.admin.tenants.admins.empty",
                                "등록된 관리자가 없습니다.",
                              )}
                            </p>
                          </div>
                        </TableCell>
                      </TableRow>
                    ) : (
                      currentAdmins.map((admin) => (
                        <TableRow
                          key={admin.id}
                          className="hover:bg-muted/30 transition-colors group cursor-pointer"
                          onClick={() => navigate(`/users/${admin.id}`)}
                        >
                          <TableCell className="font-medium">
                            <div className="flex items-center gap-3">
                              <div className="h-8 w-8 rounded-lg bg-secondary flex items-center justify-center text-secondary-foreground font-bold text-xs">
                                {admin.name.charAt(0)}
                              </div>
                              <span>{admin.name}</span>
                            </div>
                          </TableCell>
                          <TableCell className="text-muted-foreground italic">
                            {admin.email}
                          </TableCell>
                        </TableRow>
                      ))
                    )}
                  </TableBody>
                </Table>
              </div>
            </div>
          </CardContent>
        </Card>
      </div>

      {/* Common Dialog for adding users */}
      <Dialog
        open={isDialogOpen}
        onOpenChange={(open) => {
          if (!open) {
            setDialogMode(null);
            setSearchTerm("");
          }
        }}
      >
        <DialogContent className="sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle className="text-xl font-bold">
              {dialogTitle}
            </DialogTitle>
            <DialogDescription>{dialogDescription}</DialogDescription>
          </DialogHeader>

          <div className="py-4 space-y-4">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
              <Input
                placeholder={t(
                  "ui.admin.tenants.admins.dialog_search_placeholder",
                  "사용자 검색 (최소 2자)...",
                )}
                className="pl-10 h-11"
                autoFocus
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
              />
            </div>

            <div className="max-h-[300px] overflow-y-auto rounded-lg border border-border">
              {searchTerm.length < 2 ? (
                <div className="p-10 text-center text-muted-foreground flex flex-col items-center gap-2">
                  <Search className="h-8 w-8 opacity-20" />
                  <p className="text-sm">
                    {t(
                      "ui.admin.tenants.admins.dialog_search_hint",
                      "검색어를 입력해 주세요.",
                    )}
                  </p>
                </div>
              ) : usersQuery.isLoading ? (
                <div className="p-10 text-center">
                  <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary mx-auto" />
                </div>
              ) : searchResults.length === 0 ? (
                <div className="p-10 text-center text-muted-foreground">
                  {t(
                    "ui.admin.tenants.admins.dialog_no_results",
                    "검색 결과가 없습니다.",
                  )}
                </div>
              ) : (
                <div className="divide-y divide-border">
                  {searchResults.map((user) => {
                    const isAlreadyOwner = currentOwners.some(
                      (o) => o.id === user.id,
                    );
                    const isAlreadyAdmin = currentAdmins.some(
                      (a) => a.id === user.id,
                    );
                    const isAlreadyMember =
                      dialogMode === "owner" ? isAlreadyOwner : isAlreadyAdmin;

                    return (
                      <div
                        key={user.id}
                        className="flex items-center justify-between p-3 hover:bg-muted/50 transition-colors"
                      >
                        <div className="flex items-center gap-3">
                          <div className="h-9 w-9 rounded-full bg-primary/10 flex items-center justify-center text-primary font-bold text-xs">
                            {user.name.charAt(0)}
                          </div>
                          <div className="flex flex-col">
                            <span className="text-sm font-medium">
                              {user.name}
                            </span>
                            <span className="text-xs text-muted-foreground">
                              {user.email}
                            </span>
                          </div>
                        </div>
                        <Button
                          size="sm"
                          variant={isAlreadyMember ? "ghost" : "outline"}
                          disabled={
                            isAlreadyMember ||
                            addOwnerMutation.isPending ||
                            addAdminMutation.isPending
                          }
                          onClick={() => handleAddUser(user.id)}
                        >
                          {isAlreadyMember ? (
                            <Badge variant="secondary" className="font-normal">
                              {dialogMode === "owner"
                                ? t(
                                    "ui.admin.tenants.owners.already_owner",
                                    "이미 소유자",
                                  )
                                : t(
                                    "ui.admin.tenants.admins.already_admin",
                                    "이미 관리자",
                                  )}
                            </Badge>
                          ) : (
                            <>
                              <Plus className="h-3 w-3 mr-1" />{" "}
                              {t("ui.common.add", "추가")}
                            </>
                          )}
                        </Button>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}

export default TenantAdminsAndOwnersTab;
