import { TestBed } from '@angular/core/testing';
import { provideRouter, Router, UrlTree } from '@angular/router';

import { Tenant } from '../services/tenant.interface';
import { TenantService } from '../services/tenant.service';
import { hasMenuGuard } from './menu.guard';

const tenant: Tenant = {
  id: 1,
  codigo: 'test',
  nombre: 'Test Tenant',
  dominio: 'localhost',
  primary_color: '#6376F3',
  secondary_color: '#A0A0A0',
  danger_color: '#FF8888',
  success_color: '#198754',
  header_bg_color: '#313131',
  footer_bg_color: '#313131',
  header_logo: 'https://example.com/header.png',
  footer_logo: 'https://example.com/footer.png',
  categories: [],
  menues: [
    {
      id: 1,
      code: 'index',
      label: 'Inicio',
      parent_menu_code: null,
      content_type: 'dynamic',
      route: '/',
      submenues: [],
    },
  ],
};

function runGuard(menuCode: string, url: string, currentTenant: Tenant | null) {
  TestBed.configureTestingModule({
    providers: [
      provideRouter([]),
      {
        provide: TenantService,
        useValue: { tenant: () => currentTenant },
      },
    ],
  });

  return TestBed.runInInjectionContext(() =>
    hasMenuGuard(menuCode)(null as never, { url } as never),
  );
}

describe('hasMenuGuard', () => {
  beforeEach(() => {
    TestBed.resetTestingModule();
  });

  it('allows a route exposed by the tenant menu', () => {
    expect(runGuard('index', '/', tenant)).toBe(true);
  });

  it('cancels navigation when the tenant is missing', () => {
    expect(runGuard('index', '/', null)).toBe(false);
  });

  it('redirects a missing menu route to the store root', () => {
    const result = runGuard('checkout', '/checkout/25', tenant);

    expect(result instanceof UrlTree).toBe(true);
    expect(TestBed.inject(Router).serializeUrl(result as UrlTree)).toBe('/');
  });

  it('allows the store root when its menu is missing to avoid a self-redirect', () => {
    const tenantWithoutMenus = { ...tenant, menues: [] };

    expect(runGuard('index', '/', tenantWithoutMenus)).toBe(true);
  });
});
