import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  Plus,
  Search,
  ShieldCheck,
  UserPlus,
} from "lucide-react";
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { useTenantPermission } from "../hooks/useTenantPermission";
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 {
  fetchUsers,
  fetchTenantRelations,
  addTenantRelation,
  removeTenantRelation,
  type TenantRelation,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";
import { Trash2 } from "lucide-react";

interface TenantFineGrainedPermissionsTabProps {
  tenantIdProp?: string;
}

export function TenantFineGrainedPermissionsTab({ tenantIdProp }: TenantFineGrainedPermissionsTabProps = {}) {
  const { tenantId: tenantIdParam } = useParams<{ tenantId: string }>();
  const tenantId = tenantIdProp || tenantIdParam || "";
  const { hasPermission } = useTenantPermission(tenantId);
  const isWritable = hasPermission("manage_admins");
  const queryClient = useQueryClient();
  const [searchTerm, setSearchTerm] = useState("");
  const [isDialogOpen, setIsDialogOpen] = useState(false);

  // 🌟 테넌트 탭별 드롭다운 즉각 변경을 위한 임시 로컬 맵 선언
  const [localTenantPermissions, setLocalTenantPermissions] = useState<Record<string, Record<string, "none" | "read" | "write">>>({});

  const relationsQuery = useQuery({
    queryKey: ["tenant-relations", tenantId],
    queryFn: () => fetchTenantRelations(tenantId),
    enabled: !!tenantId,
  });
  const relationsData = relationsQuery.data ?? [];

  // 🌟 서버 데이터를 수신하면 로컬 변경 상태 맵을 실시간 동기화
  useEffect(() => {
    if (relationsQuery.data) {
      const initialMap: Record<string, Record<string, "none" | "read" | "write">> = {};
      for (const user of relationsQuery.data) {
        initialMap[user.userId] = {};
        const tabs = ["profile", "permissions", "organization", "schema"];
        for (const tab of tabs) {
          const isWrite = user.relations.includes(`${tab}_managers`);
          const isRead = user.relations.includes(`${tab}_viewers`);
          initialMap[user.userId][tab] = isWrite ? "write" : isRead ? "read" : "none";
        }
      }
      setLocalTenantPermissions(initialMap);
    }
  }, [relationsQuery.data]);
  const relations = relationsQuery.data ?? [];

  const invalidateAllQueries = () => {
    queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
    queryClient.invalidateQueries({ queryKey: ["tenant", tenantId] });
    queryClient.invalidateQueries({ queryKey: ["me"] });
    setTimeout(() => {
      queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] });
      queryClient.invalidateQueries({ queryKey: ["tenant", tenantId] });
      queryClient.invalidateQueries({ queryKey: ["me"] });
    }, 500);
  };

  const addRelationMutation = useMutation({
    mutationFn: (payload: { userId: string; relation: string }) =>
      addTenantRelation(tenantId, payload.userId, payload.relation),
    onMutate: async (newRelation) => {
      await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] });
      const previousRelations = queryClient.getQueryData<TenantRelation[]>(["tenant-relations", tenantId]);

      queryClient.setQueryData<TenantRelation[]>(["tenant-relations", tenantId], (old) => {
        if (!old) return [];
        return old.map((user) => {
          if (user.userId === newRelation.userId) {
            return {
              ...user,
              relations: user.relations.includes(newRelation.relation)
                ? user.relations
                : [...user.relations, newRelation.relation],
            };
          }
          return user;
        });
      });

      return { previousRelations };
    },
    onError: (err: AxiosError<{ error?: string }>, _, context) => {
      if (context?.previousRelations) {
        queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations);
      }
      toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
    },
    onSuccess: () => {
      // Quiet mutate
    },
  });

  const removeRelationMutation = useMutation({
    mutationFn: (payload: { userId: string; relation: string }) =>
      removeTenantRelation(tenantId, payload.userId, payload.relation),
    onMutate: async (targetRelation) => {
      await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] });
      const previousRelations = queryClient.getQueryData<TenantRelation[]>(["tenant-relations", tenantId]);

      queryClient.setQueryData<TenantRelation[]>(["tenant-relations", tenantId], (old) => {
        if (!old) return [];
        return old.map((user) => {
          if (user.userId === targetRelation.userId) {
            return {
              ...user,
              relations: user.relations.filter((r) => r !== targetRelation.relation),
            };
          }
          return user;
        });
      });

      return { previousRelations };
    },
    onError: (err: AxiosError<{ error?: string }>, _, context) => {
      if (context?.previousRelations) {
        queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations);
      }
      toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다."));
    },
    onSuccess: () => {
      // Quiet mutate
    },
  });

  const handleRelationChange = async (
    userId: string,
    tab: "profile" | "permissions" | "organization" | "schema",
    currentVal: "none" | "read" | "write",
    newVal: "none" | "read" | "write",
  ) => {
    const readRel = `${tab}_viewers`;
    const writeRel = `${tab}_managers`;

    if (currentVal === newVal) return;

    try {
      if (currentVal === "read") {
        await removeRelationMutation.mutateAsync({ userId, relation: readRel });
      } else if (currentVal === "write") {
        await removeRelationMutation.mutateAsync({ userId, relation: writeRel });
      }

      if (newVal === "read") {
        await addRelationMutation.mutateAsync({ userId, relation: readRel });
      } else if (newVal === "write") {
        await addRelationMutation.mutateAsync({ userId, relation: writeRel });
      }

      invalidateAllQueries();

      // 🌟 Trigger a single consolidated success toast at the very end
      toast.success(t("msg.admin.tenants.relations.update_success", "세부 권한이 성공적으로 변경되었습니다."));
    } catch {
      // Individual mutations handle error toast via onError
    }
  };

  const handleRemoveAllRelations = async (userId: string, userRelations: string[]) => {
    if (!window.confirm(t("msg.admin.tenants.relations.remove_all_confirm", "이 사용자의 모든 세부 권한을 삭제하시겠습니까?"))) {
      return;
    }
    for (const rel of userRelations) {
      await removeRelationMutation.mutateAsync({ userId, relation: rel });
    }
    invalidateAllQueries();
  };

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

  const handleAddUser = (userId: string) => {
    addRelationMutation.mutate({ userId, relation: "profile_viewers" }, {
      onSettled: () => {
        invalidateAllQueries();
      }
    });
    setIsDialogOpen(false);
    setSearchTerm("");
  };

  if (!tenantId) return null;

  const searchResults = usersQuery.data?.items || [];

  return (
    <div className="space-y-8 mt-6 flex flex-col h-auto pb-10">
      <Card className="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.relations.title", "세부 권한 설정 (Fine-grained Permissions)")}
            </CardTitle>
            <CardDescription className="text-muted-foreground">
              {t(
                "msg.admin.tenants.relations.subtitle",
                "사용자별로 각 탭의 세부 조회 및 수정 권한을 격리하여 할당합니다. 상위 상속 권한은 자동으로 보존됩니다.",
              )}
            </CardDescription>
          </div>
          <Button
            className="bg-primary text-primary-foreground hover:bg-primary/90"
            onClick={() => setIsDialogOpen(true)}
            disabled={!isWritable}
          >
            <UserPlus className="mr-2 h-4 w-4" />
            {t("ui.admin.tenants.relations.add_button", "세부 권한 사용자 추가")}
          </Button>
        </CardHeader>
        <CardContent className="pt-0">
          <div className="rounded-md border border-border overflow-hidden">
            <Table>
              <TableHeader className="bg-secondary/40">
                <TableRow>
                  <TableHead className="font-bold">{t("ui.common.name", "이름")}</TableHead>
                  <TableHead className="font-bold">{t("ui.admin.tenants.detail.tab_profile", "테넌트 프로필")}</TableHead>
                  <TableHead className="font-bold">{t("ui.admin.tenants.detail.tab_permissions", "권한 관리")}</TableHead>
                  <TableHead className="font-bold">{t("ui.admin.tenants.detail.tab_organization", "조직 관리")}</TableHead>
                  <TableHead className="font-bold">{t("ui.admin.tenants.detail.tab_schema", "사용자 스키마")}</TableHead>
                  <TableHead className="font-bold text-center w-20">{t("ui.common.action", "작업")}</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {relations.length === 0 ? (
                  <TableRow>
                    <TableCell colSpan={6} className="text-center py-12 text-muted-foreground">
                      {t("msg.admin.tenants.relations.empty", "세부 권한이 지정된 사용자가 없습니다. 사용자를 추가해 설정하세요.")}
                    </TableCell>
                  </TableRow>
                ) : (
                  relations.map((user) => {
                    const profileVal = user.relations.includes("profile_managers")
                      ? "write"
                      : user.relations.includes("profile_viewers")
                      ? "read"
                      : "none";

                    const permissionsVal = user.relations.includes("permissions_managers")
                      ? "write"
                      : user.relations.includes("permissions_viewers")
                      ? "read"
                      : "none";

                    const organizationVal = user.relations.includes("organization_managers")
                      ? "write"
                      : user.relations.includes("organization_viewers")
                      ? "read"
                      : "none";

                    const schemaVal = user.relations.includes("schema_managers")
                      ? "write"
                      : user.relations.includes("schema_viewers")
                      ? "read"
                      : "none";

                    const curProfileVal = localTenantPermissions[user.userId]?.profile ?? profileVal;
                    const curPermissionsVal = localTenantPermissions[user.userId]?.permissions ?? permissionsVal;
                    const curOrganizationVal = localTenantPermissions[user.userId]?.organization ?? organizationVal;
                    const curSchemaVal = localTenantPermissions[user.userId]?.schema ?? schemaVal;

                    return (
                      <TableRow key={user.userId} className="hover:bg-muted/10 transition-colors">
                        <TableCell className="font-medium">
                          <div className="flex flex-col">
                            <span className="font-semibold text-foreground">{user.name}</span>
                            <span className="text-xs text-muted-foreground italic">{user.email}</span>
                          </div>
                        </TableCell>
                        <TableCell>
                          <select
                            className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                            value={curProfileVal}
                            disabled={!isWritable}
                            name={`tenant-fine-grained-profile-${user.userId}`}
                            onChange={(e) => {
                              const nextVal = e.target.value as "none" | "read" | "write";
                              setLocalTenantPermissions(prev => ({
                                ...prev,
                                [user.userId]: {
                                  ...(prev[user.userId] ?? {}),
                                  profile: nextVal
                                }
                              }));
                              handleRelationChange(
                                user.userId,
                                "profile",
                                profileVal,
                                nextVal,
                              );
                            }}
                          >
                            <option value="none">{t("ui.common.none", "권한 없음")}</option>
                            <option value="read">{t("ui.common.read", "조회 가능 (Read)")}</option>
                            <option value="write">{t("ui.common.write", "수정 가능 (Write)")}</option>
                          </select>
                        </TableCell>
                        <TableCell>
                          <select
                            className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                            value={curPermissionsVal}
                            disabled={!isWritable}
                            name={`tenant-fine-grained-permissions-${user.userId}`}
                            onChange={(e) => {
                              const nextVal = e.target.value as "none" | "read" | "write";
                              setLocalTenantPermissions(prev => ({
                                ...prev,
                                [user.userId]: {
                                  ...(prev[user.userId] ?? {}),
                                  permissions: nextVal
                                }
                              }));
                              handleRelationChange(
                                user.userId,
                                "permissions",
                                permissionsVal,
                                nextVal,
                              );
                            }}
                          >
                            <option value="none">{t("ui.common.none", "권한 없음")}</option>
                            <option value="read">{t("ui.common.read", "조회 가능 (Read)")}</option>
                            <option value="write">{t("ui.common.write", "수정 가능 (Write)")}</option>
                          </select>
                        </TableCell>
                        <TableCell>
                          <select
                            className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                            value={curOrganizationVal}
                            disabled={!isWritable}
                            name={`tenant-fine-grained-organization-${user.userId}`}
                            onChange={(e) => {
                              const nextVal = e.target.value as "none" | "read" | "write";
                              setLocalTenantPermissions(prev => ({
                                ...prev,
                                [user.userId]: {
                                  ...(prev[user.userId] ?? {}),
                                  organization: nextVal
                                }
                              }));
                              handleRelationChange(
                                user.userId,
                                "organization",
                                organizationVal,
                                nextVal,
                              );
                            }}
                          >
                            <option value="none">{t("ui.common.none", "권한 없음")}</option>
                            <option value="read">{t("ui.common.read", "조회 가능 (Read)")}</option>
                            <option value="write">{t("ui.common.write", "수정 가능 (Write)")}</option>
                          </select>
                        </TableCell>
                        <TableCell>
                          <select
                            className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                            value={curSchemaVal}
                            disabled={!isWritable}
                            name={`tenant-fine-grained-schema-${user.userId}`}
                            onChange={(e) => {
                              const nextVal = e.target.value as "none" | "read" | "write";
                              setLocalTenantPermissions(prev => ({
                                ...prev,
                                [user.userId]: {
                                  ...(prev[user.userId] ?? {}),
                                  schema: nextVal
                                }
                              }));
                              handleRelationChange(
                                user.userId,
                                "schema",
                                schemaVal,
                                nextVal,
                              );
                            }}
                          >
                            <option value="none">{t("ui.common.none", "권한 없음")}</option>
                            <option value="read">{t("ui.common.read", "조회 가능 (Read)")}</option>
                            <option value="write">{t("ui.common.write", "수정 가능 (Write)")}</option>
                          </select>
                        </TableCell>
                        <TableCell className="text-center">
                          <Button
                            variant="ghost"
                            size="icon"
                            disabled={!isWritable}
                            onClick={() => handleRemoveAllRelations(user.userId, user.relations)}
                          >
                            <Trash2 className="h-4 w-4 text-destructive" />
                          </Button>
                        </TableCell>
                      </TableRow>
                    );
                  })
                )}
              </TableBody>
            </Table>
          </div>
        </CardContent>
      </Card>

      {/* Common Dialog for adding users */}
      <Dialog
        open={isDialogOpen}
        onOpenChange={(open) => {
          if (!open) {
            setIsDialogOpen(false);
            setSearchTerm("");
          }
        }}
      >
        <DialogContent className="sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle className="text-xl font-bold">
              {t("ui.admin.tenants.relations.dialog_title", "세부 권한 관리 유저 추가")}
            </DialogTitle>
            <DialogDescription>
              {t(
                "ui.admin.tenants.admins.dialog_description",
                "이름 또는 이메일로 사용자를 검색하세요.",
              )}
            </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 isAlreadyInMatrix = relations.some(
                      (r) => r.userId === user.id,
                    );

                    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={isAlreadyInMatrix ? "ghost" : "outline"}
                          disabled={
                            isAlreadyInMatrix ||
                            addRelationMutation.isPending
                          }
                          onClick={() => handleAddUser(user.id)}
                        >
                          {isAlreadyInMatrix ? (
                            <Badge variant="secondary" className="font-normal">
                              {t(
                                "ui.admin.tenants.relations.already_added",
                                "이미 추가됨",
                              )}
                            </Badge>
                          ) : (
                            <>
                              <Plus className="h-3 w-3 mr-1" />{" "}
                              {t("ui.common.add", "추가")}
                            </>
                          )}
                        </Button>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
