import {
  HttpClient,
  HttpHeaders,
  HttpResponse,
} from '@angular/common/http';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { IMockRequest, IMockConfig, ISafeAny } from './mock.type';
import { BixiMockModule } from './mock.module';

const DATA = {
  TEST: {
    '/users': () => {
      return { users: [1, 2] }
    },
    '/function': () => 'hello function',
    '/users/:id': (req: IMockRequest) => req.params,
    '/HttpResponse': () => new HttpResponse({ body: 'Body', headers: new HttpHeaders({ token: '1' }) }),
    '/test/:params': (res: IMockRequest) => { return res.params },
    '/test': (res: IMockRequest) => {
      return res.query
    },
    '/500': () => {
      throw new Error('500');
    },
  },
};

describe('# mock-interceptor', () => {
  let http: HttpClient;

  function genModule(options: IMockConfig, imports: any[] = [], spyConsole = true) {
    TestBed.configureTestingModule({
      declarations: [RootComponent],
      imports: [
        HttpClientTestingModule,
        BixiMockModule.forRoot(options),
        RouterTestingModule.withRoutes([
          {
            path: 'lazy',
            loadChildren: 'expected',
          },
        ]),
      ].concat(imports)
    });
    http = TestBed.inject<HttpClient>(HttpClient);
    if (spyConsole) {
      spyOn(console, 'log');
      spyOn(console, 'warn');
    }
  }

  describe('base usaging', () => {
    beforeEach(() => genModule({ data: DATA }));
    it('should be work', (done: () => void) => {
      http.get('/users').subscribe((res: any) => {
        expect(res).not.toBeNull();
        expect(res.users.length).toBe(2);
        done();
      });
    });
    it('should function', (done: () => void) => {
      http.get('/function').subscribe((res: any) => {
        expect(res).toBe('hello function');
        done();
      });
    });
    it('should get params', (done: () => void) => {
      const key = '/test/2';
      http.get(key).subscribe((res: any) => {
        expect(res.params).toBe('2');
        done();
      });
    });
    it('should return query', (done: () => void) => {
      const key = '/test?hello=world';
      http.get(key).subscribe((res: any) => {
        expect(res).not.toBeNull();
        expect(res.hello).toBe('world');
        done();
      });
    });
  });

  describe('[disabled log]', () => {
    it('config disable', (done: () => void) => {
      genModule({ data: DATA, log: false });
      http.get('/users').subscribe(() => {
        expect(console.log).not.toHaveBeenCalled();
        done();
      });
    });
  });

  describe('# before return', () => {
    it('format response', (done: () => void) => {
      genModule({
        data: DATA, interceptors: {
          response: (res: any) => {
            return {
              data: res,
              status: 800000
            }
          }
        }
      });
      http.get('/users').subscribe((res: ISafeAny) => {
        expect(res.status).not.toBeUndefined();
        expect(res.status).toBe(800000);
        done();
      });
    });
  });
});

@Component({
  selector: 'root-cmp',
  template: ` <router-outlet></router-outlet>`,
})
class RootComponent { }
