import { describe, it, expect, beforeEach, vi } from 'vitest';
import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { provideRouter, Router } from '@angular/router';

import { of } from 'rxjs';

import { Tenant } from '../../services/tenant.interface';
import { TenantService } from '../../services/tenant.service';
import { CartService } from '../../services/cart/cart.service';
import { ToastService } from '../../services/toast.service';
import { AuthService } from '../../services/auth/auth.service';
import { AuthUser } from '../../services/auth/auth.interfaces';
import { StoreLayoutComponent } from './store-layout.component';

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

describe('StoreLayoutComponent', () => {
  beforeEach(async () => {
    const tenantState = signal(tenant);
    const authUserState = signal<AuthUser | null>(null);
    const isAuthenticatedState = signal(false);

    await TestBed.configureTestingModule({
      imports: [StoreLayoutComponent],
      providers: [
        provideRouter([]),
        {
          provide: TenantService,
          useValue: {
            tenant: tenantState.asReadonly(),
            status: signal<'ready'>('ready').asReadonly(),
            getTenant: () => tenantState(),
            bootstrap: vi.fn().mockResolvedValue(undefined)
          }
        },
        {
          provide: CartService,
          useValue: {
            cart: signal(null).asReadonly(),
            loadCart: () => of({ id: 1, items: [], subtotal: '0' }),
            updateItemQuantity: vi.fn().mockReturnValue(of({ data: { id: 1, items: [], subtotal: '0' } })),
            removeItem: vi.fn().mockReturnValue(of({ data: { id: 1, items: [], subtotal: '0' } }))
          }
        },
        {
          provide: ToastService,
          useValue: {
            show: vi.fn(),
            info: vi.fn(),
            danger: vi.fn(),
            success: vi.fn(),
            dismiss: vi.fn()
          }
        },
        {
          provide: AuthService,
          useValue: {
            user: authUserState,
            isAuthenticated: isAuthenticatedState,
            logout: vi.fn().mockReturnValue(of(void 0))
          }
        }
      ]
    }).compileComponents();
  });

  it('renders the main layout sections', () => {
    const fixture = TestBed.createComponent(StoreLayoutComponent);
    fixture.detectChanges();

    const compiled = fixture.nativeElement as HTMLElement;

    expect(compiled.querySelector('app-store-header .store-layout__header')).not.toBeNull();
    expect(compiled.querySelector('.store-layout__category-trigger')).not.toBeNull();
    expect(compiled.querySelector('router-outlet')).not.toBeNull();
    expect(compiled.querySelector('app-store-footer .store-layout__footer')).not.toBeNull();
  });

  it('renders the tenant branding and action icons', () => {
    const fixture = TestBed.createComponent(StoreLayoutComponent);
    fixture.detectChanges();

    const compiled = fixture.nativeElement as HTMLElement;

    expect(compiled.querySelector('[data-testid="store-header-brand-slot"]')).not.toBeNull();
    expect(compiled.querySelector('[data-testid="store-footer-brand-slot"]')).not.toBeNull();
    expect(
      compiled.querySelector(`app-store-header img.store-layout__brand-logo[src="${tenant.header_logo}"]`)
    ).not.toBeNull();
    expect(
      compiled.querySelector(`app-store-footer img.store-layout__brand-logo[src="${tenant.footer_logo}"]`)
    ).not.toBeNull();
    expect(compiled.querySelector('.fa-cart-shopping')).not.toBeNull();
    expect(compiled.querySelector('.fa-circle-user')).not.toBeNull();
    expect(compiled.querySelector('.fa-instagram')).not.toBeNull();
    expect(compiled.querySelector('.fa-whatsapp')).not.toBeNull();
    expect(compiled.querySelector('.fa-facebook')).not.toBeNull();
    expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull();
  });

  it('redirects to /login when user icon is clicked and user is not logged in', () => {
    const authService = TestBed.inject(AuthService);
    const router = TestBed.inject(Router);
    vi.spyOn(router, 'navigate');

    (authService.isAuthenticated as any).set(false);

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

    const compiled = fixture.nativeElement as HTMLElement;
    const userButton = compiled.querySelector('app-icon-button[variant="user"] button') as HTMLButtonElement;
    expect(userButton).not.toBeNull();
    userButton.click();
    fixture.detectChanges();

    expect(compiled.querySelector('app-user-dropdown')).toBeNull();
    expect(router.navigate).toHaveBeenCalledWith(['/login']);
  });

  it('opens authenticated user dropdown without redirecting on icon click', () => {
    const authService = TestBed.inject(AuthService);
    const router = TestBed.inject(Router);
    vi.spyOn(router, 'navigate');

    (authService.isAuthenticated as any).set(true);
    (authService.user as any).set({
      id: 1,
      nombre_apellido: 'Ada Lovelace',
      email: 'ada@example.com'
    });

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

    const compiled = fixture.nativeElement as HTMLElement;
    const userButton = compiled.querySelector('app-icon-button[variant="user"] button') as HTMLButtonElement;
    expect(userButton).not.toBeNull();
    userButton.click();
    fixture.detectChanges();

    expect(compiled.querySelector('app-user-dropdown')).not.toBeNull();
    expect(compiled.textContent).toContain('Ada Lovelace');
    expect(router.navigate).not.toHaveBeenCalled();
  });

  it('logs out from the authenticated user dropdown', () => {
    const authService = TestBed.inject(AuthService);
    const router = TestBed.inject(Router);
    vi.spyOn(router, 'navigate');

    (authService.isAuthenticated as any).set(true);
    (authService.user as any).set({
      id: 1,
      nombre_apellido: 'Ada Lovelace',
      email: 'ada@example.com'
    });

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

    const compiled = fixture.nativeElement as HTMLElement;
    const userButton = compiled.querySelector('app-icon-button[variant="user"] button') as HTMLButtonElement;
    userButton.click();
    fixture.detectChanges();

    const logoutButton = compiled.querySelector('[data-testid="user-dropdown-logout"]') as HTMLButtonElement;
    expect(logoutButton).not.toBeNull();
    logoutButton.click();
    fixture.detectChanges();

    expect(authService.logout).toHaveBeenCalled();
    expect(router.navigate).toHaveBeenCalledWith(['/login']);
  });

  it('redirects to /checkout when cart buy button is clicked', () => {
    const router = TestBed.inject(Router);
    vi.spyOn(router, 'navigate');

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

    (fixture.componentInstance as any).isCartOpen.set(true);
    fixture.detectChanges();

    const compiled = fixture.nativeElement as HTMLElement;
    const buyButton = Array.from(compiled.querySelectorAll('app-button button'))
      .find((button) => button.textContent?.trim() === 'Comprar') as HTMLButtonElement | undefined;

    expect(buyButton).toBeDefined();
    buyButton!.click();
    fixture.detectChanges();

    expect(router.navigate).toHaveBeenCalledWith(['/checkout']);
    expect((fixture.componentInstance as any).isCartOpen()).toBe(false);
  });
});
