/**
 * 持久化中间件基础设施。
 *
 * 为了平滑迁移，这里把旧实现直接读写 localStorage 的 key
 * （token / user / permissions / gongxue-route-dock）包装成 zustand
 * persist 的 StateStorage，保证迁移前后数据格式兼容。
 */
import { createJSONStorage, type StateStorage } from 'zustand/middleware';
import type { AppPersistedState, DockTab } from '../app/appTypes';
import type { PermissionPersistedState } from '../permission/permissionTypes';
import type { UserInfo, UserPersistedState } from '../user/userTypes';

export const AUTH_STORAGE_NAME = 'gongxue-auth';
export const LEGACY_TOKEN_KEY = 'token';
export const LEGACY_USER_KEY = 'user';

export const PERMISSION_STORAGE_NAME = 'permissions';

export const APP_UI_STORAGE_NAME = 'gongxue-app-ui';
export const LEGACY_DOCK_STORAGE_KEY = 'gongxue-route-dock';

export const SETTINGS_STORAGE_NAME = 'gongxue-settings';

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null;
}

function isDockTab(value: unknown): value is DockTab {
  return (
    isRecord(value) &&
    typeof value.key === 'string' &&
    value.key.startsWith('/') &&
    typeof value.label === 'string'
  );
}

/**
 * 用户会话持久化：继续使用旧的 `token` / `user` 两个 key，
 * 保持与后端、既有代码及浏览器缓存格式一致。
 */
const legacyAuthStorage: StateStorage = {
  getItem: () => {
    const token = localStorage.getItem(LEGACY_TOKEN_KEY);
    const rawUser = localStorage.getItem(LEGACY_USER_KEY);
    if (token === null && rawUser === null) return null;
    let user: UserInfo | null = null;
    if (rawUser !== null) {
      try {
        const parsed: unknown = JSON.parse(rawUser);
        user = isRecord(parsed) ? (parsed as UserInfo) : null;
      } catch {
        user = null;
      }
    }
    return JSON.stringify({ state: { token, user }, version: 1 });
  },
  setItem: (_name, value) => {
    try {
      const persisted = JSON.parse(value) as { state?: UserPersistedState };
      const { token, user } = persisted.state ?? {};
      if (token) {
        localStorage.setItem(LEGACY_TOKEN_KEY, token);
      } else {
        localStorage.removeItem(LEGACY_TOKEN_KEY);
      }
      if (user) {
        localStorage.setItem(LEGACY_USER_KEY, JSON.stringify(user));
      } else {
        localStorage.removeItem(LEGACY_USER_KEY);
      }
    } catch {
      // 持久化写入失败不应影响应用运行
    }
  },
  removeItem: () => {
    localStorage.removeItem(LEGACY_TOKEN_KEY);
    localStorage.removeItem(LEGACY_USER_KEY);
  },
};

/**
 * 权限持久化：兼容旧格式（原始 JSON 数组）与 zustand persist 格式。
 * 无论磁盘上是什么状态，恢复后一律为 `unknown`，保持 fail-closed，
 * 直到 `/auth/profile` 校验成功。
 */
const legacyPermissionStorage: StateStorage = {
  getItem: () => {
    const raw = localStorage.getItem(PERMISSION_STORAGE_NAME);
    if (!raw) return null;
    try {
      const parsed: unknown = JSON.parse(raw);
      if (Array.isArray(parsed)) {
        return JSON.stringify({
          state: { permissions: parsed.filter(isString), status: 'unknown' },
          version: 1,
        });
      }
      if (isRecord(parsed) && isRecord(parsed.state)) {
        const permissions = Array.isArray(parsed.state.permissions)
          ? parsed.state.permissions.filter(isString)
          : [];
        return JSON.stringify({
          state: { permissions, status: 'unknown' },
          version: 1,
        });
      }
    } catch {
      // 损坏的缓存按无权限处理
    }
    return null;
  },
  setItem: (_name, value) => {
    try {
      const persisted = JSON.parse(value) as { state?: PermissionPersistedState };
      const permissions = Array.isArray(persisted.state?.permissions)
        ? persisted.state.permissions.filter(isString)
        : [];
      localStorage.setItem(PERMISSION_STORAGE_NAME, JSON.stringify(permissions));
    } catch {
      // 忽略损坏数据
    }
  },
  removeItem: () => {
    localStorage.removeItem(PERMISSION_STORAGE_NAME);
  },
};

/**
 * 应用 UI 状态持久化：新 key `gongxue-app-ui`，
 * 首次读取时自动迁移旧 key `gongxue-route-dock` 中已打开的页签。
 */
const appUiStorage: StateStorage = {
  getItem: (name) => {
    const current = localStorage.getItem(name);
    if (current) return current;
    const legacy = localStorage.getItem(LEGACY_DOCK_STORAGE_KEY);
    if (!legacy) return null;
    try {
      const parsed: unknown = JSON.parse(legacy);
      const routeDockTabs = Array.isArray(parsed) ? parsed.filter(isDockTab) : [];
      return JSON.stringify({ state: { routeDockTabs, sidebarCollapsed: false }, version: 1 });
    } catch {
      return null;
    }
  },
  setItem: (name, value) => {
    try {
      localStorage.setItem(name, value);
    } catch {
      // 持久化失败不应影响应用运行
    }
  },
  removeItem: (name) => {
    try {
      localStorage.removeItem(name);
    } catch {
      // 持久化失败不应影响应用运行
    }
  },
};

/** 会话 Store 使用的 persist storage（兼容旧 token/user key） */
export const authPersistStorage = createJSONStorage(() => legacyAuthStorage);

/** 权限 Store 使用的 persist storage（兼容旧 permissions key） */
export const permissionPersistStorage = createJSONStorage(() => legacyPermissionStorage);

/** 应用 UI Store 使用的 persist storage（含旧 RouteDock key 迁移） */
export const appUiPersistStorage = createJSONStorage(() => appUiStorage);

export type { AppPersistedState, PermissionPersistedState, UserPersistedState };
