import { create } from "zustand";
import { persist } from "zustand/middleware";
import { ARTISTS } from "./mock-data";
import type { Artist } from "@/types/artist";

/**
 * 每用户终身投票总额度 —— 一人 12 票,每位艺人最多 1 票,
 * 投完即结束,不限时,不可撤销。
 */
export const TOTAL_VOTE_QUOTA = 12;

/** 派生类型:我应援的艺人(新规则下每位仅 1 票,不再带 votedCount) */
export interface MySupport {
  artist: Artist;
}

interface VoteStore {
  /** 当前所有艺人(含动态票数 / 实时排名) */
  artists: Artist[];
  /**
   * 我已投票的艺人 ID 列表(顺序 = 投票顺序)。
   * 用数组而不是 Set:zustand persist 默认 storage 是 JSON,Set 无法直接序列化。
   * 数组按投票顺序保留,既能 .includes() 判重,也能在 /me 页面显示"我的投票"时按时间排序。
   */
  votedArtists: string[];
  /**
   * 给艺人投票。
   * - 已投过该艺人 → 返回 { ok: false, reason: "already" }
   * - 已用满 12 票 → 返回 { ok: false, reason: "exhausted" }
   * - 成功 → 返回 { ok: true }
   */
  vote: (artistId: string) => { ok: boolean; reason?: "already" | "exhausted" };
  /** 重置(开发时用 / 测试用) */
  reset: () => void;
}

/** 票数倒序 + 编号升序兜底,确保 0 票时也有稳定排名 */
function rank(list: Artist[]): Artist[] {
  return [...list]
    .sort((a, b) => b.votes - a.votes || a.no.localeCompare(b.no))
    .map((a, i) => ({ ...a, rank: i + 1 }));
}

const INITIAL_ARTISTS = rank(ARTISTS);

export const useVoteStore = create<VoteStore>()(
  persist(
    (set, get) => ({
      artists: INITIAL_ARTISTS,
      votedArtists: [],
      vote: (artistId) => {
        const state = get();
        if (state.votedArtists.includes(artistId)) {
          return { ok: false, reason: "already" };
        }
        if (state.votedArtists.length >= TOTAL_VOTE_QUOTA) {
          return { ok: false, reason: "exhausted" };
        }
        const updated = state.artists.map((a) =>
          a.id === artistId ? { ...a, votes: a.votes + 1 } : a,
        );
        set({
          artists: rank(updated),
          votedArtists: [...state.votedArtists, artistId],
        });
        return { ok: true };
      },
      reset: () =>
        set({
          artists: INITIAL_ARTISTS,
          votedArtists: [],
        }),
    }),
    {
      name: "cyber-star-vote",
      // 仅持久化 votedArtists —— artists 票数/排名是派生数据,
      // 刷新后重新从初始数据 + votedArtists 重建。
      // 注意:当前 mock 阶段 artists 只反映本地投票,不同步服务端 —— 等后端接入再调整。
      partialize: (state) => ({ votedArtists: state.votedArtists }),
      // rehydrate 时把 votedArtists 数据"回放"到 artists 票数上,保持视图一致
      onRehydrateStorage: () => (state) => {
        if (!state) return;
        const counts = new Map<string, number>();
        for (const id of state.votedArtists) {
          counts.set(id, (counts.get(id) ?? 0) + 1);
        }
        const rebuilt = INITIAL_ARTISTS.map((a) => ({
          ...a,
          votes: a.votes + (counts.get(a.id) ?? 0),
        }));
        state.artists = rank(rebuilt);
      },
    },
  ),
);

/** 选择器:按 ID 获取最新艺人 */
export function selectArtist(id: string) {
  return (s: VoteStore) => s.artists.find((a) => a.id === id);
}

/** 选择器:当前剩余票数 = 12 - 已投艺人数 */
export function selectRemaining(s: VoteStore): number {
  return Math.max(0, TOTAL_VOTE_QUOTA - s.votedArtists.length);
}

/** 选择器:是否已投过指定艺人(高阶,在组件里用 useVoteStore(selectHasVoted(id))) */
export function selectHasVoted(id: string) {
  return (s: VoteStore) => s.votedArtists.includes(id);
}

/** 选择器:12 票是否已全部投完 */
export function selectIsExhausted(s: VoteStore): boolean {
  return s.votedArtists.length >= TOTAL_VOTE_QUOTA;
}

/**
 * 派生函数:"我的应援"列表 —— 按投票顺序(最早投的在前)。
 *
 * ⚠️ 不要直接 `useVoteStore(selectMySupports)`:它每次都返回新数组,
 *    会触发 React 19 的 "getSnapshot should be cached" 报错。
 *    正确用法:在组件里 useMemo 派生(参考 MeContent.tsx)。
 */
export function selectMySupports(s: VoteStore): MySupport[] {
  const list: MySupport[] = [];
  for (const id of s.votedArtists) {
    const artist = s.artists.find((a) => a.id === id);
    if (artist) list.push({ artist });
  }
  return list;
}

/** 选择器:我支持的艺人数 = 投票数 */
export function selectMySupportingCount(s: VoteStore): number {
  return s.votedArtists.length;
}
