import type { YoutubePickerOpenPayload } from '../../types';
import type { ModalStateReader, RendererContext } from '../context';
import { YOMITAN_POPUP_COMMAND_EVENT } from '../yomitan-popup.js';

function createOption(value: string, label: string): HTMLOptionElement {
  const option = document.createElement('option');
  option.value = value;
  option.textContent = label;
  return option;
}

function payloadHasTracks(payload: YoutubePickerOpenPayload | null): boolean {
  return (payload?.tracks.length ?? 0) > 0;
}

export function createYoutubeTrackPickerModal(
  ctx: RendererContext,
  options: {
    modalStateReader: Pick<ModalStateReader, 'isAnyModalOpen'>;
    restorePointerInteractionState: () => void;
    syncSettingsModalSubtitleSuppression: () => void;
  },
) {
  const OPEN_KEY_GUARD_MS = 200;
  let resolveSelectionInFlight = false;
  let keyboardSubmitEnabledAtMs = 0;

  function setStatus(message: string, isError = false): void {
    ctx.state.youtubePickerStatus = message;
    ctx.dom.youtubePickerStatus.textContent = message;
    ctx.dom.youtubePickerStatus.style.color = isError ? '#ed8796' : '#a5adcb';
  }

  function getTrackLabel(trackId: string): string {
    return (
      ctx.state.youtubePickerPayload?.tracks.find((track) => track.id === trackId)?.label ?? ''
    );
  }

  function renderTrackList(): void {
    ctx.dom.youtubePickerTracks.replaceChildren();
    const payload = ctx.state.youtubePickerPayload;
    if (!payload || !payloadHasTracks(payload)) {
      const li = document.createElement('li');
      const left = document.createElement('span');
      left.textContent = 'No subtitle tracks found';
      const right = document.createElement('span');
      right.className = 'youtube-picker-track-meta';
      right.textContent = 'Continue without subtitles';
      li.append(left, right);
      ctx.dom.youtubePickerTracks.appendChild(li);
      return;
    }

    for (const track of payload.tracks) {
      const li = document.createElement('li');
      const left = document.createElement('span');
      left.textContent = track.label;
      const right = document.createElement('span');
      right.className = 'youtube-picker-track-meta';
      right.textContent = `${track.kind} · ${track.language}`;
      li.append(left, right);
      ctx.dom.youtubePickerTracks.appendChild(li);
    }
  }

  function setResolveControlsDisabled(disabled: boolean): void {
    ctx.dom.youtubePickerPrimarySelect.disabled = disabled;
    ctx.dom.youtubePickerSecondarySelect.disabled = disabled;
    ctx.dom.youtubePickerContinueButton.disabled = disabled;
    ctx.dom.youtubePickerCloseButton.disabled = disabled;
  }

  function syncSecondaryOptions(): void {
    const payload = ctx.state.youtubePickerPayload;
    const primaryTrackId = ctx.dom.youtubePickerPrimarySelect.value || null;
    ctx.dom.youtubePickerSecondarySelect.replaceChildren();
    ctx.dom.youtubePickerSecondarySelect.appendChild(createOption('', 'None'));
    if (!payload) return;

    for (const track of payload.tracks) {
      if (track.id === primaryTrackId) continue;
      ctx.dom.youtubePickerSecondarySelect.appendChild(createOption(track.id, track.label));
    }
    if (primaryTrackId && ctx.dom.youtubePickerSecondarySelect.value === primaryTrackId) {
      ctx.dom.youtubePickerSecondarySelect.value = '';
    }
  }

  function setSelection(primaryTrackId: string | null, secondaryTrackId: string | null): void {
    ctx.state.youtubePickerPrimaryTrackId = primaryTrackId;
    ctx.state.youtubePickerSecondaryTrackId = secondaryTrackId;
    ctx.dom.youtubePickerPrimarySelect.value = primaryTrackId ?? '';
    syncSecondaryOptions();
    ctx.dom.youtubePickerSecondarySelect.value = secondaryTrackId ?? '';
  }

  function applyPayload(payload: YoutubePickerOpenPayload): void {
    ctx.state.youtubePickerPayload = payload;
    ctx.dom.youtubePickerTitle.textContent = `Select YouTube subtitles for ${payload.url}`;
    ctx.dom.youtubePickerPrimarySelect.replaceChildren();
    ctx.dom.youtubePickerSecondarySelect.replaceChildren();

    if (!payloadHasTracks(payload)) {
      ctx.dom.youtubePickerPrimarySelect.appendChild(createOption('', 'No tracks available'));
      ctx.dom.youtubePickerPrimarySelect.disabled = true;
      ctx.dom.youtubePickerSecondarySelect.disabled = true;
      ctx.dom.youtubePickerContinueButton.textContent = 'Continue without subtitles';
      setSelection(null, null);
      setStatus('No subtitle tracks were found. Playback will continue without subtitles.');
      renderTrackList();
      return;
    }

    ctx.dom.youtubePickerPrimarySelect.disabled = false;
    ctx.dom.youtubePickerSecondarySelect.disabled = false;
    ctx.dom.youtubePickerContinueButton.textContent = 'Use selected subtitles';
    for (const track of payload.tracks) {
      ctx.dom.youtubePickerPrimarySelect.appendChild(createOption(track.id, track.label));
    }
    setSelection(payload.defaultPrimaryTrackId, payload.defaultSecondaryTrackId);
    renderTrackList();
    setStatus('Select the subtitle tracks to download.');
  }

  async function resolveSelection(
    action: 'use-selected' | 'continue-without-subtitles',
  ): Promise<void> {
    if (resolveSelectionInFlight) {
      return;
    }
    const payload = ctx.state.youtubePickerPayload;
    if (!payload) return;
    const hasTracks = payloadHasTracks(payload);
    if (action === 'use-selected' && hasTracks && !ctx.dom.youtubePickerPrimarySelect.value) {
      setStatus('Primary subtitle selection is required.', true);
      return;
    }

    resolveSelectionInFlight = true;
    setResolveControlsDisabled(true);
    try {
      const response =
        action === 'use-selected'
          ? await window.electronAPI.youtubePickerResolve({
              sessionId: payload.sessionId,
              action: 'use-selected',
              primaryTrackId: ctx.dom.youtubePickerPrimarySelect.value || null,
              secondaryTrackId: ctx.dom.youtubePickerSecondarySelect.value || null,
            })
          : await window.electronAPI.youtubePickerResolve({
              sessionId: payload.sessionId,
              action: 'continue-without-subtitles',
              primaryTrackId: null,
              secondaryTrackId: null,
            });
      if (!response.ok) {
        setStatus(response.message, true);
        return;
      }
      closeYoutubePickerModal();
    } catch (error) {
      setStatus(error instanceof Error ? error.message : String(error), true);
    } finally {
      resolveSelectionInFlight = false;
      const shouldKeepDisabled =
        ctx.state.youtubePickerModalOpen && !payloadHasTracks(ctx.state.youtubePickerPayload);
      setResolveControlsDisabled(shouldKeepDisabled);
    }
  }

  function openYoutubePickerModal(payload: YoutubePickerOpenPayload): void {
    keyboardSubmitEnabledAtMs = Date.now() + OPEN_KEY_GUARD_MS;
    if (ctx.state.youtubePickerModalOpen) {
      options.syncSettingsModalSubtitleSuppression();
      applyPayload(payload);
      window.electronAPI.notifyOverlayModalOpened('youtube-track-picker');
      return;
    }
    ctx.state.youtubePickerModalOpen = true;
    options.syncSettingsModalSubtitleSuppression();
    applyPayload(payload);
    ctx.dom.overlay.classList.add('interactive');
    ctx.dom.youtubePickerModal.classList.remove('hidden');
    ctx.dom.youtubePickerModal.setAttribute('aria-hidden', 'false');
    window.electronAPI.notifyOverlayModalOpened('youtube-track-picker');
  }

  function closeYoutubePickerModal(): void {
    if (!ctx.state.youtubePickerModalOpen) return;
    ctx.state.youtubePickerModalOpen = false;
    options.syncSettingsModalSubtitleSuppression();
    ctx.state.youtubePickerPayload = null;
    ctx.state.youtubePickerPrimaryTrackId = null;
    ctx.state.youtubePickerSecondaryTrackId = null;
    ctx.state.youtubePickerStatus = '';
    ctx.dom.youtubePickerModal.classList.add('hidden');
    ctx.dom.youtubePickerModal.setAttribute('aria-hidden', 'true');
    window.electronAPI.notifyOverlayModalClosed('youtube-track-picker');
    window.dispatchEvent(
      new CustomEvent(YOMITAN_POPUP_COMMAND_EVENT, {
        detail: {
          type: 'refreshOptions',
        },
      }),
    );
    if (!options.modalStateReader.isAnyModalOpen()) {
      ctx.dom.overlay.classList.remove('interactive');
    }
    options.restorePointerInteractionState();
    void window.electronAPI.focusMainWindow();
    if (typeof ctx.dom.overlay.focus === 'function') {
      ctx.dom.overlay.focus({ preventScroll: true });
    }
    if (ctx.platform.shouldToggleMouseIgnore) {
      if (!ctx.state.isOverSubtitle && !options.modalStateReader.isAnyModalOpen()) {
        window.electronAPI.setIgnoreMouseEvents(true, { forward: true });
      } else {
        window.electronAPI.setIgnoreMouseEvents(false);
      }
    }
    window.focus();
  }

  function handleYoutubePickerKeydown(e: KeyboardEvent): boolean {
    if (!ctx.state.youtubePickerModalOpen) return false;

    if (e.key === 'Escape') {
      e.preventDefault();
      void resolveSelection('continue-without-subtitles');
      return true;
    }

    if (e.key === 'Enter') {
      e.preventDefault();
      if (Date.now() < keyboardSubmitEnabledAtMs) {
        return true;
      }
      void resolveSelection(
        payloadHasTracks(ctx.state.youtubePickerPayload)
          ? 'use-selected'
          : 'continue-without-subtitles',
      );
      return true;
    }

    return false;
  }

  function wireDomEvents(): void {
    ctx.dom.youtubePickerPrimarySelect.addEventListener('change', () => {
      const primaryTrackId = ctx.dom.youtubePickerPrimarySelect.value || null;
      if (ctx.dom.youtubePickerSecondarySelect.value === primaryTrackId) {
        ctx.dom.youtubePickerSecondarySelect.value = '';
      }
      setSelection(primaryTrackId, ctx.dom.youtubePickerSecondarySelect.value || null);
    });

    ctx.dom.youtubePickerSecondarySelect.addEventListener('change', () => {
      const primaryTrackId = ctx.dom.youtubePickerPrimarySelect.value || null;
      const secondaryTrackId = ctx.dom.youtubePickerSecondarySelect.value || null;
      if (primaryTrackId && secondaryTrackId === primaryTrackId) {
        ctx.dom.youtubePickerSecondarySelect.value = '';
        setStatus('Primary and secondary subtitles must be different.', true);
        return;
      }
      setSelection(primaryTrackId, secondaryTrackId);
      setStatus('Select the subtitle tracks to download.');
    });

    ctx.dom.youtubePickerContinueButton.addEventListener('click', () => {
      void resolveSelection(
        payloadHasTracks(ctx.state.youtubePickerPayload)
          ? 'use-selected'
          : 'continue-without-subtitles',
      );
    });

    ctx.dom.youtubePickerCloseButton.addEventListener('click', () => {
      void resolveSelection('continue-without-subtitles');
    });
  }

  return {
    closeYoutubePickerModal,
    handleYoutubePickerKeydown,
    openYoutubePickerModal,
    wireDomEvents,
  };
}
