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

import { ModalService } from '../../../../core/services/modal.service';
import { Tenant } from '../../../../core/services/tenant.interface';
import { TenantService } from '../../../../core/services/tenant.service';
import { ToastService } from '../../../../core/services/toast.service';
import { ReutilizablesTestPageComponent } from './reutilizables-test-page.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'
};

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

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

function createToastServiceStub() {
  return {
    success: vi.fn(),
    danger: vi.fn(),
    info: vi.fn()
  };
}

function createModalServiceStub() {
  return {
    open: vi.fn(),
    openConfirm: vi.fn().mockReturnValue(of(true)),
    openConfirmDelete: vi.fn().mockReturnValue(of(false))
  };
}

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

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

  it('renders the tenant configuration section with logo sources and swatch colors', async () => {
    const modalServiceStub = createModalServiceStub();
    await TestBed.configureTestingModule({
      imports: [ReutilizablesTestPageComponent],
      providers: [
        {
          provide: TenantService,
          useValue: createTenantServiceStub(tenant)
        },
        {
          provide: ToastService,
          useValue: createToastServiceStub()
        },
        {
          provide: ModalService,
          useValue: modalServiceStub
        }
      ]
    }).compileComponents();

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

    const element = fixture.nativeElement as HTMLElement;
    const sectionTitle = element.querySelector('.configuracion-tennant h2');

    expect(sectionTitle?.textContent).toContain('Configuracion Tenant');

    const headerImg = element.querySelector(
      '.tenant-logo-card img[alt="Header Logo"]'
    ) as HTMLImageElement;
    expect(headerImg?.src).toBe(tenant.header_logo);

    const footerImg = element.querySelector(
      '.tenant-logo-card img[alt="Footer Logo"]'
    ) as HTMLImageElement;
    expect(footerImg?.src).toBe(tenant.footer_logo);

    expect(element.textContent).toContain(tenant.primary_color);
    expect(element.textContent).toContain(tenant.secondary_color);
    expect(element.textContent).toContain(tenant.danger_color);
    expect(element.textContent).toContain(tenant.success_color);
  });

  it('renders the paginator demo with the initial page status', async () => {
    const modalServiceStub = createModalServiceStub();
    await TestBed.configureTestingModule({
      imports: [ReutilizablesTestPageComponent],
      providers: [
        {
          provide: TenantService,
          useValue: createTenantServiceStub(tenant)
        },
        {
          provide: ToastService,
          useValue: createToastServiceStub()
        },
        {
          provide: ModalService,
          useValue: modalServiceStub
        }
      ]
    }).compileComponents();

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

    const element = fixture.nativeElement as HTMLElement;

    expect(element.querySelector('app-paginator')).not.toBeNull();
    expect(
      element.querySelector('[data-testid="paginator-status"]')?.textContent?.trim()
    ).toBe('1/8');
  });

  it('renders the modal showcase and opens the confirm demos from the buttons', async () => {
    const modalServiceStub = createModalServiceStub();
    await TestBed.configureTestingModule({
      imports: [ReutilizablesTestPageComponent],
      providers: [
        {
          provide: TenantService,
          useValue: createTenantServiceStub(tenant)
        },
        {
          provide: ToastService,
          useValue: createToastServiceStub()
        },
        {
          provide: ModalService,
          useValue: modalServiceStub
        }
      ]
    }).compileComponents();

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

    const element = fixture.nativeElement as HTMLElement;
    const buttons = Array.from(
      element.querySelectorAll('.button-group app-button button')
    );
    const confirmButton = buttons.find((button) =>
      button.textContent?.includes('Abrir confirm modal')
    ) as HTMLButtonElement;
    const deleteButton = buttons.find((button) =>
      button.textContent?.includes('Abrir confirm delete')
    ) as HTMLButtonElement;

    expect(
      element.querySelector('[data-testid="modal-last-result"]')?.textContent
    ).toContain('Todavia no se abrio ningun modal.');

    confirmButton.click();
    fixture.detectChanges();
    deleteButton.click();
    fixture.detectChanges();

    expect(modalServiceStub.openConfirm).toHaveBeenCalledWith({
      title: 'Confirmar accion',
      content: 'Caso base para verificar apertura, cierre y devolucion de resultado.',
      confirmLabel: 'Confirmar'
    });
    expect(modalServiceStub.openConfirmDelete).toHaveBeenCalledWith({
      title: 'Eliminar producto',
      content:
        'Esta accion eliminara el producto del catalogo. Podras volver a crearlo manualmente.',
      confirmLabel: 'Eliminar'
    });
    expect(
      element.querySelector('[data-testid="modal-last-result"]')?.textContent
    ).toContain('Resultado: false');
  });

  it('updates the visible result when the confirm modal resolves to true', async () => {
    const modalServiceStub = createModalServiceStub();
    await TestBed.configureTestingModule({
      imports: [ReutilizablesTestPageComponent],
      providers: [
        {
          provide: TenantService,
          useValue: createTenantServiceStub(tenant)
        },
        {
          provide: ToastService,
          useValue: createToastServiceStub()
        },
        {
          provide: ModalService,
          useValue: modalServiceStub
        }
      ]
    }).compileComponents();

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

    const element = fixture.nativeElement as HTMLElement;
    const confirmButton = Array.from(
      element.querySelectorAll('.button-group app-button button')
    ).find((button) =>
      button.textContent?.includes('Abrir confirm modal')
    ) as HTMLButtonElement;

    confirmButton.click();
    fixture.detectChanges();

    expect(
      element.querySelector('[data-testid="modal-last-result"]')?.textContent
    ).toContain('Resultado: true');
  });
});
