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

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

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 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 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 leftSelectedPlayer = computed(() => playersStore.players[scoreboardStore.scoreboard.leftPlayerId]);
const rightSelectedPlayer = computed(() => playersStore.players[scoreboardStore.scoreboard.rightPlayerId]);

const getPlayerLabel = (playerId: string) => {
  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 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 leftHasSelectedPlayerChanges = computed(() => {
  const player = leftSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.gamertag !== leftPendingGamertag.value
    || player.team !== scoreboardStore.scoreboard.leftTeamOverride
    || player.country !== scoreboardStore.scoreboard.leftCountryOverride;
});

const rightHasSelectedPlayerChanges = computed(() => {
  const player = rightSelectedPlayer.value;
  if (!player) {
    return false;
  }
  return player.gamertag !== rightPendingGamertag.value
    || player.team !== scoreboardStore.scoreboard.rightTeamOverride
    || player.country !== scoreboardStore.scoreboard.rightCountryOverride;
});

const leftPlayerOptions = computed(() => filterOptions(playerOptions.value, leftFilter.value));
const rightPlayerOptions = computed(() => filterOptions(playerOptions.value, rightFilter.value));

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

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

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

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

const onRightFocus = () => {
  rightFocused.value = true;
  rightInput.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;
  }

  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;
  }

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

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 saveLeftSelectedPlayerChanges = () => {
  const playerId = scoreboardStore.scoreboard.leftPlayerId;
  const player = playersStore.players[playerId];
  if (!player) {
    return;
  }
  playersStore.upsertPlayer(playerId, {
    ...player,
    gamertag: leftPendingGamertag.value,
    team: scoreboardStore.scoreboard.leftTeamOverride,
    country: scoreboardStore.scoreboard.leftCountryOverride,
  });
  scoreboardStore.scoreboard.leftNameOverride = '';
};

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

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;
  }
});

</script>

<template>
  <div class="scoreboard-panel">
    <div class="row items-center q-mb-md">
      <div class="text-h4">
        Scoreboard
      </div>
      <QSpace />
      <QBtn
        color="secondary"
        outline
        icon="swap_horiz"
        label="Intercambiar lados"
        class="q-mr-sm"
        @click="scoreboardStore.swapPlayers"
      />
      <QBtn
        color="secondary"
        outline
        icon="restart_alt"
        label="Reset scores"
        @click="scoreboardStore.resetScores"
      />
    </div>

    <div class="row q-col-gutter-lg">
      <div class="col-12 col-md-6">
        <QCard
          flat
          bordered
        >
          <QCardSection>
            <div class="text-subtitle1 text-weight-bold">
              Lado izquierdo
            </div>
          </QCardSection>
          <QSeparator />
          <QCardSection>
            <QSelect
              v-model="scoreboardStore.scoreboard.leftPlayerId"
              v-model:input-value="leftInput"
              :options="leftPlayerOptions"
              label="Jugador"
              dense
              outlined
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              @filter="onLeftFilter"
              @focus="onLeftFocus"
              @blur="onLeftBlur"
              @update:model-value="onLeftSelect"
            />
            <QInput
              v-model="scoreboardStore.scoreboard.leftTeamOverride"
              label="Team"
              dense
              outlined
              class="q-mt-sm"
            />
            <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
              outlined
              class="q-mt-sm"
              @filter="onLeftCountryFilter"
            />
            <QBtn
              v-if="leftCanSave"
              color="primary"
              icon="save"
              label="Guardar jugador"
              class="q-mt-sm"
              @click="saveLeftPlayer"
            />
            <QBtn
              v-if="leftHasSelectedPlayerChanges"
              color="primary"
              icon="save"
              label="Guardar cambios del jugador"
              class="q-mt-sm q-ml-sm"
              @click="saveLeftSelectedPlayerChanges"
            />
            <QInput
              v-model.number="scoreboardStore.leftScore"
              type="number"
              label="Score"
              dense
              outlined
              class="q-mt-md"
              min="0"
            />
          </QCardSection>
        </QCard>
      </div>

      <div class="col-12 col-md-6">
        <QCard
          flat
          bordered
        >
          <QCardSection>
            <div class="text-subtitle1 text-weight-bold">
              Lado derecho
            </div>
          </QCardSection>
          <QSeparator />
          <QCardSection>
            <QSelect
              v-model="scoreboardStore.scoreboard.rightPlayerId"
              v-model:input-value="rightInput"
              :options="rightPlayerOptions"
              label="Jugador"
              dense
              outlined
              emit-value
              map-options
              use-input
              input-debounce="0"
              hide-selected
              fill-input
              @filter="onRightFilter"
              @focus="onRightFocus"
              @blur="onRightBlur"
              @update:model-value="onRightSelect"
            />
            <QInput
              v-model="scoreboardStore.scoreboard.rightTeamOverride"
              label="Team"
              dense
              outlined
              class="q-mt-sm"
            />
            <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
              outlined
              class="q-mt-sm"
              @filter="onRightCountryFilter"
            />
            <QBtn
              v-if="rightCanSave"
              color="primary"
              icon="save"
              label="Guardar jugador"
              class="q-mt-sm"
              @click="saveRightPlayer"
            />
            <QBtn
              v-if="rightHasSelectedPlayerChanges"
              color="primary"
              icon="save"
              label="Guardar cambios del jugador"
              class="q-mt-sm q-ml-sm"
              @click="saveRightSelectedPlayerChanges"
            />
            <QInput
              v-model.number="scoreboardStore.rightScore"
              type="number"
              label="Score"
              dense
              outlined
              class="q-mt-md"
              min="0"
            />
          </QCardSection>
        </QCard>
      </div>
    </div>
  </div>
</template>

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