import * as React from 'react';
import { render } from '@testing-library/react';
import { describe, it, expect, vi } from 'vitest';
import { generateShortcode, default as SaveComponent } from './save';
import type { BlockSaveProps } from '@wordpress/blocks';
import type { TitleSelection, TitleIdType, WidgetParams } from '../types';

vi.mock('@wordpress/block-editor', () => ({
  useBlockProps: {
    save: vi.fn((props) => props),
  },
}));

vi.mock('@wordpress/shortcode', () => ({
  string: vi.fn(({ tag, attrs }) => `[${tag} ${Object.entries(attrs).map(([key, value]) => `${key}="${value}"`).join(' ')}]`),
}));

describe('generateShortcode', () => {
  it('generates a shortcode with mapped attributes', () => {
    const attributes: WidgetParams = {
      id: '123',
      idType: 'justwatch' as TitleIdType,
      objectType: 'movie',
      seasonNumber: 2,
      episodeNumber: 5,
      maxOffers: 10,
      offerLabel: 'Watch Now',
      apiKey: 'test-api-key',
      theme: 'dark',
      scale: 1.5,
      noOffersMessage: 'No offers available',
    };

    const shortcode = generateShortcode(attributes);

    expect(shortcode).toBe(
      '[justwatch id="123" id-type="justwatch" object-type="movie" season-number="2" episode-number="5" max-offers="10" offer-label="Watch Now" api-key="test-api-key" theme="dark" scale="1.5" no-offers-message="No offers available"]'
    );
  });

  it('generates a shortcode with only required attributes', () => {
    const attributes: TitleSelection = {
      id: '456',
      idType: 'tmdb',
      objectType: 'show',
    };

    const shortcode = generateShortcode(attributes);

    expect(shortcode).toBe(
      '[justwatch id="456" id-type="tmdb" object-type="show"]'
    );
  });

  it('throws if required attributes are missing', () => {
    const attributes = {
      id: '',
      objectType: '',
    };

    try {
      generateShortcode(attributes as any);
    }
    catch (error) {
      expect(error).toBeInstanceOf(Error);
    }
  });

  it('maps custom keys to shortcode attributes', () => {
    const attributes: TitleSelection = {
      id: '789',
      objectType: 'movie',
      seasonNumber: 3,
      episodeNumber: 7,
    };

    const shortcode = generateShortcode(attributes);

    expect(shortcode).toBe(
      '[justwatch id="789" object-type="movie" season-number="3" episode-number="7"]'
    );
  });

  it('maps keys to custom shortcode attributes using keyMap', () => {
    const attributes: WidgetParams = {
      id: '123',
      idType: 'justwatch' as TitleIdType,
      objectType: 'movie',
      seasonNumber: 2,
      episodeNumber: 5,
    };

    const shortcode = generateShortcode(attributes, {
      keyMap: {
        idType: 'provider',
        seasonNumber: 'season',
        episodeNumber: 'episode',
      },
    });

    expect(shortcode).toBe(
      '[justwatch id="123" provider="justwatch" object-type="movie" season="2" episode="5"]'
    );
  });

  it('excludes keys mapped to null in keyMap', () => {
    const attributes: WidgetParams = {
      id: '123',
      idType: 'justwatch' as TitleIdType,
      objectType: 'movie',
      seasonNumber: 2,
      episodeNumber: 5,
    };

    const shortcode = generateShortcode(attributes, {
      keyMap: {
        idType: null, // Exclude idType
        seasonNumber: 'season',
        episodeNumber: 'episode',
      },
    });

    expect(shortcode).toBe(
      '[justwatch id="123" object-type="movie" season="2" episode="5"]'
    );
  });

  it('handles keyMap with mixed mappings and exclusions', () => {
    const attributes: WidgetParams = {
      id: '123',
      idType: 'justwatch' as TitleIdType,
      objectType: 'movie',
      seasonNumber: 2,
      episodeNumber: 5,
      maxOffers: 10,
    };

    const shortcode = generateShortcode(attributes, {
      keyMap: {
        idType: null, // Exclude idType
        seasonNumber: 'season',
        episodeNumber: 'episode',
        maxOffers: 'offers', // Rename maxOffers to offers
      },
    });

    expect(shortcode).toBe(
      '[justwatch id="123" object-type="movie" season="2" episode="5" offers="10"]'
    );
  });

  it('ignores keyMap for keys not present in attributes', () => {
    const attributes: WidgetParams = {
      id: '123',
      objectType: 'movie',
    };

    const shortcode = generateShortcode(attributes, {
      keyMap: {
        idType: 'provider', // idType is not in attributes
        seasonNumber: 'season', // seasonNumber is not in attributes
      },
    });

    expect(shortcode).toBe(
      '[justwatch id="123" object-type="movie"]'
    );
  });

  it('handles empty keyMap', () => {
    const attributes: WidgetParams = {
      id: '123',
      idType: 'justwatch' as TitleIdType,
      objectType: 'movie',
    };

    const shortcode = generateShortcode(attributes, {
      keyMap: {}, // Empty keyMap
    });

    expect(shortcode).toBe(
      '[justwatch id="123" id-type="justwatch" object-type="movie"]'
    );
  });
});

describe.skip('SaveComponent', () => {
  it('renders the shortcode when required attributes are provided', () => {
    const attributes: TitleSelection = {
      id: '123',
      objectType: 'movie',
    };

    const { container } = render(<SaveComponent attributes={attributes} className="justwatch-shortcode" />);

    expect(container.textContent).toBe(
      '[justwatch id="123" type="movie"]'
    );
  });

  it('renders an empty div when required attributes are missing', () => {
    const props: BlockSaveProps<TitleSelection> = {
      attributes: {
        id: '',
        objectType: '',
      },
    } as any;

    const { container } = render(<SaveComponent {...props} />);

    expect(container.textContent).toBe('');
  });

  it('applies the correct block props', () => {
    const attributes: TitleSelection = {
      id: '123',
      objectType: 'movie',
    };

    const { container } = render(<SaveComponent attributes={attributes} className="justwatch-shortcode" />);

    expect(container.firstChild).toHaveClass('justwatch-shortcode');
  });
});