<script setup lang="ts">
import { computed, ref, watch, watchEffect, type Ref } from 'vue';
import { countryOptions, getCountryLabel } from '../../../shared/countries';
import { getCharactersByGame } from '../../../shared/fighting-characters';
import type { Schemas } from '../../../types';
import { usePlayersStore } from '../stores/players';
import { useScoreboardStore } from '../stores/scoreboard';

const playersStore = usePlayersStore();
const scoreboardStore = useScoreboardStore();

const CUSTOM_LEFT_PLAYER_ID = '__custom_left_player__';
const CUSTOM_RIGHT_PLAYER_ID = '__custom_right_player__';

const leftFilter = ref('');
const rightFilter = ref('');
const leftInput = ref('');
const rightInput = ref('');
const leftFocused = ref(false);
const rightFocused = ref(false);

const leftCountryInput = ref('');
const rightCountryInput = ref('');
const leftCountryOptions = ref(countryOptions);
const rightCountryOptions = ref(countryOptions);

const leftCharacterInput = ref('');
const rightCharacterInput = ref('');
const gameInput = ref('');

const allFightingGameOptions = [
  'Street Fighter 6',
  'TEKKEN 8',
  'Guilty Gear -Strive-',
  'Mortal Kombat 1',
  'The King of Fighters XV',
  'Granblue Fantasy Versus: Rising',
  '2XKO',
].map((game) => ({
  label: game,
  value: game,
}));

const fightingGameOptions = ref(allFightingGameOptions);

const characterOptions = computed(() => getCharactersByGame(scoreboardStore.scoreboard.game));
type CharacterOption = ReturnType<typeof getCharactersByGame>[number];
const leftCharacterOptions = ref<CharacterOption[]>([]);
const rightCharacterOptions = ref<CharacterOption[]>([]);

const leftCharacterImage = computed(() => {
  const match = characterOptions.value.find((option) => option.value === scoreboardStore.scoreboard.leftCharacter);
  return match?.image ?? '';
});

const rightCharacterImage = computed(() => {
  const match = characterOptions.value.find((option) => option.value === scoreboardStore.scoreboard.rightCharacter);
  return match?.image ?? '';
});

const leftPanelImage = computed(() => leftCharacterImage.value);
const rightPanelImage = computed(() => rightCharacterImage.value);


const normalizeName = (value: string) => value.trim().toLowerCase();

const filterOptions = (
  options: { label: string; value: string }[],
  needle: string,
) => {
  if (!needle) {
    return options;
  }
  const lowerNeedle = needle.toLowerCase();
  return options.filter((option) => option.label.toLowerCase().includes(lowerNeedle));
};

const filterCountries = (
  value: string,
  update: (callback: () => void) => void,
  target: Ref<{ value: string; label: string }[]>,
) => {
  update(() => {
    const needle = value.toLowerCase().trim();
    if (!needle) {
      target.value = countryOptions;
      return;
    }
    target.value = countryOptions.filter((country) => country.label.toLowerCase().includes(needle));
  });
};


const onLeftCountryFilter = (value: string, update: (callback: () => void) => void) => {
  filterCountries(value, update, leftCountryOptions);
};

const onRightCountryFilter = (value: string, update: (callback: () => void) => void) => {
  filterCountries(value, update, rightCountryOptions);
};


const filterCharacters = (
  value: string,
  update: (callback: () => void) => void,
  target: Ref<CharacterOption[]>,
) => {
  update(() => {
    const needle = value.toLowerCase().trim();
    if (!needle) {
      target.value = characterOptions.value;
      return;
    }
    target.value = characterOptions.value.filter((character) => character.label.toLowerCase().includes(needle));
  });
};

const onLeftCharacterFilter = (value: string, update: (callback: () => void) => void) => {
  filterCharacters(value, update, leftCharacterOptions);
};

const onRightCharacterFilter = (value: string, update: (callback: () => void) => void) => {
  filterCharacters(value, update, rightCharacterOptions);
};

const onGameFilter = (value: string, update: (callback: () => void) => void) => {
  update(() => {
    const needle = value.toLowerCase().trim();
    if (!needle) {
      fightingGameOptions.value = allFightingGameOptions;
      return;
    }
    fightingGameOptions.value = allFightingGameOptions.filter((game) => game.label.toLowerCase().includes(needle));
  });
};

const playerOptions = computed(() => {
  const base = [{ label: '(Sin asignar)', value: '' }];
  const entries = Object.entries(playersStore.players) as [string, Schemas.Players[string]][];
  const options = entries.map(([id, player]) => ({
    value: id,
    label: player.gamertag || id,
  }));
  return base.concat(options);
});

const buildPlayerOptions = (
  filterValue: string,
  selectedPlayerId: string,
  customPlayerId: string,
  customNameOverride: string,
) => {
  const options = filterOptions(playerOptions.value, filterValue);
  if (selectedPlayerId !== customPlayerId || !customNameOverride.trim()) {
    return options;
  }
  return [{
    value: customPlayerId,
    label: customNameOverride,
  }].concat(options);
};

const leftPlayerOptions = computed(() => buildPlayerOptions(
  leftFilter.value,
  scoreboardStore.scoreboard.leftPlayerId,
  CUSTOM_LEFT_PLAYER_ID,
  scoreboardStore.scoreboard.leftNameOverride,
));

const rightPlayerOptions = computed(() => buildPlayerOptions(
  rightFilter.value,
  scoreboardStore.scoreboard.rightPlayerId,
  CUSTOM_RIGHT_PLAYER_ID,
  scoreboardStore.scoreboard.rightNameOverride,
));

const leftSelectedPlayer = computed(() => playersStore.players[scoreboardStore.scoreboard.leftPlayerId]);
const rightSelectedPlayer = computed(() => playersStore.players[scoreboardStore.scoreboard.rightPlayerId]);

const getPlayerLabel = (playerId: string) => {
  if (playerId === CUSTOM_LEFT_PLAYER_ID) {
    return scoreboardStore.scoreboard.leftNameOverride;
  }
  if (playerId === CUSTOM_RIGHT_PLAYER_ID) {
    return scoreboardStore.scoreboard.rightNameOverride;
  }
  const match = playerOptions.value.find((option) => option.value === playerId);
  return match ? match.label : '';
};

const playerExistsByGamertag = (name: string) => {
  const normalized = normalizeName(name);
  if (!normalized) {
    return false;
  }
  return Object.values(playersStore.players).some((player) => normalizeName(player.gamertag || '') === normalized);
};

const leftDisplayName = computed(() => scoreboardStore.scoreboard.leftNameOverride || getPlayerLabel(scoreboardStore.scoreboard.leftPlayerId));
const rightDisplayName = computed(() => scoreboardStore.scoreboard.rightNameOverride || getPlayerLabel(scoreboardStore.scoreboard.rightPlayerId));

const leftCanSave = computed(
  () => Boolean(scoreboardStore.scoreboard.leftNameOverride.trim())
    && !playerExistsByGamertag(scoreboardStore.scoreboard.leftNameOverride),
);

const rightCanSave = computed(
  () => Boolean(scoreboardStore.scoreboard.rightNameOverride.trim())
    && !playerExistsByGamertag(scoreboardStore.scoreboard.rightNameOverride),
);

const leftTeamChanged = computed(() => {
  const player = leftSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.team !== scoreboardStore.scoreboard.leftTeamOverride;
});

const rightTeamChanged = computed(() => {
  const player = rightSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.team !== scoreboardStore.scoreboard.rightTeamOverride;
});

const leftCountryChanged = computed(() => {
  const player = leftSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.country !== scoreboardStore.scoreboard.leftCountryOverride;
});

const rightCountryChanged = computed(() => {
  const player = rightSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.country !== scoreboardStore.scoreboard.rightCountryOverride;
});

const leftPendingGamertag = computed(() => {
  const override = scoreboardStore.scoreboard.leftNameOverride.trim();
  if (override) {
    return override;
  }
  return leftSelectedPlayer.value?.gamertag ?? '';
});

const rightPendingGamertag = computed(() => {
  const override = scoreboardStore.scoreboard.rightNameOverride.trim();
  if (override) {
    return override;
  }
  return rightSelectedPlayer.value?.gamertag ?? '';
});

const leftNameChanged = computed(() => {
  const player = leftSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.gamertag !== leftPendingGamertag.value;
});

const rightNameChanged = computed(() => {
  const player = rightSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.gamertag !== rightPendingGamertag.value;
});

const leftCanSaveNameChange = computed(
  () => leftNameChanged.value && !playerExistsByGamertag(leftPendingGamertag.value),
);

const rightCanSaveNameChange = computed(
  () => rightNameChanged.value && !playerExistsByGamertag(rightPendingGamertag.value),
);

const leftShowsNameSave = computed(() => leftCanSave.value || leftCanSaveNameChange.value);
const rightShowsNameSave = computed(() => rightCanSave.value || rightCanSaveNameChange.value);

const startLeftCustomPlayer = () => {
  const wasCustom = scoreboardStore.scoreboard.leftPlayerId === CUSTOM_LEFT_PLAYER_ID;
  scoreboardStore.scoreboard.leftPlayerId = CUSTOM_LEFT_PLAYER_ID;
  if (!wasCustom) {
    scoreboardStore.scoreboard.leftTeamOverride = '';
    scoreboardStore.scoreboard.leftCountryOverride = '';
  }
};

const startRightCustomPlayer = () => {
  const wasCustom = scoreboardStore.scoreboard.rightPlayerId === CUSTOM_RIGHT_PLAYER_ID;
  scoreboardStore.scoreboard.rightPlayerId = CUSTOM_RIGHT_PLAYER_ID;
  if (!wasCustom) {
    scoreboardStore.scoreboard.rightTeamOverride = '';
    scoreboardStore.scoreboard.rightCountryOverride = '';
  }
};

const filterPlayerInput = (
  val: string,
  update: (fn: () => void) => void,
  filterValue: Ref<string>,
  focused: Ref<boolean>,
  inputValue: Ref<string>,
  selectedPlayerId: string,
  customPlayerId: string,
  customNameOverride: string,
  setCustomNameOverride: (value: string) => void,
  startCustomPlayer: () => void,
) => {
  update(() => {
    filterValue.value = val;

    if (!focused.value) {
      return;
    }

    if (!val.trim() && selectedPlayerId === customPlayerId) {
      inputValue.value = customNameOverride;
      return;
    }

    inputValue.value = val;
    setCustomNameOverride(val);
    if (val.trim()) {
      startCustomPlayer();
    }
  });
};

const onLeftFilter = (val: string, update: (fn: () => void) => void) => {
  filterPlayerInput(
    val,
    update,
    leftFilter,
    leftFocused,
    leftInput,
    scoreboardStore.scoreboard.leftPlayerId,
    CUSTOM_LEFT_PLAYER_ID,
    scoreboardStore.scoreboard.leftNameOverride,
    (value) => {
      scoreboardStore.scoreboard.leftNameOverride = value;
    },
    startLeftCustomPlayer,
  );
};

const onRightFilter = (val: string, update: (fn: () => void) => void) => {
  filterPlayerInput(
    val,
    update,
    rightFilter,
    rightFocused,
    rightInput,
    scoreboardStore.scoreboard.rightPlayerId,
    CUSTOM_RIGHT_PLAYER_ID,
    scoreboardStore.scoreboard.rightNameOverride,
    (value) => {
      scoreboardStore.scoreboard.rightNameOverride = value;
    },
    startRightCustomPlayer,
  );
};

const onLeftFocus = () => {
  leftFocused.value = true;
  leftInput.value = leftDisplayName.value;
};

const onLeftBlur = () => {
  leftFocused.value = false;
  leftFilter.value = '';
  leftInput.value = leftDisplayName.value;
};

const onRightFocus = () => {
  rightFocused.value = true;
  rightInput.value = rightDisplayName.value;
};

const onRightBlur = () => {
  rightFocused.value = false;
  rightFilter.value = '';
  rightInput.value = rightDisplayName.value;
};

const applyLeftPlayerData = (playerId: string) => {
  const player = playersStore.players[playerId];
  scoreboardStore.scoreboard.leftTeamOverride = player?.team ?? '';
  scoreboardStore.scoreboard.leftCountryOverride = player?.country ?? '';
  leftCountryInput.value = getCountryLabel(scoreboardStore.scoreboard.leftCountryOverride);
};

const applyRightPlayerData = (playerId: string) => {
  const player = playersStore.players[playerId];
  scoreboardStore.scoreboard.rightTeamOverride = player?.team ?? '';
  scoreboardStore.scoreboard.rightCountryOverride = player?.country ?? '';
  rightCountryInput.value = getCountryLabel(scoreboardStore.scoreboard.rightCountryOverride);
};

const onLeftSelect = (playerId: string) => {
  const hasExistingPlayer = Boolean(playerId && playersStore.players[playerId]);
  if (!hasExistingPlayer) {
    return;
  }

  leftFocused.value = false;
  scoreboardStore.scoreboard.leftNameOverride = '';
  leftFilter.value = '';
  leftInput.value = getPlayerLabel(playerId);
  applyLeftPlayerData(playerId);
};

const onRightSelect = (playerId: string) => {
  const hasExistingPlayer = Boolean(playerId && playersStore.players[playerId]);
  if (!hasExistingPlayer) {
    return;
  }

  rightFocused.value = false;
  scoreboardStore.scoreboard.rightNameOverride = '';
  rightFilter.value = '';
  rightInput.value = getPlayerLabel(playerId);
  applyRightPlayerData(playerId);
};

const adjustLeftScore = (delta: number) => {
  scoreboardStore.leftScore = Math.max(0, scoreboardStore.leftScore + delta);
};

const adjustRightScore = (delta: number) => {
  scoreboardStore.rightScore = Math.max(0, scoreboardStore.rightScore + delta);
};

const createPlayerId = (name: string) => {
  const base = name
    .trim()
    .toLowerCase()
    .normalize('NFD')
    .replace(/[^\w\s-]/g, '')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/\s+/g, '-');

  const seed = base || 'player';
  let index = 1;
  let candidate = seed;
  while (playersStore.players[candidate]) {
    index += 1;
    candidate = `${seed}-${index}`;
  }
  return candidate;
};

const saveLeftPlayer = () => {
  const gamertag = scoreboardStore.scoreboard.leftNameOverride.trim();
  if (!gamertag || playerExistsByGamertag(gamertag)) {
    return;
  }
  const id = createPlayerId(gamertag);
  playersStore.upsertPlayer(id, {
    gamertag,
    name: '',
    team: scoreboardStore.scoreboard.leftTeamOverride,
    country: scoreboardStore.scoreboard.leftCountryOverride,
    twitter: '',
  });
  scoreboardStore.scoreboard.leftPlayerId = id;
  scoreboardStore.scoreboard.leftNameOverride = '';
  leftInput.value = gamertag;
};

const saveRightPlayer = () => {
  const gamertag = scoreboardStore.scoreboard.rightNameOverride.trim();
  if (!gamertag || playerExistsByGamertag(gamertag)) {
    return;
  }
  const id = createPlayerId(gamertag);
  playersStore.upsertPlayer(id, {
    gamertag,
    name: '',
    team: scoreboardStore.scoreboard.rightTeamOverride,
    country: scoreboardStore.scoreboard.rightCountryOverride,
    twitter: '',
  });
  scoreboardStore.scoreboard.rightPlayerId = id;
  scoreboardStore.scoreboard.rightNameOverride = '';
  rightInput.value = gamertag;
};

const saveLeftNameChange = () => {
  const playerId = scoreboardStore.scoreboard.leftPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  if (!leftCanSaveNameChange.value) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    gamertag: leftPendingGamertag.value,
  });
  scoreboardStore.scoreboard.leftNameOverride = '';
};

const saveRightNameChange = () => {
  const playerId = scoreboardStore.scoreboard.rightPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  if (!rightCanSaveNameChange.value) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    gamertag: rightPendingGamertag.value,
  });
  scoreboardStore.scoreboard.rightNameOverride = '';
};

const saveLeftTeamChange = () => {
  const playerId = scoreboardStore.scoreboard.leftPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    team: scoreboardStore.scoreboard.leftTeamOverride,
  });
};

const saveRightTeamChange = () => {
  const playerId = scoreboardStore.scoreboard.rightPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    team: scoreboardStore.scoreboard.rightTeamOverride,
  });
};

const saveLeftCountryChange = () => {
  const playerId = scoreboardStore.scoreboard.leftPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    country: scoreboardStore.scoreboard.leftCountryOverride,
  });
};

const saveRightCountryChange = () => {
  const playerId = scoreboardStore.scoreboard.rightPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    country: scoreboardStore.scoreboard.rightCountryOverride,
  });
};

const onLeftNameSave = () => {
  if (leftCanSave.value) {
    saveLeftPlayer();
    return;
  }
  saveLeftNameChange();
};

const onRightNameSave = () => {
  if (rightCanSave.value) {
    saveRightPlayer();
    return;
  }
  saveRightNameChange();
};



watch(
  () => scoreboardStore.scoreboard.leftPlayerId,
  (playerId) => {
    applyLeftPlayerData(playerId);
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.rightPlayerId,
  (playerId) => {
    applyRightPlayerData(playerId);
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.leftCountryOverride,
  (value) => {
    leftCountryInput.value = getCountryLabel(value);
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.rightCountryOverride,
  (value) => {
    rightCountryInput.value = getCountryLabel(value);
  },
  { immediate: true },
);

watchEffect(() => {
  if (!leftFocused.value) {
    leftInput.value = leftDisplayName.value;
  }
});

watchEffect(() => {
  if (!rightFocused.value) {
    rightInput.value = rightDisplayName.value;
  }
});


watch(
  () => scoreboardStore.scoreboard.game,
  (value) => {
    const match = allFightingGameOptions.find((option) => option.value === value);
    gameInput.value = match?.label ?? '';
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.game,
  () => {
    const options = getCharactersByGame(scoreboardStore.scoreboard.game);
    leftCharacterOptions.value = options;
    rightCharacterOptions.value = options;
    const allowed = new Set(options.map((option) => option.value));

    if (!allowed.has(scoreboardStore.scoreboard.leftCharacter)) {
      scoreboardStore.scoreboard.leftCharacter = '';
      leftCharacterInput.value = '';
    }

    if (!allowed.has(scoreboardStore.scoreboard.rightCharacter)) {
      scoreboardStore.scoreboard.rightCharacter = '';
      rightCharacterInput.value = '';
    }
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.leftCharacter,
  (value) => {
    const match = characterOptions.value.find((option) => option.value === value);
    leftCharacterInput.value = match?.label ?? '';
  },
  { immediate: true },
);

watch(
  () => scoreboardStore.scoreboard.rightCharacter,
  (value) => {
    const match = characterOptions.value.find((option) => option.value === value);
    rightCharacterInput.value = match?.label ?? '';
  },
  { immediate: true },
);

</script>

<template>
  <div class="scoreboard-panel">
    <div class="row items-center q-mb-md">
      <div class="text-h4">
        Scoreboard
      </div>
    </div>

    <QCard
      flat
      bordered
      class="scoreboard-preview"
    >
      <div class="scoreboard-preview__side">
        <div class="scoreboard-preview__side-inner">
          <div class="scoreboard-preview__image-column">
            <div class="scoreboard-preview__image-wrap">
              <img
                v-if="leftPanelImage"
                :src="leftPanelImage"
                :alt="`${leftDisplayName || 'Left'} preview`"
                class="scoreboard-preview__image"
              >
              <div
                v-else
                class="scoreboard-preview__empty"
              >
                Left image
              </div>
            </div>
            <QSelect
              v-model="scoreboardStore.scoreboard.leftCharacter"
              v-model:input-value="leftCharacterInput"
              :options="leftCharacterOptions"
              option-value="value"
              option-label="label"
              emit-value
              map-options
              label="Character"
              dense
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              clearable
              class="scoreboard-preview__field scoreboard-preview__character-field"
              :disable="!scoreboardStore.scoreboard.game"
              @filter="onLeftCharacterFilter"
            />
          </div>
          <div class="scoreboard-preview__controls">
            <QSelect
              v-model="scoreboardStore.scoreboard.leftPlayerId"
              v-model:input-value="leftInput"
              :options="leftPlayerOptions"
              label="Player"
              dense
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              options-dense
              class="scoreboard-preview__field"
              @filter="onLeftFilter"
              @focus="onLeftFocus"
              @blur="onLeftBlur"
              @update:model-value="onLeftSelect"
            >
              <template #append>
                <QBtn
                  v-if="leftShowsNameSave"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="onLeftNameSave"
                />
              </template>
            </QSelect>
            <QInput
              v-model="scoreboardStore.scoreboard.leftTeamOverride"
              label="Team"
              dense
              class="scoreboard-preview__field"
            >
              <template #append>
                <QBtn
                  v-if="leftTeamChanged"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="saveLeftTeamChange"
                />
              </template>
            </QInput>
            <QSelect
              v-model="scoreboardStore.scoreboard.leftCountryOverride"
              v-model:input-value="leftCountryInput"
              :options="leftCountryOptions"
              option-value="value"
              option-label="label"
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              clearable
              label="Country"
              dense
              class="scoreboard-preview__field"
              @filter="onLeftCountryFilter"
            >
              <template #append>
                <QBtn
                  v-if="leftCountryChanged"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="saveLeftCountryChange"
                />
              </template>
            </QSelect>
          </div>
        </div>
      </div>

      <div class="scoreboard-preview__center">
        <QSelect
          v-model="scoreboardStore.scoreboard.game"
          v-model:input-value="gameInput"
          :options="fightingGameOptions"
          label="Juego"
          dense
          emit-value
          map-options
          use-input
          input-debounce="0"
          hide-selected
          fill-input
          class="scoreboard-preview__field scoreboard-preview__game-field"
          @filter="onGameFilter"
        />

        <div class="scoreboard-preview__score-controls">
          <div class="scoreboard-preview__score-side">
            <QBtn
              flat
              dense
              round
              size="sm"
              icon="add"
              @click="adjustLeftScore(1)"
            />
            <span class="scoreboard-preview__score-value">{{ scoreboardStore.scoreboard.leftScore }}</span>
            <QBtn
              flat
              dense
              round
              size="sm"
              icon="remove"
              @click="adjustLeftScore(-1)"
            />
          </div>

          <span class="scoreboard-preview__dash">-</span>

          <div class="scoreboard-preview__score-side">
            <QBtn
              flat
              dense
              round
              size="sm"
              icon="add"
              @click="adjustRightScore(1)"
            />
            <span class="scoreboard-preview__score-value">{{ scoreboardStore.scoreboard.rightScore }}</span>
            <QBtn
              flat
              dense
              round
              size="sm"
              icon="remove"
              @click="adjustRightScore(-1)"
            />
          </div>
        </div>

        <div class="scoreboard-preview__actions">
          <QBtn
            flat
            dense
            icon="swap_horiz"
            class="scoreboard-preview__action-btn"
            @click="scoreboardStore.swapPlayers"
          />
          <QBtn
            flat
            dense
            icon="restart_alt"
            class="scoreboard-preview__action-btn"
            @click="scoreboardStore.resetScores"
          />
        </div>
      </div>

      <div class="scoreboard-preview__side scoreboard-preview__side--right">
        <div class="scoreboard-preview__side-inner">
          <div class="scoreboard-preview__controls">
            <QSelect
              v-model="scoreboardStore.scoreboard.rightPlayerId"
              v-model:input-value="rightInput"
              :options="rightPlayerOptions"
              label="Player"
              dense
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              options-dense
              class="scoreboard-preview__field"
              @filter="onRightFilter"
              @focus="onRightFocus"
              @blur="onRightBlur"
              @update:model-value="onRightSelect"
            >
              <template #append>
                <QBtn
                  v-if="rightShowsNameSave"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="onRightNameSave"
                />
              </template>
            </QSelect>
            <QInput
              v-model="scoreboardStore.scoreboard.rightTeamOverride"
              label="Team"
              dense
              class="scoreboard-preview__field"
            >
              <template #append>
                <QBtn
                  v-if="rightTeamChanged"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="saveRightTeamChange"
                />
              </template>
            </QInput>
            <QSelect
              v-model="scoreboardStore.scoreboard.rightCountryOverride"
              v-model:input-value="rightCountryInput"
              :options="rightCountryOptions"
              option-value="value"
              option-label="label"
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              clearable
              label="Country"
              dense
              class="scoreboard-preview__field"
              @filter="onRightCountryFilter"
            >
              <template #append>
                <QBtn
                  v-if="rightCountryChanged"
                  flat
                  round
                  dense
                  icon="save"
                  color="primary"
                  @click.stop="saveRightCountryChange"
                />
              </template>
            </QSelect>
          </div>
          <div class="scoreboard-preview__image-column">
            <div class="scoreboard-preview__image-wrap">
              <img
                v-if="rightPanelImage"
                :src="rightPanelImage"
                :alt="`${rightDisplayName || 'Right'} preview`"
                class="scoreboard-preview__image"
              >
              <div
                v-else
                class="scoreboard-preview__empty"
              >
                Right image
              </div>
            </div>
            <QSelect
              v-model="scoreboardStore.scoreboard.rightCharacter"
              v-model:input-value="rightCharacterInput"
              :options="rightCharacterOptions"
              option-value="value"
              option-label="label"
              emit-value
              map-options
              label="Character"
              dense
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              clearable
              class="scoreboard-preview__field scoreboard-preview__character-field"
              :disable="!scoreboardStore.scoreboard.game"
              @filter="onRightCharacterFilter"
            />
          </div>
        </div>
      </div>
    </QCard>
  </div>
</template>

<style scoped>
.scoreboard-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
}


.scoreboard-preview {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, auto) minmax(0, 1fr);
  gap: 18px;
  padding: 16px;
  align-items: center;
}

.scoreboard-preview__side {
  display: flex;
  align-items: center;
}

.scoreboard-preview__image-column {
  width: min(100%, 320px);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.scoreboard-preview__side-inner {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(220px, 320px) minmax(180px, 1fr);
  align-items: center;
  gap: 14px;
}

.scoreboard-preview__side--right {
  text-align: right;
}

.scoreboard-preview__side--right .scoreboard-preview__side-inner {
  grid-template-columns: minmax(180px, 1fr) minmax(220px, 320px);
}


.scoreboard-preview__side .scoreboard-preview__image-column {
  justify-self: start;
}

.scoreboard-preview__side--right .scoreboard-preview__image-column {
  justify-self: end;
}

.scoreboard-preview__image-wrap {
  width: min(100%, 320px);
  aspect-ratio: 4 / 4;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: #2f3a4f;
}

.scoreboard-preview__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  transform: scale(2);
  transform-origin: center;
}

.scoreboard-preview__empty {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.65);
  font-weight: 600;
}

.scoreboard-preview__controls {
  width: min(100%, 260px);
  justify-self: center;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.scoreboard-preview__field {
  margin: 0;
}

.scoreboard-preview__character-field {
  margin-top: 2px;
}

.scoreboard-preview__field :deep(.q-field__control) {
  min-height: 28px;
  padding: 0;
  background: transparent !important;
  border-radius: 0;
}

.scoreboard-preview__field :deep(.q-field__control:before),
.scoreboard-preview__field :deep(.q-field__control:after) {
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.34);
}

.scoreboard-preview__field :deep(.q-field__native),
.scoreboard-preview__field :deep(.q-field__input),
.scoreboard-preview__field :deep(.q-field__label) {
  color: rgba(255, 255, 255, 0.92);
}

.scoreboard-preview__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  align-self: stretch;
  justify-content: flex-start;
  padding-top: 2px;
  gap: 10px;
}

.scoreboard-preview__game-field {
  width: min(100%, 240px);
  margin-bottom: 56px;
}

.scoreboard-preview__score-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
}

.scoreboard-preview__actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.scoreboard-preview__action-btn {
  color: #fff;
  opacity: 0.85;
}

.scoreboard-preview__action-btn:hover {
  opacity: 1;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.45);
}

.scoreboard-preview__score-side {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.scoreboard-preview__score-value {
  min-width: 64px;
  text-align: center;
  font-size: clamp(4rem, 7vw, 5.6rem);
  font-weight: 800;
  line-height: 1;
}

.scoreboard-preview__dash {
  opacity: 0.7;
  font-size: clamp(3rem, 5vw, 4rem);
  font-weight: 700;
}


@media (min-width: 1024px) {
  .scoreboard-preview {
    grid-template-columns: minmax(0, 1fr) minmax(320px, auto) minmax(0, 1fr);
  }
}

@media (max-width: 900px) {
  .scoreboard-preview {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .scoreboard-preview__center {
    order: -1;
    justify-self: center;
  }

  .scoreboard-preview__image-wrap {
    width: min(100%, 280px);
  }

  .scoreboard-preview__side-inner {
    grid-template-columns: 1fr;
    align-items: flex-start;
    justify-items: flex-start;
  }

  .scoreboard-preview__side--right {
    text-align: left;
  }

  .scoreboard-preview__side--right .scoreboard-preview__side-inner {
    grid-template-columns: 1fr;
  }
}

</style>
