import { create } from "zustand";

import { setPlayerBearerToken } from "@/lib/lottery-auth";
import {
  clearPersistedPlayerBearerToken,
  persistPlayerBearerToken,
  readPersistedPlayerBearerToken,
} from "@/lib/player-session";
import {
  dispatchPlayerCurrencyChange,
  persistPlayerSelectedCurrency,
  readPersistedPlayerSelectedCurrency,
} from "@/lib/player-currency-preference";
import { pickActivePlayerCurrency } from "@/lib/player-currency-options";
import type { PublicCurrencyRow } from "@/types/api/currency";
import type { PlayerMeData } from "@/types/api/player-me";

export type PlayerEntryPhase = "loading" | "error" | "success";
export type PlayerEntryStepId = "token" | "account" | "hall";
export type PlayerEntryStepStatus = "pending" | "active" | "done";

export type PlayerEntryStep = {
  id: PlayerEntryStepId;
  label: string;
  status: PlayerEntryStepStatus;
};

type PlayerSessionState = {
  bearerToken: string | null;
  profile: PlayerMeData | null;
  currencies: PublicCurrencyRow[];
  /** 玩家在大厅选择的可下注币种（localStorage 持久化） */
  selectedCurrency: string | null;
  phase: PlayerEntryPhase;
  progress: number;
  errorMessage: string | null;
  steps: PlayerEntryStep[];
  setBearerToken: (token: string | null) => void;
  restoreBearerToken: () => string | null;
  clearBearerToken: () => void;
  setProfile: (profile: PlayerMeData | null) => void;
  setCurrencies: (currencies: PublicCurrencyRow[]) => void;
  /** 根据档案与币种目录校准当前选中币种 */
  reconcileSelectedCurrency: () => void;
  setSelectedCurrency: (code: string) => void;
  setPhase: (phase: PlayerEntryPhase) => void;
  setProgress: (progress: number) => void;
  setErrorMessage: (message: string | null) => void;
  updateStep: (id: PlayerEntryStepId, status: PlayerEntryStepStatus) => void;
  resetEntryFlow: () => void;
};

function initialSteps(): PlayerEntryStep[] {
  return [
    { id: "token", label: "校验登录凭证", status: "active" },
    { id: "account", label: "同步玩家账号", status: "pending" },
    { id: "hall", label: "加载彩票大厅", status: "pending" },
  ];
}

function readInitialBearerToken(): string | null {
  if (typeof window === "undefined") {
    return null;
  }
  return readPersistedPlayerBearerToken()?.trim() || null;
}

export const usePlayerSessionStore = create<PlayerSessionState>((set, get) => ({
  bearerToken: readInitialBearerToken(),
  profile: null,
  currencies: [],
  selectedCurrency: null,
  phase: "loading",
  progress: 0,
  errorMessage: null,
  steps: initialSteps(),

  setBearerToken: (token) => {
    const normalized = token?.trim() || null;
    setPlayerBearerToken(normalized);
    if (normalized) {
      persistPlayerBearerToken(normalized);
    } else {
      clearPersistedPlayerBearerToken();
    }
    set({ bearerToken: normalized });
  },

  restoreBearerToken: () => {
    const raw = readPersistedPlayerBearerToken();
    const normalized = raw?.trim() || null;
    if (normalized) {
      setPlayerBearerToken(normalized);
      set({ bearerToken: normalized });
      return normalized;
    }
    setPlayerBearerToken(null);
    set({ bearerToken: null });
    return null;
  },

  clearBearerToken: () => {
    setPlayerBearerToken(null);
    clearPersistedPlayerBearerToken();
    set({ bearerToken: null, profile: null, selectedCurrency: null });
  },

  setProfile: (profile) => {
    set({ profile });
    get().reconcileSelectedCurrency();
  },

  setCurrencies: (currencies) => {
    set({ currencies });
    get().reconcileSelectedCurrency();
  },

  reconcileSelectedCurrency: () => {
    const { profile, currencies } = get();
    const next = pickActivePlayerCurrency(
      profile,
      currencies,
      readPersistedPlayerSelectedCurrency(),
    );
    const prev = get().selectedCurrency;
    if (prev === next) {
      return;
    }
    persistPlayerSelectedCurrency(next);
    set({ selectedCurrency: next });
  },

  setSelectedCurrency: (code) => {
    const normalized = code.trim().toUpperCase();
    const allowed = get().currencies.some(
      (row) => row.is_bettable && row.code === normalized,
    );
    if (!allowed) {
      return;
    }
    persistPlayerSelectedCurrency(normalized);
    set({ selectedCurrency: normalized });
    dispatchPlayerCurrencyChange(normalized);
  },
  setPhase: (phase) => set({ phase }),
  setProgress: (progress) => set({ progress: Math.max(0, Math.min(100, progress)) }),
  setErrorMessage: (errorMessage) => set({ errorMessage }),
  updateStep: (id, status) =>
    set((state) => ({
      steps: state.steps.map((step) =>
        step.id === id ? { ...step, status } : step,
      ),
    })),
  resetEntryFlow: () =>
    set({
      phase: "loading",
      progress: 0,
      errorMessage: null,
      steps: initialSteps(),
    }),
}));
