import { defineStore } from 'pinia';
import { computed, ref, watch } from 'vue';
import { playersReplicant } from '../../../browser_shared/replicants';
import type { Schemas } from '../../../types';

type PlayersMap = Schemas.Players;
type Player = PlayersMap[string];

const STORAGE_KEY = 'scoreko-dev.players';

const normalizePlayer = (input: unknown): Player => {
  const candidate = typeof input === 'object' && input !== null ? (input as Record<string, unknown>) : {};
  return {
    gamertag: typeof candidate.gamertag === 'string' ? candidate.gamertag : '',
    name: typeof candidate.name === 'string' ? candidate.name : '',
    team: typeof candidate.team === 'string' ? candidate.team : '',
    country: typeof candidate.country === 'string' ? candidate.country : '',
    twitter: typeof candidate.twitter === 'string' ? candidate.twitter : '',
  };
};

const normalizePlayers = (input: unknown): PlayersMap => {
  if (typeof input !== 'object' || input === null) {
    return {};
  }
  const result: PlayersMap = {};
  Object.entries(input as Record<string, unknown>).forEach(([id, value]) => {
    if (!id) {
      return;
    }
    result[id] = normalizePlayer(value);
  });
  return result;
};

const readStorage = (): PlayersMap | null => {
  if (typeof window === 'undefined') {
    return null;
  }
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (!raw) {
      return null;
    }
    const parsed = JSON.parse(raw) as unknown;
    return normalizePlayers(parsed);
  } catch {
    return null;
  }
};

const writeStorage = (value: PlayersMap) => {
  if (typeof window === 'undefined') {
    return;
  }
  try {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
  } catch {
    // Ignore storage errors (quota, disabled, etc.)
  }
};

export const usePlayersStore = defineStore('players', () => {
  const players = ref<PlayersMap>({});
  const replicant = playersReplicant;
  const storageSnapshot = readStorage();
  if (storageSnapshot) {
    players.value = storageSnapshot;
  }

  const isApplyingReplicant = ref(false);

  watch(
    () => replicant?.data,
    (value) => {
      if (!value) {
        return;
      }
      isApplyingReplicant.value = true;
      players.value = normalizePlayers(value);
      isApplyingReplicant.value = false;
      writeStorage(players.value);
    },
    { deep: true, immediate: true }
  );

  watch(
    players,
    (value) => {
      writeStorage(value);
      if (isApplyingReplicant.value || !replicant) {
        return;
      }
      replicant.data = normalizePlayers(value);
      replicant.save();
    },
    { deep: true, flush: 'sync' }
  );

  const setPlayers = (value: PlayersMap) => {
    players.value = normalizePlayers(value);
  };

  const upsertPlayer = (id: string, player: Player) => {
    players.value = {
      ...players.value,
      [id]: normalizePlayer(player),
    };
  };

  const removePlayer = (id: string) => {
    const next = { ...players.value };
    delete next[id];
    players.value = next;
  };

  const rows = computed(() => Object.entries(players.value).map(([id, player]) => ({
    id,
    ...player,
  })));

  return {
    players,
    rows,
    setPlayers,
    upsertPlayer,
    removePlayer,
  };
});
