import request from 'supertest'
import { generateSimpleViteManifest, mockApp, mockConfig, mockFetch, mockRedis } from './util.js'
import { expect } from 'chai'
import * as td from 'testdouble'
import RedisMock from 'ioredis-mock'

describe('With different app root', function () {
  let app

  beforeEach(async function () {
    let count = 0
    mockConfig({ baseUrls: ['http://ui-server/'] })
    mockRedis()
    mockFetch({
      'http://ui-server': {
        '/manifest.json': generateSimpleViteManifest({
          'example.js': { imports: ['test.txt'] },
          'test.txt': { },
          'main.css': {},
          'index.html': {
            file: 'index.html.js',
            isEntry: true,
            imports: ['example.js'],
            css: ['main.css']
          },
          'image.png': {}
        }),
        '/example.js': () => new Response('this is example', { headers: { 'content-type': 'application/javascript' } }),
        '/test.txt': () => new Response('this is test', { headers: { 'content-type': 'text/plain' } }),
        '/index.html.js': () => new Response('this is index.html.js', { headers: { 'content-type': 'application/javascript' } }),
        '/index.html': () => new Response('<html><head></head><body>it\'s me</body></html>', { headers: { 'content-type': 'text/html' } }),
        '/main.css': () => new Response('.foo { color: #000; }', { headers: { 'content-type': 'text/css' } }),
        '/favicon.ico': 'not really a favicon, though',
        '/test.svg': () => {
          if (count > 0) {
            return new Response(null, { status: 404 })
          }
          count++
          return new Response('<svg></svg>', { headers: { 'content-type': 'image/svg' } })
        }
      }
    })
    process.env.APP_ROOT = '/appsuite/'
    app = await mockApp()
  })

  afterEach(async function () {
    process.env.APP_ROOT = '/'
    await new RedisMock().flushdb()
    td.reset()
  })

  it('serves files defined in manifest.json file', async function () {
    const response = await request(app.server).get('/appsuite/example.js')
    expect(response.statusCode).to.equal(200)
    expect(response.headers['content-type']).to.equal('application/javascript')
    expect(response.text).to.equal('this is example')
    const response2 = await request(app.server).get('/appsuite/test.txt')
    expect(response2.statusCode).to.equal(200)
    expect(response2.headers['content-type']).to.equal('text/plain')
    expect(response2.text).to.equal('this is test')
  })

  it('serves / as index.html', async function () {
    const response = await request(app.server).get('/appsuite/')
    expect(response.statusCode).to.equal(200)
    expect(response.headers['content-type']).to.equal('text/html')
    expect(response.text).to.equal('<html><head></head><body>it\'s me</body></html>')
  })

  it('serves approot without slash as index.html', async function () {
    const response = await request(app.server).get('/appsuite')
    expect(response.statusCode).to.equal(302)
    expect(response.headers.location).to.equal('/appsuite/')
  })

  it('directly fetches files not referenced in manifest.json files from the upstream servers', async function () {
    const response = await request(app.server).get('/appsuite/favicon.ico')
    expect(response.statusCode).to.equal(200)
    expect(response.text).to.equal('not really a favicon, though')
  })

  it('returns 404 if a file misses the app-root', async function () {
    const response = await request(app.server).get('/example.js')
    expect(response.statusCode).to.equal(404)
  })
})