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

type Scoreboard = Schemas.Scoreboard;

const STORAGE_KEY = 'scoreko-dev.scoreboard';

const defaultScoreboard: Scoreboard = {
  leftPlayerId: '',
  rightPlayerId: '',
  leftNameOverride: '',
  rightNameOverride: '',
  leftTeamOverride: '',
  rightTeamOverride: '',
  leftCountryOverride: '',
  rightCountryOverride: '',
  leftCharacter: '',
  rightCharacter: '',
  leftScore: 0,
  rightScore: 0,
  round: '',
  game: '',
};

const normalizeScoreboard = (input: unknown): Scoreboard => {
  const candidate = typeof input === 'object' && input !== null ? (input as Record<string, unknown>) : {};
  return {
    leftPlayerId: typeof candidate.leftPlayerId === 'string' ? candidate.leftPlayerId : '',
    rightPlayerId: typeof candidate.rightPlayerId === 'string' ? candidate.rightPlayerId : '',
    leftNameOverride: typeof candidate.leftNameOverride === 'string' ? candidate.leftNameOverride : '',
    rightNameOverride: typeof candidate.rightNameOverride === 'string' ? candidate.rightNameOverride : '',
    leftTeamOverride: typeof candidate.leftTeamOverride === 'string' ? candidate.leftTeamOverride : '',
    rightTeamOverride: typeof candidate.rightTeamOverride === 'string' ? candidate.rightTeamOverride : '',
    leftCountryOverride: typeof candidate.leftCountryOverride === 'string' ? candidate.leftCountryOverride : '',
    rightCountryOverride: typeof candidate.rightCountryOverride === 'string' ? candidate.rightCountryOverride : '',
    leftCharacter: typeof candidate.leftCharacter === 'string' ? candidate.leftCharacter : '',
    rightCharacter: typeof candidate.rightCharacter === 'string' ? candidate.rightCharacter : '',
    leftScore: typeof candidate.leftScore === 'number' ? Math.max(0, Math.floor(candidate.leftScore)) : 0,
    rightScore: typeof candidate.rightScore === 'number' ? Math.max(0, Math.floor(candidate.rightScore)) : 0,
    round: typeof candidate.round === 'string' ? candidate.round : '',
    game: typeof candidate.game === 'string' ? candidate.game : '',
  };
};

const readStorage = (): Scoreboard | 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 normalizeScoreboard(parsed);
  } catch {
    return null;
  }
};

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

export const useScoreboardStore = defineStore('scoreboard', () => {
  const scoreboard = ref<Scoreboard>({ ...defaultScoreboard });
  const replicant = scoreboardReplicant;
  const storageSnapshot = readStorage();
  if (storageSnapshot) {
    scoreboard.value = storageSnapshot;
  }

  const isApplyingReplicant = ref(false);

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

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

  const setScoreboard = (value: Scoreboard) => {
    scoreboard.value = normalizeScoreboard(value);
  };

  const swapPlayers = () => {
    scoreboard.value = {
      ...scoreboard.value,
      leftPlayerId: scoreboard.value.rightPlayerId,
      rightPlayerId: scoreboard.value.leftPlayerId,
      leftNameOverride: scoreboard.value.rightNameOverride,
      rightNameOverride: scoreboard.value.leftNameOverride,
      leftTeamOverride: scoreboard.value.rightTeamOverride,
      rightTeamOverride: scoreboard.value.leftTeamOverride,
      leftCountryOverride: scoreboard.value.rightCountryOverride,
      rightCountryOverride: scoreboard.value.leftCountryOverride,
      leftCharacter: scoreboard.value.rightCharacter,
      rightCharacter: scoreboard.value.leftCharacter,
      leftScore: scoreboard.value.rightScore,
      rightScore: scoreboard.value.leftScore,
    };
  };

  const resetScores = () => {
    scoreboard.value = {
      ...scoreboard.value,
      leftScore: 0,
      rightScore: 0,
    };
  };

  const leftScore = computed({
    get: () => scoreboard.value.leftScore,
    set: (value: number) => {
      scoreboard.value = {
        ...scoreboard.value,
        leftScore: Math.max(0, Math.floor(value)),
      };
    },
  });

  const rightScore = computed({
    get: () => scoreboard.value.rightScore,
    set: (value: number) => {
      scoreboard.value = {
        ...scoreboard.value,
        rightScore: Math.max(0, Math.floor(value)),
      };
    },
  });

  return {
    scoreboard,
    leftScore,
    rightScore,
    setScoreboard,
    swapPlayers,
    resetScores,
  };
});
