import type { ReactElement } from 'react';
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@cameleer/design-system';
import { PrimaryActionButton, computeMode } from './PrimaryActionButton';

function wrap(ui: ReactElement) {
  return render(<ThemeProvider>{ui}</ThemeProvider>);
}

describe('PrimaryActionButton', () => {
  it('renders Save in save mode', () => {
    wrap(<PrimaryActionButton mode="save" enabled onClick={() => {}} />);
    expect(screen.getByRole('button', { name: /save/i })).toBeInTheDocument();
  });

  it('renders Redeploy in redeploy mode', () => {
    wrap(<PrimaryActionButton mode="redeploy" enabled onClick={() => {}} />);
    expect(screen.getByRole('button', { name: /redeploy/i })).toBeInTheDocument();
  });

  it('renders Deploying… disabled in deploying mode', () => {
    wrap(<PrimaryActionButton mode="deploying" enabled={false} onClick={() => {}} />);
    const btn = screen.getByRole('button', { name: /deploying/i });
    expect(btn).toBeDisabled();
  });

  it('renders Uploading… NN% with progress overlay in uploading mode', () => {
    wrap(<PrimaryActionButton mode="uploading" enabled={false} progress={42} onClick={() => {}} />);
    const btn = screen.getByRole('button', { name: /uploading/i });
    expect(btn).toBeDisabled();
    expect(btn).toHaveTextContent('42%');
    const fill = btn.querySelector('[data-upload-fill]') as HTMLElement | null;
    expect(fill).not.toBeNull();
    expect(fill!.style.width).toBe('42%');
  });
});

describe('computeMode', () => {
  it('returns uploading when uploading flag set, even if deploymentInProgress is false', () => {
    expect(computeMode({ deploymentInProgress: false, uploading: true, hasLocalEdits: true, serverDirtyAgainstDeploy: false })).toBe('uploading');
  });

  it('returns deploying when deploymentInProgress even if uploading flag set', () => {
    expect(computeMode({ deploymentInProgress: true, uploading: true, hasLocalEdits: false, serverDirtyAgainstDeploy: false })).toBe('deploying');
  });

  it('returns save when local edits without upload or deploy', () => {
    expect(computeMode({ deploymentInProgress: false, uploading: false, hasLocalEdits: true, serverDirtyAgainstDeploy: false })).toBe('save');
  });

  it('returns redeploy when server dirty and no local edits', () => {
    expect(computeMode({ deploymentInProgress: false, uploading: false, hasLocalEdits: false, serverDirtyAgainstDeploy: true })).toBe('redeploy');
  });
});
