import { createApp, h } from 'vue'
import { afterEach, describe, expect, it, vi } from 'vitest'
import PlaylistSaved from '../src/components/PlaylistSaved.vue'
import { useApi } from '../src/composables/useApi'
import { parseSpotifyUrl } from '../src/lib/spotifyUrl'
import { parseStreamEvent } from '../src/lib/streamParser'

afterEach(() => vi.unstubAllGlobals())

describe('parseSpotifyUrl', () => {
  it.each([
    ['https://open.spotify.com/track/123', 'https://open.spotify.com/track/123'],
    [
      'https://open.spotify.com/playlist/123?si=abc',
      'https://open.spotify.com/playlist/123?si=abc',
    ],
  ])('accepts %s', (value, expected) => {
    expect(parseSpotifyUrl(value)).toBe(expected)
  })

  it.each([
    'http://open.spotify.com/track/123',
    'https://embed.spotify.com/track/123',
    'https://open.spotify.com:8443/track/123',
    'https://open.spotify.com.evil.example/track/123',
    'https://user@open.spotify.com/track/123',
    'javascript:alert(1)',
    '/track/123',
    'not a url',
  ])('rejects %s', (value) => {
    expect(parseSpotifyUrl(value)).toBeNull()
  })

  it('removes an unsafe track link at the event parsing boundary', () => {
    const event = parseStreamEvent({
      type: 'track',
      rank: 1,
      track: {
        id: 'track-1',
        uri: 'spotify:track:1',
        title: 'Track',
        artists: ['Artist'],
        album_name: 'Album',
        album_art_url: null,
        external_url: 'https://evil.example/track/1',
      },
      justification: 'It fits.',
    })

    expect(event).toMatchObject({ type: 'track', track: { external_url: null } })
  })

  it('keeps playlist confirmation but removes an unsafe API link', async () => {
    vi.stubGlobal(
      'fetch',
      vi.fn(
        async () =>
          new Response(JSON.stringify({ url: 'https://evil.example/playlist/1' }), {
            headers: { 'Content-Type': 'application/json' },
          }),
      ),
    )
    const { createPlaylist } = useApi()
    const result = await createPlaylist({
      schema_version: 1,
      name: 'Playlist',
      track_uris: ['spotify:track:1'],
    })
    const root = document.createElement('div')
    const app = createApp({
      render: () => h(PlaylistSaved, { name: 'Playlist', url: result.url, trackCount: 1 }),
    })
    app.mount(root)

    expect(root.textContent).toContain('Saved Playlist')
    expect(root.querySelector('a')).toBeNull()
    app.unmount()
  })
})
