import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import { KeyRound, Plus, Search, ShieldCheck, X } from "lucide-react";
import { useDeferredValue, useMemo, useState } from "react";
import { useAuth } from "react-oidc-context";
import { PageHeader } from "../../../../common/core/components/page";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../components/ui/card";
import { Input } from "../../components/ui/input";
import { Label } from "../../components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../components/ui/table";
import { Textarea } from "../../components/ui/textarea";
import { toast } from "../../components/ui/use-toast";
import {
  createDeveloperGrant,
  type DevAssignableUser,
  fetchDeveloperGrants,
  fetchDevUser,
  fetchDevUsers,
  revokeDeveloperGrant,
} from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import { fetchMe } from "../auth/authApi";
import {
  type DeveloperAccessPage,
  developerAccessPageOptions,
  normalizeDeveloperAccessPageSelection,
  normalizeDeveloperAccessPages,
} from "../developer-access/developerAccessPages";

function formatUserLabel(user: DevAssignableUser) {
  const primary = user.name.trim() || user.email.trim();
  return `${primary} (${user.email.trim()})`;
}

export default function DeveloperGrantsPage() {
  const auth = useAuth();
  const queryClient = useQueryClient();
  const hasAccessToken = Boolean(auth.user?.access_token);
  const userProfile = auth.user?.profile as Record<string, unknown> | undefined;
  const role = resolveProfileRole(userProfile);

  const { data: me, isLoading: isLoadingMe } = useQuery({
    queryKey: ["userMe"],
    queryFn: fetchMe,
    enabled: hasAccessToken,
  });
  const profileRole = me?.role?.trim() || role;
  const isSuperAdmin = profileRole === "super_admin";

  const [userSearch, setUserSearch] = useState("");
  const deferredUserSearch = useDeferredValue(userSearch.trim());
  const [selectedUser, setSelectedUser] = useState<DevAssignableUser | null>(
    null,
  );
  const [selectedAccessPages, setSelectedAccessPages] = useState<
    DeveloperAccessPage[]
  >(["all"]);
  const [grantNotes, setGrantNotes] = useState("");
  const [adminNotes, setAdminNotes] = useState<Record<number, string>>({});

  const { data: userSearchData, isFetching: isUserSearchLoading } = useQuery({
    queryKey: ["developer-grant-users", deferredUserSearch],
    queryFn: () => fetchDevUsers(deferredUserSearch, 10),
    enabled:
      hasAccessToken &&
      isSuperAdmin &&
      deferredUserSearch.length > 0 &&
      selectedUser == null,
  });

  const { data: selectedUserDetail, isFetching: isSelectedUserDetailLoading } =
    useQuery({
      queryKey: ["developer-grant-user", selectedUser?.id],
      queryFn: () => fetchDevUser(selectedUser?.id || ""),
      enabled: hasAccessToken && isSuperAdmin && selectedUser != null,
    });

  const {
    data: grants,
    isLoading: isLoadingGrants,
    error: grantsError,
  } = useQuery({
    queryKey: ["developer-grants"],
    queryFn: () => fetchDeveloperGrants(),
    enabled: hasAccessToken && isSuperAdmin,
  });

  const grantList = grants ?? [];

  const filteredGrantedUsers = useMemo(() => {
    return [...grantList].sort((a, b) => {
      const tenantCompare = a.organization.localeCompare(b.organization);
      if (tenantCompare !== 0) {
        return tenantCompare;
      }
      return a.name.localeCompare(b.name);
    });
  }, [grantList]);

  const createGrantMutation = useMutation({
    mutationFn: createDeveloperGrant,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["developer-grants"] });
      toast(
        t(
          "msg.dev.grants.create_success",
          "개발자 권한이 직접 부여되었습니다.",
        ),
        "success",
      );
      setSelectedUser(null);
      setUserSearch("");
      setSelectedAccessPages(["all"]);
      setGrantNotes("");
    },
    onError: (err: AxiosError<{ error?: string }> | Error) => {
      toast(
        (err as AxiosError<{ error?: string }>).response?.data?.error ||
          (err as Error).message ||
          t("msg.common.error", "오류가 발생했습니다."),
        "error",
      );
    },
  });

  const revokeGrantMutation = useMutation({
    mutationFn: ({ id, adminNotes }: { id: number; adminNotes: string }) =>
      revokeDeveloperGrant(id, adminNotes),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["developer-grants"] });
      toast(
        t("msg.dev.grants.revoke_success", "개발자 권한이 회수되었습니다."),
        "success",
      );
    },
    onError: (err: AxiosError<{ error?: string }> | Error) => {
      toast(
        (err as AxiosError<{ error?: string }>).response?.data?.error ||
          (err as Error).message ||
          t("msg.common.error", "오류가 발생했습니다."),
        "error",
      );
    },
  });

  if (isLoadingMe) {
    return (
      <div className="p-8 text-center">
        {t("ui.common.loading", "Loading...")}
      </div>
    );
  }

  if (!isSuperAdmin) {
    return (
      <div className="space-y-6">
        <PageHeader
          icon={<ShieldCheck size={20} />}
          title={t("ui.dev.nav.developer_grants", "개발자 권한 부여")}
          description={t(
            "msg.dev.grants.forbidden_desc",
            "이 화면은 super admin만 사용할 수 있습니다.",
          )}
        />
        <Card className="border-amber-500/30 bg-amber-500/10">
          <CardContent className="p-4 text-sm text-foreground">
            {t(
              "msg.dev.grants.forbidden",
              "개발자 권한 직접 부여는 super admin만 사용할 수 있습니다.",
            )}
          </CardContent>
        </Card>
      </div>
    );
  }

  const handleGrant = () => {
    if (!selectedUser) {
      toast(
        t("msg.dev.grants.user_required", "부여할 사용자를 선택해주세요."),
        "error",
      );
      return;
    }
    const tenantId =
      selectedUserDetail?.tenant?.id?.trim() ||
      selectedUserDetail?.tenantSlug?.trim() ||
      selectedUserDetail?.companyCode?.trim() ||
      "";

    createGrantMutation.mutate({
      userId: selectedUser.id,
      tenantId,
      reason: grantNotes.trim() || "직접 부여",
      adminNotes: grantNotes.trim(),
      accessPages: normalizeDeveloperAccessPageSelection(selectedAccessPages),
    });
  };

  const handleSelectUser = (user: DevAssignableUser) => {
    setSelectedUser(user);
    setUserSearch(formatUserLabel(user));
    setSelectedAccessPages(["all"]);
  };

  const handleAccessPageToggle = (page: DeveloperAccessPage) => {
    setSelectedAccessPages((current) => {
      if (page === "all") {
        return ["all"];
      }
      const withoutAll = current.filter((item) => item !== "all");
      if (withoutAll.includes(page)) {
        const next = withoutAll.filter((item) => item !== page);
        return next.length > 0 ? next : ["all"];
      }
      return normalizeDeveloperAccessPageSelection([...withoutAll, page]);
    });
  };

  return (
    <div className="space-y-8">
      <PageHeader
        icon={<KeyRound size={20} />}
        title={t("ui.dev.nav.developer_grants", "개발자 권한 부여")}
        description={t(
          "msg.dev.grants.description",
          "사용자에게 개발자 권한을 직접 부여하고, 부여된 권한을 회수할 수 있습니다.",
        )}
        actions={
          <Badge variant="muted">
            {t("msg.dev.grants.count", "총 {{count}}건", {
              count: filteredGrantedUsers.length,
            })}
          </Badge>
        }
      />

      <Card className="glass-panel">
        <CardHeader>
          <CardTitle className="text-xl">
            {t("ui.dev.grants.form.title", "직접 부여")}
          </CardTitle>
          <CardDescription>
            {t(
              "msg.dev.grants.form.description",
              "사용자를 선택하면 현재 소속 정보가 표시되고, 그 사용자에게 개발자 권한을 즉시 부여합니다.",
            )}
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-5">
          <div className="grid gap-4 xl:grid-cols-[minmax(0,1.15fr)_minmax(0,0.85fr)]">
            <Card className="border-primary/10 bg-primary/5 shadow-sm">
              <CardHeader className="space-y-1 pb-3">
                <div className="flex items-center justify-between gap-2">
                  <CardTitle className="text-base">
                    {t("ui.dev.grants.user_section", "사용자 선택")}
                  </CardTitle>
                  <Badge variant="outline">
                    {t("ui.dev.grants.input_section", "입력")}
                  </Badge>
                </div>
                <CardDescription>
                  {t(
                    "msg.dev.grants.user_section_description",
                    "검색어를 입력해 사용자를 선택합니다. 선택 전에는 다음 단계 정보가 비어 있습니다.",
                  )}
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-2 pt-0">
                <div className="space-y-2">
                  <Label htmlFor="user-search">
                    {t("ui.dev.grants.user", "사용자")}{" "}
                    <span className="text-destructive">*</span>
                  </Label>
                  <div className="relative">
                    <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
                    <Input
                      id="user-search"
                      className="pl-10"
                      placeholder={t(
                        "ui.dev.grants.user_search_placeholder",
                        "이름 또는 이메일 검색...",
                      )}
                      value={userSearch}
                      onChange={(event) => {
                        setSelectedUser(null);
                        setUserSearch(event.target.value);
                      }}
                    />
                  </div>
                  {selectedUser && (
                    <p className="text-xs text-muted-foreground">
                      {t(
                        "msg.dev.grants.selected_user",
                        "선택된 사용자: {{user}}",
                        { user: formatUserLabel(selectedUser) },
                      )}
                    </p>
                  )}
                </div>

                {userSearch.trim() !== "" && selectedUser == null && (
                  <div className="mt-2 max-h-64 overflow-y-auto rounded-lg border border-border/70 bg-muted/20 shadow-sm">
                    {isUserSearchLoading ? (
                      <div className="px-3 py-3 text-sm text-muted-foreground">
                        {t(
                          "msg.dev.grants.search_loading",
                          "사용자를 찾는 중입니다...",
                        )}
                      </div>
                    ) : (userSearchData?.items ?? []).length > 0 ? (
                      (userSearchData?.items ?? []).map((user) => (
                        <button
                          key={user.id}
                          type="button"
                          className="flex w-full flex-col gap-1 border-b border-border/40 px-3 py-2 text-left last:border-b-0 hover:bg-primary/5"
                          onMouseDown={(event) => {
                            event.preventDefault();
                            handleSelectUser(user);
                          }}
                        >
                          <span className="text-sm font-semibold">
                            {user.name || user.email}
                          </span>
                          <span className="text-xs text-muted-foreground">
                            {user.email}
                            {user.loginId ? ` · ${user.loginId}` : ""}
                          </span>
                        </button>
                      ))
                    ) : (
                      <div className="px-3 py-4 text-center text-sm text-muted-foreground">
                        {t(
                          "msg.dev.grants.search_empty",
                          "검색 결과가 없습니다.",
                        )}
                      </div>
                    )}
                  </div>
                )}
              </CardContent>
            </Card>

            <Card className="border-dashed bg-muted/20 shadow-none">
              <CardHeader className="space-y-1 pb-3">
                <div className="flex items-center justify-between gap-2">
                  <CardTitle className="text-base">
                    {t("ui.dev.grants.selected_info", "선택된 사용자 정보")}
                  </CardTitle>
                  <Badge variant="secondary">
                    {t("ui.dev.grants.read_only", "읽기 전용")}
                  </Badge>
                </div>
                <CardDescription>
                  {t(
                    "msg.dev.grants.selected_info_description",
                    "선택된 사용자의 소속, 이메일, 전화번호를 확인합니다.",
                  )}
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4 pt-0">
                <div className="space-y-2">
                  <Label htmlFor="tenant-readonly">
                    {t("ui.dev.grants.tenant", "소속")}
                  </Label>
                  <Input
                    id="tenant-readonly"
                    className="border-dashed bg-background/70 text-foreground/90 shadow-none focus-visible:border-input focus-visible:ring-0 focus-visible:ring-offset-0"
                    value={
                      selectedUserDetail?.tenant?.name ||
                      selectedUserDetail?.tenantSlug ||
                      selectedUserDetail?.companyCode ||
                      (selectedUser && !isSelectedUserDetailLoading
                        ? t("ui.common.na", "없음")
                        : "")
                    }
                    readOnly
                    placeholder={
                      selectedUser
                        ? isSelectedUserDetailLoading
                          ? t("msg.common.loading", "Loading...")
                          : t(
                              "msg.dev.grants.tenant_missing",
                              "선택한 사용자의 테넌트 정보가 없습니다.",
                            )
                        : t(
                            "msg.dev.grants.user_required",
                            "부여할 사용자를 선택해주세요.",
                          )
                    }
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="email-readonly">
                    {t("ui.dev.grants.email", "이메일")}
                  </Label>
                  <Input
                    id="email-readonly"
                    className="border-dashed bg-background/70 text-foreground/90 shadow-none focus-visible:border-input focus-visible:ring-0 focus-visible:ring-offset-0"
                    value={
                      selectedUserDetail?.email || selectedUser?.email || ""
                    }
                    readOnly
                    placeholder={t(
                      "msg.dev.grants.user_required",
                      "부여할 사용자를 선택해주세요.",
                    )}
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="phone-readonly">
                    {t("ui.dev.grants.phone", "전화번호")}
                  </Label>
                  <Input
                    id="phone-readonly"
                    className="border-dashed bg-background/70 text-foreground/90 shadow-none focus-visible:border-input focus-visible:ring-0 focus-visible:ring-offset-0"
                    value={selectedUserDetail?.phone || ""}
                    readOnly
                    placeholder={t(
                      "msg.dev.grants.phone_missing",
                      "등록된 전화번호가 없습니다.",
                    )}
                  />
                </div>

                <div className="space-y-2">
                  <Label>
                    {t("ui.dev.grants.pages", "권한 페이지")}{" "}
                    <span className="text-destructive">*</span>
                  </Label>
                  <div className="grid gap-2 rounded-lg border border-border/60 bg-muted/20 p-3">
                    {developerAccessPageOptions.map((option) => {
                      const checked =
                        option.value === "all"
                          ? selectedAccessPages.includes("all")
                          : selectedAccessPages.includes(option.value);
                      return (
                        <label
                          key={option.value}
                          className="flex items-center gap-3 rounded-md px-2 py-1.5 text-sm hover:bg-background/60"
                        >
                          <input
                            type="checkbox"
                            checked={checked}
                            onChange={() =>
                              handleAccessPageToggle(option.value)
                            }
                          />
                          <span className="font-medium">{option.label}</span>
                        </label>
                      );
                    })}
                  </div>
                  <p className="text-xs text-muted-foreground">
                    {t(
                      "msg.dev.grants.pages_hint",
                      "전체를 선택하면 개요, 연동 앱 추가, 감사로그가 모두 포함됩니다.",
                    )}
                  </p>
                </div>
              </CardContent>
            </Card>
          </div>

          <Card className="border-border/70 bg-background/80 shadow-sm">
            <CardHeader className="space-y-1 pb-3">
              <div className="flex items-center justify-between gap-2">
                <CardTitle className="text-base">
                  {t("ui.dev.grants.admin_notes", "부여 사유")}
                </CardTitle>
              </div>
              <CardDescription>
                {t(
                  "msg.dev.grants.admin_notes_description",
                  "직접 부여의 근거를 간단히 남겨 두면 추후 회수와 검토에 도움이 됩니다.",
                )}
              </CardDescription>
            </CardHeader>
            <CardContent className="space-y-3 pt-0">
              <Textarea
                id="admin-notes"
                value={grantNotes}
                onChange={(event) => setGrantNotes(event.target.value)}
                className="min-h-[132px] bg-background"
                placeholder={t(
                  "msg.dev.grants.admin_notes_placeholder",
                  "예: 테스트 환경 확인 후 권한 부여",
                )}
              />
              <p className="text-xs text-muted-foreground">
                {t(
                  "msg.dev.grants.admin_notes_hint",
                  "회수는 목록의 회수 버튼으로 처리합니다.",
                )}
              </p>
            </CardContent>
          </Card>

          <div className="flex justify-end">
            <Button
              onClick={handleGrant}
              disabled={createGrantMutation.isPending}
              className="gap-2"
            >
              <Plus className="h-4 w-4" />
              {createGrantMutation.isPending
                ? t("ui.common.submitting", "제출 중...")
                : t("ui.dev.grants.grant", "직접 부여")}
            </Button>
          </div>
        </CardContent>
      </Card>

      <Card className="glass-panel">
        <CardHeader>
          <CardTitle className="text-xl">
            {t("ui.dev.grants.list.title", "부여된 권한")}
          </CardTitle>
          <CardDescription>
            {t(
              "msg.dev.grants.list.description",
              "현재 부여된 개발자 권한 목록입니다.",
            )}
          </CardDescription>
        </CardHeader>
        <CardContent>
          {isLoadingGrants ? (
            <div className="py-8 text-center text-sm text-muted-foreground">
              {t("msg.common.loading", "Loading...")}
            </div>
          ) : grantsError ? (
            <div className="rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive">
              {t(
                "msg.dev.grants.load_error",
                "개발자 권한 목록을 불러오지 못했습니다.",
              )}
            </div>
          ) : filteredGrantedUsers.length === 0 ? (
            <div className="py-8 text-center text-sm text-muted-foreground">
              {t("msg.dev.grants.empty", "부여된 권한이 없습니다.")}
            </div>
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>{t("ui.dev.grants.user", "사용자")}</TableHead>
                  <TableHead>{t("ui.dev.grants.tenant", "테넌트")}</TableHead>
                  <TableHead>
                    {t("ui.dev.grants.reason", "부여 사유")}
                  </TableHead>
                  <TableHead>
                    {t("ui.dev.grants.pages", "권한 페이지")}
                  </TableHead>
                  <TableHead>{t("ui.dev.grants.status", "상태")}</TableHead>
                  <TableHead>{t("ui.dev.grants.date", "부여일")}</TableHead>
                  <TableHead className="text-right">
                    {t("ui.dev.grants.actions", "관리")}
                  </TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {filteredGrantedUsers.map((grant) => (
                  <TableRow key={grant.id}>
                    <TableCell>
                      <div className="space-y-1">
                        <div className="font-medium">
                          {grant.name || grant.email || grant.userId}
                        </div>
                        <div className="text-xs text-muted-foreground">
                          {grant.email || grant.userId}
                        </div>
                        <div className="font-mono text-xs text-muted-foreground">
                          {grant.userId}
                        </div>
                      </div>
                    </TableCell>
                    <TableCell>
                      <div className="space-y-1">
                        <div className="font-medium">
                          {grant.organization ||
                            grant.tenantId ||
                            t("ui.common.na", "없음")}
                        </div>
                        <div className="font-mono text-xs text-muted-foreground">
                          {grant.tenantId || t("ui.common.na", "없음")}
                        </div>
                      </div>
                    </TableCell>
                    <TableCell className="max-w-md">
                      <div className="truncate" title={grant.reason}>
                        {grant.reason}
                      </div>
                      {grant.adminNotes && (
                        <div className="mt-1 text-xs text-muted-foreground">
                          {grant.adminNotes}
                        </div>
                      )}
                    </TableCell>
                    <TableCell>
                      <div className="flex flex-wrap gap-1">
                        {(grant.accessPages?.length
                          ? normalizeDeveloperAccessPages(grant.accessPages)
                          : ["all"]
                        ).map((page) => (
                          <Badge key={page} variant="outline">
                            {developerAccessPageOptions.find(
                              (option) => option.value === page,
                            )?.label ?? page}
                          </Badge>
                        ))}
                      </div>
                    </TableCell>
                    <TableCell>
                      <Badge variant="success">
                        {t("ui.dev.grants.approved", "승인됨")}
                      </Badge>
                    </TableCell>
                    <TableCell className="text-sm text-muted-foreground">
                      {new Date(grant.createdAt).toLocaleDateString()}
                    </TableCell>
                    <TableCell className="text-right">
                      <div className="ml-auto flex min-w-[220px] flex-col items-end gap-2">
                        <Input
                          placeholder={t(
                            "ui.dev.grants.revoke_notes_placeholder",
                            "회수 메모 (선택)...",
                          )}
                          className="h-8 text-xs"
                          value={adminNotes[grant.id] || ""}
                          onChange={(event) =>
                            setAdminNotes({
                              ...adminNotes,
                              [grant.id]: event.target.value,
                            })
                          }
                        />
                        <Button
                          size="sm"
                          variant="outline"
                          className="text-destructive hover:bg-destructive/10"
                          disabled={revokeGrantMutation.isPending}
                          onClick={() => {
                            revokeGrantMutation.mutate({
                              id: grant.id,
                              adminNotes: adminNotes[grant.id] || "",
                            });
                          }}
                        >
                          <X className="mr-1 h-3 w-3" />
                          {t("ui.dev.grants.revoke", "회수")}
                        </Button>
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
