'use client';

import { create } from 'zustand';
import { loadServerData } from '@/lib/server-data';
import type { Member } from '@/lib/members';
import { ensureMemberUsernames } from '@/lib/members';
import { SYSTEM_ADMIN_MEMBER, ensureSystemAdminMember } from '@/lib/member-system';
import { findMemberByUsernameCredentials, resolveAuthUserFromMembers, toAuthUser, type AuthUser } from '@/lib/auth-user';
import { useMemberStore } from './useMemberStore';

interface AuthState {
  user: AuthUser | null;
  isAuthenticated: boolean;
  login: (username: string, password: string, remember: boolean) => Promise<boolean>;
  logout: () => void;
  checkAuth: () => void;
  refreshUser: () => Promise<void>;
}

interface StoredMembersData {
  members: Member[];
}

const SESSION_KEY = 'ftb_auth_session';
const PERSIST_KEY = 'ftb_auth_persist';

const FALLBACK_MEMBERS: Member[] = [SYSTEM_ADMIN_MEMBER];

function writeAuthStorage(user: AuthUser, remember: boolean) {
  sessionStorage.setItem(SESSION_KEY, JSON.stringify(user));
  if (remember) {
    localStorage.setItem(PERSIST_KEY, JSON.stringify(user));
  }
}

function clearAuthStorage() {
  sessionStorage.removeItem(SESSION_KEY);
  localStorage.removeItem(PERSIST_KEY);
}

async function loadMembersForAuth(): Promise<Member[]> {
  try {
    const stored = await loadServerData<StoredMembersData>('members');
    if (stored?.members?.length) {
      const ensured = ensureSystemAdminMember(stored.members);
      return ensureMemberUsernames(ensured.members).members;
    }
  } catch {}

  const inMemoryMembers = useMemberStore.getState().members;
  const members = inMemoryMembers.length > 0 ? ensureSystemAdminMember(inMemoryMembers).members : FALLBACK_MEMBERS;
  return ensureMemberUsernames(members).members;
}

async function refreshStoredAuthUser(user: AuthUser, remember: boolean, set: (state: Partial<AuthState>) => void) {
  try {
    const members = await loadMembersForAuth();
    const next = resolveAuthUserFromMembers(user, members);
    if (!next) {
      clearAuthStorage();
      set({ user: null, isAuthenticated: false });
      return;
    }
    set({ user: next, isAuthenticated: true });
    writeAuthStorage(next, remember);
  } catch {}
}

export const useAuthStore = create<AuthState>((set) => ({
  user: null,
  isAuthenticated: false,

  login: async (username, password, remember) => {
    const members = await loadMembersForAuth();
    const member = findMemberByUsernameCredentials(username, password, members);
    if (!member) return false;

    const user = toAuthUser(member);
    set({ user, isAuthenticated: true });
    writeAuthStorage(user, remember);
    return true;
  },

  logout: () => {
    set({ user: null, isAuthenticated: false });
    clearAuthStorage();
  },

  checkAuth: () => {
    const session = sessionStorage.getItem(SESSION_KEY);
    if (session) {
      const user = JSON.parse(session);
      set({ user, isAuthenticated: true });
      void refreshStoredAuthUser(user, !!localStorage.getItem(PERSIST_KEY), set);
      return;
    }
    const persist = localStorage.getItem(PERSIST_KEY);
    if (persist) {
      const user = JSON.parse(persist);
      set({ user, isAuthenticated: true });
      writeAuthStorage(user, true);
      void refreshStoredAuthUser(user, true, set);
      return;
    }
  },

  refreshUser: async () => {
    const cur = useAuthStore.getState().user;
    if (!cur) return;
    try {
      const memoryMember = useMemberStore.getState().members.find((x) => x.id === cur.id);
      const members = memoryMember ? [memoryMember] : await loadMembersForAuth();
      const member = members.find((x) => x.id === cur.id);
      if (!member) return;

      const next = toAuthUser(member);
      useAuthStore.setState({ user: next });
      writeAuthStorage(next, !!localStorage.getItem(PERSIST_KEY));
    } catch {}
  },
}));
