'use client';
import { create } from 'zustand';
import type { Department, Member, RoleItem, PasswordRule } from '@/lib/members';
import { DEFAULT_PASSWORD_RULE, ensureMemberUsernames, generatePassword, generateUsernameFromName } from '@/lib/members';
import {
  SYSTEM_ADMIN_MEMBER,
  SYSTEM_ADMIN_ROLE_ID,
  canDeleteSystemMember,
  ensureSystemAdminMember,
  sanitizeSystemAdminPatch,
} from '@/lib/member-system';
import { DEFAULT_ROLE_PERMISSIONS, DEFAULT_ROLE_PRESETS } from '@/lib/permissions';
import { mergePresetRolePermissions } from '@/lib/role-permission-migration';
import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data';

const PRESET_DEPARTMENTS: Department[] = [
  { id: 'dept-1', name: '产品部', order: 1, createdAt: '2024-01-01' },
  { id: 'dept-2', name: '技术部', order: 2, createdAt: '2024-01-01' },
  { id: 'dept-2-1', name: '前端组', parentId: 'dept-2', order: 1, createdAt: '2024-01-01' },
  { id: 'dept-2-2', name: '后端组', parentId: 'dept-2', order: 2, createdAt: '2024-01-01' },
  { id: 'dept-2-3', name: '测试组', parentId: 'dept-2', order: 3, createdAt: '2024-01-01' },
  { id: 'dept-3', name: '设计部', order: 3, createdAt: '2024-01-01' },
  { id: 'dept-4', name: '运营部', order: 4, createdAt: '2024-01-01' },
];

const PRESET_ROLES: RoleItem[] = DEFAULT_ROLE_PRESETS;

const MOCK_MEMBERS: Member[] = [
  SYSTEM_ADMIN_MEMBER,
];
let lastMembersFetchAt = 0;

interface MemberState {
  departments: Department[];
  members: Member[];
  roles: RoleItem[];
  passwordRule: PasswordRule;
  loading: boolean;
  loaded: boolean;
  fetchMembers: (options?: { force?: boolean }) => Promise<void>;
  updatePasswordRule: (rule: PasswordRule) => void;
  createDepartment: (data: Omit<Department, 'id' | 'createdAt'>) => void;
  updateDepartment: (id: string, data: Partial<Department>) => void;
  deleteDepartment: (id: string) => void;
  createMember: (data: Omit<Member, 'id' | 'createdAt'>) => void;
  updateMember: (id: string, data: Partial<Member>) => Promise<void>;
  deleteMember: (id: string) => void;
  createRole: (data: Omit<RoleItem, 'id' | 'createdAt'>) => void;
  updateRole: (id: string, data: Partial<RoleItem>) => void;
  deleteRole: (id: string) => void;
}

async function saveStored(state: { departments: Department[]; members: Member[]; roles: RoleItem[]; passwordRule: PasswordRule }) {
  await saveServerData('members', state);
}

async function loadStored(): Promise<{ departments: Department[]; members: Member[]; roles: RoleItem[]; passwordRule: PasswordRule } | null> {
  try {
    return await loadServerData<{ departments: Department[]; members: Member[]; roles: RoleItem[]; passwordRule: PasswordRule }>('members');
  } catch {}
  return null;
}

export const useMemberStore = create<MemberState>((set, get) => ({
  departments: PRESET_DEPARTMENTS,
  members: MOCK_MEMBERS,
  roles: PRESET_ROLES,
  passwordRule: DEFAULT_PASSWORD_RULE,
  loading: false,
  loaded: false,

  fetchMembers: async (options) => {
    if (!options?.force && get().loaded && Date.now() - lastMembersFetchAt < SERVER_DATA_CACHE_MS) return;
    const cached = await loadStored();
    if (!options?.force && get().loaded && Date.now() - lastMembersFetchAt < SERVER_DATA_CACHE_MS) return;
    lastMembersFetchAt = Date.now();
    if (cached) {
      // 迁移：旧 RoleItem 没 permissions 字段，补默认值
      const migratedRoles = cached.roles.map((r) => {
        if (!('permissions' in r) || !Array.isArray((r as any).permissions)) {
          return { ...r, permissions: DEFAULT_ROLE_PERMISSIONS[r.id] ?? [] };
        }
        return r;
      });
      const permissionMerged = mergePresetRolePermissions(migratedRoles);
      const rolesWithNewDefaults = permissionMerged.roles;
      const adminRole = PRESET_ROLES.find((r) => r.id === SYSTEM_ADMIN_ROLE_ID)!;
      const roles = rolesWithNewDefaults.some((r) => r.id === SYSTEM_ADMIN_ROLE_ID)
        ? rolesWithNewDefaults.map((r) => r.id === SYSTEM_ADMIN_ROLE_ID ? { ...adminRole, ...r, isSystem: true, permissions: DEFAULT_ROLE_PERMISSIONS[SYSTEM_ADMIN_ROLE_ID] } : r)
        : [adminRole, ...rolesWithNewDefaults];
      const rolesChanged =
        permissionMerged.changed ||
        roles.length !== rolesWithNewDefaults.length ||
        roles.some((role, index) => JSON.stringify(role) !== JSON.stringify(rolesWithNewDefaults[index]));
      const ensured = ensureSystemAdminMember(cached.members);
      const usernameEnsured = ensureMemberUsernames(ensured.members);
      const next = {
        departments: cached.departments,
        members: usernameEnsured.members,
        roles,
        passwordRule: cached.passwordRule || DEFAULT_PASSWORD_RULE,
      };
      set({ ...next, loaded: true });
      if (ensured.changed || usernameEnsured.changed || rolesChanged) void saveStored(next).catch(() => {});
    } else {
      set({ loaded: true });
    }
  },

  updatePasswordRule: (rule) => {
    set({ passwordRule: rule });
    void saveStored({ departments: get().departments, members: get().members, roles: get().roles, passwordRule: rule }).catch(() => {});
  },

  createDepartment: (data) => {
    const dept: Department = { ...data, id: `dept-${Date.now()}`, createdAt: new Date().toISOString().slice(0, 10) };
    const departments = [...get().departments, dept];
    set({ departments });
    void saveStored({ departments, members: get().members, roles: get().roles, passwordRule: get().passwordRule }).catch(() => {});
  },
  updateDepartment: (id, data) => {
    const departments = get().departments.map((d) => d.id === id ? { ...d, ...data } : d);
    set({ departments });
    void saveStored({ departments, members: get().members, roles: get().roles, passwordRule: get().passwordRule }).catch(() => {});
  },
  deleteDepartment: (id) => {
    const departments = get().departments.filter((d) => d.id !== id && d.parentId !== id);
    set({ departments });
    void saveStored({ departments, members: get().members, roles: get().roles, passwordRule: get().passwordRule }).catch(() => {});
  },

  createMember: (data) => {
    const member: Member = {
      ...data,
      username: data.username || generateUsernameFromName(data.name, get().members.map((m) => m.username ?? '')),
      phone: data.phone ?? '',
      id: `m-${Date.now()}`,
      createdAt: new Date().toISOString().slice(0, 10),
    };
    const members = [...get().members, member];
    set({ members });
    void saveStored({ departments: get().departments, members, roles: get().roles, passwordRule: get().passwordRule }).catch(() => {});
  },
  updateMember: async (id, data) => {
    const previousMembers = get().members;
    const safeData = sanitizeSystemAdminPatch(id, data);
    const updatedMembers = get().members.map((m) => m.id === id ? { ...m, ...safeData } : m);
    const ensured = ensureSystemAdminMember(updatedMembers);
    set({ members: ensured.members });
    try {
      await saveStored({ departments: get().departments, members: ensured.members, roles: get().roles, passwordRule: get().passwordRule });
    } catch (error) {
      set({ members: previousMembers });
      throw error;
    }
  },
  deleteMember: (id) => {
    if (!canDeleteSystemMember(id)) return;
    const members = get().members.filter((m) => m.id !== id);
    set({ members });
    void saveStored({ departments: get().departments, members, roles: get().roles, passwordRule: get().passwordRule }).catch(() => {});
  },

  createRole: (data) => {
    const role: RoleItem = {
      ...data,
      id: `role-${Date.now()}`,
      createdAt: new Date().toISOString().slice(0, 10),
      permissions: data.permissions ?? [],
    };
    const roles = [...get().roles, role];
    set({ roles });
    void saveStored({ departments: get().departments, members: get().members, roles, passwordRule: get().passwordRule }).catch(() => {});
  },
  updateRole: (id, data) => {
    const roles = get().roles.map((r) => {
      if (r.id !== id) return r;
      // 超管不允许改 permissions（防误操作锁死系统）
      if (r.id === 'role-admin' && data.permissions) {
        const { permissions, ...rest } = data;
        return { ...r, ...rest };
      }
      return { ...r, ...data };
    });
    set({ roles });
    void saveStored({ departments: get().departments, members: get().members, roles, passwordRule: get().passwordRule }).catch(() => {});
  },
  deleteRole: (id) => {
    if (id === SYSTEM_ADMIN_ROLE_ID) return;
    const roles = get().roles.filter((r) => r.id !== id);
    set({ roles });
    void saveStored({ departments: get().departments, members: get().members, roles, passwordRule: get().passwordRule }).catch(() => {});
  },
}));
