import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Key, Plus, Save, Trash2, Users } from "lucide-react";
import * as React from "react";
import { Link } from "react-router-dom";
import { PageHeader } from "../../../../common/core/components/page";
import { Button } from "../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../components/ui/card";
import { Input } from "../../components/ui/input";
import { toast } from "../../components/ui/use-toast";
import {
  fetchGlobalCustomClaimDefinitions,
  type GlobalCustomClaimDefinition,
  type GlobalCustomClaimPermission,
  updateGlobalCustomClaimDefinitions,
} from "../../lib/adminApi";
import { t } from "../../lib/i18n";

type ClaimDraft = GlobalCustomClaimDefinition & { id: string };

const valueTypes: GlobalCustomClaimDefinition["valueType"][] = [
  "text",
  "number",
  "boolean",
  "array",
  "object",
  "date",
  "datetime",
];

const permissions: GlobalCustomClaimPermission[] = [
  "admin_only",
  "user_and_admin",
];

function toDrafts(items: GlobalCustomClaimDefinition[]): ClaimDraft[] {
  return items.map((item, index) => ({
    id: `${item.key || "claim"}-${index}`,
    key: item.key,
    label: item.label,
    valueType: item.valueType || "text",
    readPermission: item.readPermission || "admin_only",
    writePermission: item.writePermission || "admin_only",
    description: item.description || "",
  }));
}

function toDefinitions(drafts: ClaimDraft[]): GlobalCustomClaimDefinition[] {
  return drafts
    .map((draft) => normalizeClaimDraftPermissions(draft))
    .map((draft) => ({
      key: draft.key.trim(),
      label: draft.label.trim(),
      valueType: draft.valueType,
      readPermission: draft.readPermission,
      writePermission: draft.writePermission,
      description: draft.description?.trim(),
    }))
    .filter((draft) => draft.key.length > 0);
}

function normalizeClaimDraftPermissions(draft: ClaimDraft): ClaimDraft {
  if (draft.writePermission !== "user_and_admin") {
    return draft;
  }
  return {
    ...draft,
    readPermission: "user_and_admin",
  };
}

function permissionLabel(permission: GlobalCustomClaimPermission) {
  return permission === "user_and_admin"
    ? t(
        "ui.common.custom_claim_permission.user_and_admin",
        "사용자 및 관리자 가능",
      )
    : t("ui.common.custom_claim_permission.admin_only", "관리자만 가능");
}

export default function GlobalCustomClaimsPage() {
  const queryClient = useQueryClient();
  const [drafts, setDrafts] = React.useState<ClaimDraft[]>([]);

  const query = useQuery({
    queryKey: ["global-custom-claim-definitions"],
    queryFn: fetchGlobalCustomClaimDefinitions,
  });

  React.useEffect(() => {
    if (query.data) {
      setDrafts(toDrafts(query.data.items));
    }
  }, [query.data]);

  const mutation = useMutation({
    mutationFn: updateGlobalCustomClaimDefinitions,
    onSuccess: (data) => {
      queryClient.setQueryData(["global-custom-claim-definitions"], data);
      toast.success(t("msg.info.saved_success", "저장되었습니다."));
    },
    onError: () => {
      toast.error(t("err.common.unknown", "오류가 발생했습니다."));
    },
  });

  const addClaim = () => {
    setDrafts((current) => [
      ...current,
      {
        id: `global-claim-${Date.now()}`,
        key: "",
        label: "",
        valueType: "text",
        readPermission: "admin_only",
        writePermission: "admin_only",
        description: "",
      },
    ]);
  };

  const updateClaim = (id: string, patch: Partial<ClaimDraft>) => {
    setDrafts((current) =>
      current.map((draft) =>
        draft.id === id
          ? normalizeClaimDraftPermissions({ ...draft, ...patch })
          : draft,
      ),
    );
  };

  const removeClaim = (id: string) => {
    setDrafts((current) => current.filter((draft) => draft.id !== id));
  };

  const saveClaims = () => {
    mutation.mutate({ items: toDefinitions(drafts) });
  };

  return (
    <div className="space-y-6">
      <PageHeader
        titleAs="h2"
        icon={<Key size={20} />}
        title={t(
          "ui.admin.users.global_custom_claims.title",
          "전역 Claim 설정",
        )}
        description={t(
          "msg.admin.users.global_custom_claims.description",
          "모든 RP에 공통 적용할 사용자 claim 정의와 사용자의 읽기/쓰기 권한 기본값을 관리합니다. 쓰기 허용 시 읽기도 자동으로 허용됩니다.",
        )}
        actions={
          <>
            <Button asChild variant="outline" size="sm" className="h-9">
              <Link to="/users">
                <Users size={16} />
                {t("ui.admin.users.list.title", "사용자 관리")}
              </Link>
            </Button>
            <Button
              type="button"
              variant="outline"
              size="sm"
              className="h-9 gap-2"
              onClick={addClaim}
            >
              <Plus size={16} />
              {t("ui.common.add", "추가")}
            </Button>
            <Button
              type="button"
              size="sm"
              className="h-9 gap-2"
              disabled={mutation.isPending}
              onClick={saveClaims}
            >
              <Save size={16} />
              {t("ui.common.save", "저장")}
            </Button>
          </>
        }
      />

      <Card className="bg-[var(--color-panel)]">
        <CardHeader>
          <CardTitle className="text-lg">
            {t(
              "ui.admin.users.global_custom_claims.registry",
              "Global Claim Registry",
            )}
          </CardTitle>
          <CardDescription>
            {t(
              "msg.admin.users.global_custom_claims.registry",
              "정의된 claim key만 사용자 상세의 전역 claim 값 관리 대상이 됩니다. 읽기/쓰기는 관리자 권한이 아니라 사용자가 본인 claim 값을 조회하거나 수정할 수 있는지에 대한 설정입니다.",
            )}
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          {query.isLoading ? (
            <div className="py-12 text-center text-sm text-muted-foreground">
              {t("ui.common.loading", "로딩 중...")}
            </div>
          ) : drafts.length === 0 ? (
            <div className="rounded-lg border border-dashed py-12 text-center text-sm text-muted-foreground">
              {t(
                "msg.admin.users.global_custom_claims.empty",
                "정의된 전역 claim이 없습니다.",
              )}
            </div>
          ) : (
            drafts.map((claim) => (
              <div
                key={claim.id}
                className="grid gap-3 rounded-md border bg-background p-3 lg:grid-cols-[minmax(160px,0.8fr)_minmax(160px,0.8fr)_130px_160px_160px_minmax(220px,1fr)_40px]"
              >
                <Input
                  value={claim.key}
                  name={`global-claim-definition-key-${claim.id}`}
                  className="font-mono text-xs"
                  placeholder="claim_key"
                  data-testid={`global-claim-definition-key-${claim.key || claim.id}`}
                  onChange={(event) =>
                    updateClaim(claim.id, { key: event.target.value })
                  }
                />
                <Input
                  value={claim.label}
                  name={`global-claim-definition-label-${claim.id}`}
                  placeholder={t(
                    "ui.admin.users.global_custom_claims.label_placeholder",
                    "표시 이름",
                  )}
                  data-testid={`global-claim-definition-label-${claim.key || claim.id}`}
                  onChange={(event) =>
                    updateClaim(claim.id, { label: event.target.value })
                  }
                />
                <select
                  aria-label={t(
                    "ui.admin.users.global_custom_claims.value_type",
                    "Claim 타입",
                  )}
                  value={claim.valueType}
                  name={`global-claim-definition-value-type-${claim.id}`}
                  className="h-10 rounded-md border border-input bg-background px-3 text-sm"
                  onChange={(event) =>
                    updateClaim(claim.id, {
                      valueType: event.target
                        .value as GlobalCustomClaimDefinition["valueType"],
                    })
                  }
                >
                  {valueTypes.map((valueType) => (
                    <option key={valueType} value={valueType}>
                      {valueType}
                    </option>
                  ))}
                </select>
                <select
                  aria-label={t(
                    "ui.admin.users.global_custom_claims.read_permission",
                    "읽기 권한",
                  )}
                  value={claim.readPermission}
                  name={`global-claim-definition-read-permission-${claim.id}`}
                  className="h-10 rounded-md border border-input bg-background px-3 text-sm"
                  data-testid={`global-claim-definition-read-permission-${claim.key || claim.id}`}
                  onChange={(event) =>
                    updateClaim(claim.id, {
                      readPermission: event.target
                        .value as GlobalCustomClaimPermission,
                    })
                  }
                >
                  {permissions.map((permission) => (
                    <option key={permission} value={permission}>
                      {permissionLabel(permission)}
                    </option>
                  ))}
                </select>
                <select
                  aria-label={t(
                    "ui.admin.users.global_custom_claims.write_permission",
                    "쓰기 권한",
                  )}
                  value={claim.writePermission}
                  name={`global-claim-definition-write-permission-${claim.id}`}
                  className="h-10 rounded-md border border-input bg-background px-3 text-sm"
                  data-testid={`global-claim-definition-write-permission-${claim.key || claim.id}`}
                  onChange={(event) =>
                    updateClaim(claim.id, {
                      writePermission: event.target
                        .value as GlobalCustomClaimPermission,
                    })
                  }
                >
                  {permissions.map((permission) => (
                    <option key={permission} value={permission}>
                      {permissionLabel(permission)}
                    </option>
                  ))}
                </select>
                <Input
                  value={claim.description || ""}
                  name={`global-claim-definition-description-${claim.id}`}
                  placeholder={t(
                    "ui.admin.users.global_custom_claims.description_placeholder",
                    "설명",
                  )}
                  onChange={(event) =>
                    updateClaim(claim.id, { description: event.target.value })
                  }
                />
                <Button
                  type="button"
                  variant="ghost"
                  size="icon"
                  onClick={() => removeClaim(claim.id)}
                >
                  <Trash2 size={16} />
                </Button>
              </div>
            ))
          )}
        </CardContent>
      </Card>
    </div>
  );
}
