import React from "react";
import { useSidebar } from "@/components/sidebar.tsx";
import { Separator } from "@/components/separator.tsx";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@/components/tabs.tsx";
import { Shield, Users, Database, Clock, Key } from "lucide-react";
import { toast } from "sonner";
import { useTranslation } from "react-i18next";
import { useConfirmation } from "@/hooks/use-confirmation.ts";
import {
  getAdminOIDCConfig,
  getRegistrationAllowed,
  getPasswordLoginAllowed,
  getPasswordResetAllowed,
  getUserList,
  getUserInfo,
  isElectron,
  getSessions,
  unlinkOIDCFromPasswordAccount,
} from "@/main-axios.ts";
import { SimpleLoader } from "@/lib/SimpleLoader.tsx";
import { RolesTab } from "@/admin/tabs/RolesTab.tsx";
import { GeneralSettingsTab } from "@/admin/tabs/GeneralSettingsTab.tsx";
import { OIDCSettingsTab } from "@/admin/tabs/OIDCSettingsTab.tsx";
import { UserManagementTab } from "@/admin/tabs/UserManagementTab.tsx";
import { SessionManagementTab } from "@/admin/tabs/SessionManagementTab.tsx";
import { DatabaseSecurityTab } from "@/admin/tabs/DatabaseSecurityTab.tsx";
import { ApiKeysTab } from "@/admin/tabs/ApiKeysTab.tsx";
import { CreateUserDialog } from "./dialogs/CreateUserDialog.tsx";
import { UserEditDialog } from "./dialogs/UserEditDialog.tsx";
import { LinkAccountDialog } from "./dialogs/LinkAccountDialog.tsx";

interface AdminSettingsProps {
  isTopbarOpen?: boolean;
  rightSidebarOpen?: boolean;
  rightSidebarWidth?: number;
}

export function AdminSettings({
  isTopbarOpen = true,
  rightSidebarOpen = false,
  rightSidebarWidth = 400,
}: AdminSettingsProps): React.ReactElement {
  const { t } = useTranslation();
  const { confirmWithToast } = useConfirmation();
  const { state: sidebarState } = useSidebar();

  const [loading, setLoading] = React.useState(true);
  const [allowRegistration, setAllowRegistration] = React.useState(true);
  const [allowPasswordLogin, setAllowPasswordLogin] = React.useState(true);
  const [allowPasswordReset, setAllowPasswordReset] = React.useState(true);

  const [oidcConfig, setOidcConfig] = React.useState({
    client_id: "",
    client_secret: "",
    issuer_url: "",
    authorization_url: "",
    token_url: "",
    identifier_path: "sub",
    name_path: "name",
    scopes: "openid email profile",
    userinfo_url: "",
    allowed_users: "",
  });

  const [users, setUsers] = React.useState<
    Array<{
      id: string;
      username: string;
      isAdmin: boolean;
      isOidc: boolean;
      passwordHash?: string;
    }>
  >([]);
  const [usersLoading, setUsersLoading] = React.useState(false);

  const [createUserDialogOpen, setCreateUserDialogOpen] = React.useState(false);
  const [userEditDialogOpen, setUserEditDialogOpen] = React.useState(false);
  const [selectedUserForEdit, setSelectedUserForEdit] = React.useState<{
    id: string;
    username: string;
    isAdmin: boolean;
    isOidc: boolean;
    passwordHash?: string;
  } | null>(null);

  const [currentUser, setCurrentUser] = React.useState<{
    id: string;
    username: string;
    is_admin: boolean;
    is_oidc: boolean;
  } | null>(null);

  const [sessions, setSessions] = React.useState<
    Array<{
      id: string;
      userId: string;
      username?: string;
      deviceType: string;
      deviceInfo: string;
      createdAt: string;
      expiresAt: string;
      lastActiveAt: string;
      isRevoked?: boolean;
      isCurrentSession?: boolean;
    }>
  >([]);
  const [sessionsLoading, setSessionsLoading] = React.useState(false);

  const [linkAccountAlertOpen, setLinkAccountAlertOpen] = React.useState(false);
  const [linkOidcUser, setLinkOidcUser] = React.useState<{
    id: string;
    username: string;
  } | null>(null);

  React.useEffect(() => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        setLoading(false);
        return;
      }
    }

    Promise.allSettled([
      getAdminOIDCConfig()
        .then((res) => {
          if (res)
            setOidcConfig((prev) => ({
              ...prev,
              ...res,
              identifier_path: (res.identifier_path as string) || "sub",
              name_path: (res.name_path as string) || "name",
              scopes: (res.scopes as string) || "openid email profile",
            }));
        })
        .catch((err) => {
          if (!err.message?.includes("No server configured")) {
            toast.error(t("admin.failedToFetchOidcConfig"));
          }
        }),
      getUserInfo()
        .then((info) => {
          if (info) {
            setCurrentUser({
              id: info.userId,
              username: info.username,
              is_admin: info.is_admin,
              is_oidc: info.is_oidc,
            });
          }
        })
        .catch((err) => {
          if (!err?.message?.includes("No server configured")) {
            console.warn("Failed to fetch current user info", err);
          }
        }),
      getSessions()
        .then((data) => setSessions(data.sessions || []))
        .catch((err) => {
          if (!err?.message?.includes("No server configured")) {
            toast.error(t("admin.failedToFetchSessions"));
          }
        }),
    ]).finally(() => setLoading(false));
  }, []);

  React.useEffect(() => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        return;
      }
    }

    getRegistrationAllowed()
      .then((res) => {
        if (typeof res?.allowed === "boolean") {
          setAllowRegistration(res.allowed);
        }
      })
      .catch((err) => {
        if (!err.message?.includes("No server configured")) {
          toast.error(t("admin.failedToFetchRegistrationStatus"));
        }
      });
  }, []);

  React.useEffect(() => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        return;
      }
    }

    getPasswordLoginAllowed()
      .then((res) => {
        if (typeof res?.allowed === "boolean") {
          setAllowPasswordLogin(res.allowed);
        }
      })
      .catch((err) => {
        if (err.code !== "NO_SERVER_CONFIGURED") {
          toast.error(t("admin.failedToFetchPasswordLoginStatus"));
        }
      });
  }, []);

  React.useEffect(() => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        return;
      }
    }

    getPasswordResetAllowed()
      .then((res) => {
        if (typeof res === "boolean") {
          setAllowPasswordReset(res);
        }
      })
      .catch((err) => {
        if (err.code !== "NO_SERVER_CONFIGURED") {
          console.warn("Failed to fetch password reset status", err);
        }
      });
  }, []);

  const fetchUsers = async () => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        return;
      }
    }

    setUsersLoading(true);
    try {
      const response = await getUserList();
      setUsers(response.users);
    } catch (err) {
      if (!err.message?.includes("No server configured")) {
        toast.error(t("admin.failedToFetchUsers"));
      }
    } finally {
      setUsersLoading(false);
    }
  };

  const handleEditUser = (user: (typeof users)[0]) => {
    setSelectedUserForEdit(user);
    setUserEditDialogOpen(true);
  };

  const handleCreateUserSuccess = () => {
    fetchUsers();
    setCreateUserDialogOpen(false);
  };

  const handleEditUserSuccess = () => {
    fetchUsers();
    setUserEditDialogOpen(false);
    setSelectedUserForEdit(null);
  };

  const fetchSessions = async () => {
    if (isElectron()) {
      const serverUrl = (window as { configuredServerUrl?: string })
        .configuredServerUrl;
      if (!serverUrl) {
        return;
      }
    }

    setSessionsLoading(true);
    try {
      const data = await getSessions();
      setSessions(data.sessions || []);
    } catch (err) {
      if (!err?.message?.includes("No server configured")) {
        toast.error(t("admin.failedToFetchSessions"));
      }
    } finally {
      setSessionsLoading(false);
    }
  };

  const handleLinkOIDCUser = (user: { id: string; username: string }) => {
    setLinkOidcUser(user);
    setLinkAccountAlertOpen(true);
  };

  const handleLinkSuccess = () => {
    fetchUsers();
    fetchSessions();
  };

  const handleUnlinkOIDC = async (userId: string, username: string) => {
    confirmWithToast(
      t("admin.unlinkOIDCDescription", { username }),
      async () => {
        try {
          const result = await unlinkOIDCFromPasswordAccount(userId);

          toast.success(
            result.message || t("admin.unlinkOIDCSuccess", { username }),
          );
          fetchUsers();
          fetchSessions();
        } catch (error: unknown) {
          const err = error as {
            response?: { data?: { error?: string; code?: string } };
          };
          toast.error(
            err.response?.data?.error || t("admin.failedToUnlinkOIDC"),
          );
        }
      },
      "destructive",
    );
  };

  const topMarginPx = isTopbarOpen ? 74 : 26;
  const leftMarginPx = sidebarState === "collapsed" ? 26 : 8;
  const bottomMarginPx = 8;
  const wrapperStyle: React.CSSProperties = {
    marginLeft: leftMarginPx,
    marginRight: rightSidebarOpen
      ? `calc(var(--right-sidebar-width, ${rightSidebarWidth}px) + 8px)`
      : 17,
    marginTop: topMarginPx,
    marginBottom: bottomMarginPx,
    height: `calc(100vh - ${topMarginPx + bottomMarginPx}px)`,
    transition:
      "margin-left 200ms linear, margin-right 200ms linear, margin-top 200ms linear",
  };

  return (
    <div
      style={wrapperStyle}
      className="bg-canvas text-foreground rounded-lg border-2 border-edge overflow-hidden"
    >
      <SimpleLoader visible={loading} message={t("common.loading")} />
      <div className="h-full w-full flex flex-col">
        <div className="flex items-center justify-between px-3 pt-2 pb-2">
          <h1 className="font-bold text-lg">{t("admin.title")}</h1>
        </div>
        <Separator className="p-0.25 w-full" />

        <div className="px-6 py-4 overflow-auto thin-scrollbar">
          <Tabs
            defaultValue="registration"
            onValueChange={(value) => {
              if (value === "users") {
                fetchUsers();
              }
            }}
            className="w-full"
          >
            <TabsList className="mb-4 bg-elevated border-2 border-edge">
              <TabsTrigger
                value="registration"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Users className="h-4 w-4" />
                {t("admin.general")}
              </TabsTrigger>
              <TabsTrigger
                value="oidc"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Shield className="h-4 w-4" />
                OIDC
              </TabsTrigger>
              <TabsTrigger
                value="users"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Users className="h-4 w-4" />
                {t("admin.users")}
              </TabsTrigger>
              <TabsTrigger
                value="sessions"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Clock className="h-4 w-4" />
                Sessions
              </TabsTrigger>
              <TabsTrigger
                value="roles"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Shield className="h-4 w-4" />
                {t("rbac.roles.label")}
              </TabsTrigger>
              <TabsTrigger
                value="security"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Database className="h-4 w-4" />
                {t("admin.databaseSecurity")}
              </TabsTrigger>
              <TabsTrigger
                value="api-keys"
                className="flex items-center gap-2 bg-elevated data-[state=active]:bg-button data-[state=active]:border data-[state=active]:border-edge"
              >
                <Key className="h-4 w-4" />
                {t("admin.apiKeys.tabLabel")}
              </TabsTrigger>
            </TabsList>

            <TabsContent value="registration" className="space-y-6">
              <GeneralSettingsTab
                allowRegistration={allowRegistration}
                setAllowRegistration={setAllowRegistration}
                allowPasswordLogin={allowPasswordLogin}
                setAllowPasswordLogin={setAllowPasswordLogin}
                allowPasswordReset={allowPasswordReset}
                setAllowPasswordReset={setAllowPasswordReset}
                oidcConfig={oidcConfig}
              />
            </TabsContent>

            <TabsContent value="oidc" className="space-y-6">
              <OIDCSettingsTab
                allowPasswordLogin={allowPasswordLogin}
                oidcConfig={oidcConfig}
                setOidcConfig={setOidcConfig}
              />
            </TabsContent>

            <TabsContent value="users" className="space-y-6">
              <UserManagementTab
                users={users}
                usersLoading={usersLoading}
                allowPasswordLogin={allowPasswordLogin}
                fetchUsers={fetchUsers}
                onCreateUser={() => setCreateUserDialogOpen(true)}
                onEditUser={handleEditUser}
                onLinkOIDCUser={handleLinkOIDCUser}
                onUnlinkOIDC={handleUnlinkOIDC}
              />
            </TabsContent>

            <TabsContent value="sessions" className="space-y-6">
              <SessionManagementTab
                sessions={sessions}
                sessionsLoading={sessionsLoading}
                fetchSessions={fetchSessions}
              />
            </TabsContent>

            <TabsContent value="roles" className="space-y-6">
              <div className="rounded-lg border-2 border-border bg-card p-4 space-y-4">
                <RolesTab />
              </div>
            </TabsContent>

            <TabsContent value="security" className="space-y-6">
              <DatabaseSecurityTab />
            </TabsContent>

            <TabsContent value="api-keys" className="space-y-6">
              <ApiKeysTab />
            </TabsContent>
          </Tabs>
        </div>
      </div>

      <CreateUserDialog
        open={createUserDialogOpen}
        onOpenChange={setCreateUserDialogOpen}
        onSuccess={handleCreateUserSuccess}
      />

      <UserEditDialog
        open={userEditDialogOpen}
        onOpenChange={setUserEditDialogOpen}
        user={selectedUserForEdit}
        currentUser={currentUser}
        onSuccess={handleEditUserSuccess}
      />

      <LinkAccountDialog
        open={linkAccountAlertOpen}
        onOpenChange={setLinkAccountAlertOpen}
        oidcUser={linkOidcUser}
        onSuccess={handleLinkSuccess}
      />
    </div>
  );
}

export default AdminSettings;
