"use client";

import {
  Refine,
  type AccessControlProvider,
  type AuthProvider,
} from "@refinedev/core";
import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
import { RefineSnackbarProvider } from "@refinedev/mui";
import { SessionProvider, signIn, signOut, useSession } from "next-auth/react";
import { usePathname } from "next/navigation";
import React, { useEffect } from "react";

import routerProvider from "@refinedev/nextjs-router";

import { ColorModeContextProvider } from "@contexts/color-mode";
import { dataProvider } from "@providers/data-provider";
import { ProjectProvider } from "@/contexts/ProjectContext";
import { RoutePermissionGuard } from "@/components/auth/RoutePermissionGuard";
import { useAuthStore } from "@/store/authStore";
import { useAccessStore } from "@/store/accessStore";
import { useProjectStore } from "@/store/projectStore";
import { apiFetch } from "@/lib/apiFetch";
import { permissionCodes, resourcePermissions } from "@/lib/permissions";
import { config } from "@config/config";
import { useAppNotificationProvider } from "@/providers/notification-provider/useAppNotificationProvider";

import { LiaNetworkWiredSolid } from "react-icons/lia";
import { TbActivity, TbDatabaseEdit, TbLocationPin } from "react-icons/tb";
import { LuReplace } from "react-icons/lu";
import { AiOutlineSecurityScan } from "react-icons/ai";
import { MdCleaningServices, MdOutlineWaterDrop } from "react-icons/md";
import {
  FactCheck as FactCheckIcon,
  ManageAccounts as ManageAccountsIcon,
  MyLocation as MyLocationIcon,
  Search as SearchIcon,
} from "@mui/icons-material";

type RefineContextProps = {
  defaultMode?: string;
};

export const RefineContext = (
  props: React.PropsWithChildren<RefineContextProps>,
) => (
  <SessionProvider>
    <App {...props} />
  </SessionProvider>
);

type AppProps = {
  defaultMode?: string;
};

const App = (props: React.PropsWithChildren<AppProps>) => {
  const { data, status } = useSession();
  const to = usePathname();
  const setAccessToken = useAuthStore((state) => state.setAccessToken);
  const currentProjectId = useProjectStore((state) => state.currentProjectId);
  const permissions = useAccessStore((state) => state.permissions);
  const setAccessContext = useAccessStore((state) => state.setContext);
  const setAccessLoading = useAccessStore((state) => state.setLoading);
  const resetAccess = useAccessStore((state) => state.reset);
  const can = (permission: string) => permissions.includes(permission);

  useEffect(() => {
    setAccessToken(
      typeof data?.accessToken === "string" ? data.accessToken : null,
    );
  }, [data?.accessToken, setAccessToken]);

  useEffect(() => {
    if (status !== "authenticated") {
      resetAccess();
      return;
    }

    let cancelled = false;
    setAccessLoading(true);
    apiFetch(`${config.BACKEND_URL}/api/v1/access-context`, {
      projectHeaderMode: currentProjectId ? "include" : "omit",
      skipAuthRedirect: true,
    })
      .then(async (response) => {
        if (cancelled) return;
        if (!response.ok) {
          resetAccess();
          return;
        }
        setAccessContext(await response.json());
      })
      .catch(() => {
        if (!cancelled) resetAccess();
      });

    return () => {
      cancelled = true;
    };
  }, [
    currentProjectId,
    resetAccess,
    setAccessContext,
    setAccessLoading,
    status,
  ]);

  useEffect(() => {
    if (status !== "authenticated" || !data?.user?.id) return;
    const auditKey = `tjwater-login-audit:${data.user.id}`;
    if (sessionStorage.getItem(auditKey)) return;

    apiFetch(`${config.BACKEND_URL}/api/v1/audit-events`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ event: "login" }),
      projectHeaderMode: "omit",
      skipAuthRedirect: true,
    })
      .then((response) => {
        if (response.ok) sessionStorage.setItem(auditKey, "1");
      })
      .catch(() => undefined);
  }, [data?.user?.id, status]);

  if (status === "loading") {
    return <span>loading...</span>;
  }

  const authProvider: AuthProvider = {
    login: async () => {
      signIn("keycloak", {
        callbackUrl: to ? to.toString() : "/",
        redirect: true,
      });
      return { success: true };
    },
    logout: async () => {
      try {
        await apiFetch(`${config.BACKEND_URL}/api/v1/audit-events`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ event: "logout" }),
          projectHeaderMode: "omit",
          skipAuthRedirect: true,
        });
      } catch {
        // Logout must still complete when audit storage is unavailable.
      }
      if (data?.user?.id) {
        sessionStorage.removeItem(`tjwater-login-audit:${data.user.id}`);
      }
      signOut({ redirect: true, callbackUrl: "/login" });
      return { success: true };
    },
    onError: async (error) => {
      if (error.response?.status === 401) {
        return { logout: true };
      }
      return { error };
    },
    check: async () =>
      status === "unauthenticated"
        ? { authenticated: false, redirectTo: "/login" }
        : { authenticated: true },
    getPermissions: async () => permissions,
    getIdentity: async () => {
      if (!data?.user) return null;
      return {
        id: data.user.id,
        username: data.user.username,
        name: data.user.name,
        avatar: data.user.image,
      };
    },
  };

  const accessControlProvider: AccessControlProvider = {
    can: async ({ resource }) => {
      const requiredPermission = resource
        ? resourcePermissions[resource]
        : undefined;
      return {
        can: !requiredPermission || permissions.includes(requiredPermission),
        reason: requiredPermission
          ? `需要权限：${requiredPermission}`
          : undefined,
      };
    },
  };

  const resources = [
    ...(can(permissionCodes.simulationView)
      ? [
          {
            name: "管网在线模拟",
            list: "/network-simulation",
            meta: {
              icon: <LiaNetworkWiredSolid className="w-6 h-6" />,
              label: "管网在线模拟",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.scadaClean)
      ? [
          {
            name: "SCADA 数据清洗",
            list: "/scada-data-cleaning",
            meta: {
              icon: <TbDatabaseEdit className="w-6 h-6" />,
              label: "SCADA 数据清洗",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.optimizationRun)
      ? [
          {
            name: "监测点优化布置",
            list: "/monitoring-place-optimization",
            meta: {
              icon: <LuReplace className="w-6 h-6" />,
              label: "监测点优化布置",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.riskRun)
      ? [
          {
            name: "健康风险分析",
            list: "/health-risk-analysis",
            meta: {
              icon: <AiOutlineSecurityScan className="w-6 h-6" />,
              label: "健康风险分析",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.simulationRun) || can(permissionCodes.burstRun)
      ? [
          {
            name: "Hydraulic Simulation",
            meta: { label: "事件模拟" },
          },
        ]
      : []),
    ...(can(permissionCodes.burstRun)
      ? [
          {
            name: "爆管模拟",
            list: "/hydraulic-simulation/burst-simulation",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <TbLocationPin className="w-6 h-6" />,
              label: "爆管模拟",
            },
          },
          {
            name: "爆管侦测",
            list: "/hydraulic-simulation/burst-detection",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <TbActivity className="w-6 h-6" />,
              label: "爆管侦测",
            },
          },
          {
            name: "爆管定位",
            list: "/hydraulic-simulation/burst-location",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <MyLocationIcon className="w-6 h-6" />,
              label: "爆管定位",
            },
          },
          {
            name: "DMA 漏损识别",
            list: "/hydraulic-simulation/dma-leak-detection",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <SearchIcon className="w-6 h-6" />,
              label: "DMA 漏损识别",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.simulationRun)
      ? [
          {
            name: "水质模拟",
            list: "/hydraulic-simulation/contaminant-simulation",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <MdOutlineWaterDrop className="w-6 h-6" />,
              label: "水质模拟",
            },
          },
          {
            name: "管道冲洗",
            list: "/hydraulic-simulation/flushing-analysis",
            meta: {
              parent: "Hydraulic Simulation",
              icon: <MdCleaningServices className="w-6 h-6" />,
              label: "管道冲洗",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.environmentManage)
      ? [
          {
            name: "系统管理",
            list: "/system-admin",
            meta: {
              icon: <ManageAccountsIcon className="w-6 h-6" />,
              label: "系统管理",
            },
          },
        ]
      : []),
    ...(can(permissionCodes.auditView)
      ? [
          {
            name: "审计日志",
            list: "/audit-logs",
            meta: {
              icon: <FactCheckIcon className="w-6 h-6" />,
              label: "审计日志",
            },
          },
        ]
      : []),
  ];

  return (
    <ProjectProvider>
      <RefineKbarProvider>
        <ColorModeContextProvider defaultMode={props.defaultMode}>
          <RefineSnackbarProvider>
            <Refine
              routerProvider={routerProvider}
              dataProvider={dataProvider}
              notificationProvider={useAppNotificationProvider}
              authProvider={authProvider}
              accessControlProvider={accessControlProvider}
              resources={resources}
              options={{
                syncWithLocation: true,
                warnWhenUnsavedChanges: true,
              }}
            >
              <RoutePermissionGuard>{props.children}</RoutePermissionGuard>
              <RefineKbar />
            </Refine>
          </RefineSnackbarProvider>
        </ColorModeContextProvider>
      </RefineKbarProvider>
    </ProjectProvider>
  );
};
