import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { Viewer, ViewerPlatform } from "../api/explorer.ts";
import { SiteConfig } from "../api/site.ts";
import { ExpandedIconSettings, FileTypeIconSetting } from "../component/FileManager/Explorer/FileTypeIcon.tsx";
import SessionManager from "../session/index.ts";
import Boolset from "../util/boolset.ts";
import { ExpandedViewerSetting } from "./thunks/viewer.ts";

declare global {
  interface Window {
    subTitle: string;
  }
}

export enum ConfigLoadState {
  NotLoaded,
  CacheHit,
  Loaded,
}

export interface SiteConfigSlice {
  [key: string]: {
    loaded: ConfigLoadState;
    config: SiteConfig;
    typed?: any;
  };
}

const initialState: SiteConfigSlice = {
  login: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
  basic: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
  explorer: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
  emojis: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
  app: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
  thumb: {
    loaded: ConfigLoadState.NotLoaded,
    config: {},
  },
};

export let Viewers: ExpandedViewerSetting = {};
export let ViewersByID: { [key: string]: Viewer } = {};

const preProcessors: {
  [key: string]: (config: SiteConfig) => any;
} = {
  explorer: (config: SiteConfig) => {
    let icons: ExpandedIconSettings = {};
    try {
      const iconSettings = <FileTypeIconSetting[]>JSON.parse(config.icons ?? "[]");
      iconSettings.forEach((item) => {
        item.exts.forEach((ext) => {
          icons[ext] = { ...item, exts: [] };
        });
      });
    } catch (e) {
      console.warn("Failed to parse icons config", e);
    }

    Viewers = {};
    ViewersByID = {};
    const isMobile = window.matchMedia("(max-width: 768px)").matches;
    config.file_viewers?.forEach((group) => {
      group.viewers.forEach((viewer) => {
        if (viewer.disabled) {
          return;
        }

        if (viewer.required_group_permission) {
          const group = SessionManager.currentUserGroup();
          if (!group) {
            return;
          }

          const groupBs = new Boolset(group.permission);
          if (viewer.required_group_permission.some((p) => !groupBs.enabled(p))) {
            return;
          }
        }

        const platform = viewer.platform || ViewerPlatform.all;
        if (platform !== ViewerPlatform.all && platform !== (isMobile ? ViewerPlatform.mobile : ViewerPlatform.pc)) {
          return;
        }

        ViewersByID[viewer.id] = viewer;
        const simplified: Viewer = viewer;
        viewer.exts.forEach((ext) => {
          if (Viewers[ext] === undefined) {
            Viewers[ext] = [];
          }
          Viewers[ext].push(simplified);
        });
      });
    });
    return { icons };
  },
};

const loadSiteConfigCache = (initial: SiteConfigSlice): SiteConfigSlice => {
  Object.entries(initial).forEach(([key, _value]) => {
    const cacheContent = localStorage.getItem(`siteConfigCache_${key}`);
    if (cacheContent == null) {
      return;
    }

    try {
      const configCache = JSON.parse(cacheContent) as SiteConfig;
      initial[key].loaded = ConfigLoadState.CacheHit;
      initial[key].config = configCache;
      if (preProcessors[key]) {
        initial[key].typed = preProcessors[key](configCache);
      }
    } catch (e) {}

    // // 检查是否有path参数
    // const url = new URL(window.location.href);
    // const c = url.searchParams.get("path");
    // rawStore.navigator.path = c === null ? "/" : c;
    // // 初始化用户个性配置
    // rawStore.siteConfig = initUserConfig(rawStore.siteConfig);
  });

  // 更改站点标题
  document.title = initial["basic"].config.title ?? "";

  return initial;
};

export const siteConfigSlice = createSlice({
  name: "siteConfig",
  initialState: loadSiteConfigCache(initialState),
  // The `reducers` field lets us define reducers and generate associated actions
  reducers: {
    applySetting: (
      state,
      action: PayloadAction<{
        section: string;
        config: SiteConfig;
      }>,
    ) => {
      state[action.payload.section].loaded = ConfigLoadState.Loaded;
      state[action.payload.section].config = action.payload.config;
      if (preProcessors[action.payload.section]) {
        state[action.payload.section].typed = preProcessors[action.payload.section](action.payload.config);
      }
    },
  },
  // // The `extraReducers` field lets the slice handle actions defined elsewhere,
  // // including actions generated by createAsyncThunk or in other slices.
  // extraReducers: (builder) => {
  //     builder
  //         .addCase(incrementAsync.pending, (state) => {
  //             state.status = "loading";
  //         })
  //         .addCase(incrementAsync.fulfilled, (state, action) => {
  //             state.status = "idle";
  //             state.value += action.payload;
  //         })
  //         .addCase(incrementAsync.rejected, (state) => {
  //             state.status = "failed";
  //         });
  // },
});

export default siteConfigSlice.reducer;
export const { applySetting } = siteConfigSlice.actions;
