import '@angular/compiler';
import { signal } from '@angular/core';
import { TestBed, getTestBed } from '@angular/core/testing';
import {
  BrowserTestingModule,
  platformBrowserTesting
} from '@angular/platform-browser/testing';
import { provideRouter } from '@angular/router';
import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest';

import { App } from './app';
import { Tenant } from './core/services/tenant.interface';
import { TenantService } from './core/services/tenant.service';

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'
};

function createTenantServiceStub(status: 'ready' | 'not-found', currentTenant: Tenant | null) {
  const tenantState = signal(currentTenant);
  const statusState = signal(status);

  return {
    tenant: tenantState.asReadonly(),
    status: statusState.asReadonly(),
    getTenant: () => tenantState(),
    bootstrap: vi.fn().mockResolvedValue(undefined)
  };
}

describe('App', () => {
  beforeAll(() => {
    try {
      getTestBed().initTestEnvironment(
        BrowserTestingModule,
        platformBrowserTesting()
      );
    } catch {
      // Test environment may already be initialized by another setup entrypoint.
    }
  });

  afterEach(() => {
    TestBed.resetTestingModule();
  });

  it('creates the app when the tenant is ready', async () => {
    await TestBed.configureTestingModule({
      imports: [App],
      providers: [
        provideRouter([]),
        {
          provide: TenantService,
          useValue: createTenantServiceStub('ready', tenant)
        }
      ]
    }).compileComponents();

    const fixture = TestBed.createComponent(App);
    fixture.detectChanges();

    expect(fixture.componentInstance).toBeTruthy();
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-primary')).toBe(
      tenant.primary_color
    );
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-secondary')).toBe(
      tenant.secondary_color
    );
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-danger')).toBe(
      tenant.danger_color
    );
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-primary-rgb')).toBe(
      '99, 118, 243'
    );
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-secondary-rgb')).toBe(
      '160, 160, 160'
    );
    expect(fixture.nativeElement.style.getPropertyValue('--tenant-danger-rgb')).toBe(
      '255, 136, 136'
    );
  });

  it('renders the tenant not found screen when the tenant is missing', async () => {
    await TestBed.configureTestingModule({
      imports: [App],
      providers: [
        provideRouter([]),
        {
          provide: TenantService,
          useValue: createTenantServiceStub('not-found', null)
        }
      ]
    }).compileComponents();

    const fixture = TestBed.createComponent(App);
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).toContain('No encontramos una tienda para este dominio');
  });
});
