import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';

import { beforeEach, describe, expect, it, vi } from 'vitest';

import AuthenticationLogin from '../login.vue';

const { formApi, routerPush } = vi.hoisted(() => ({
  formApi: {
    getValues: vi.fn(),
    setFieldValue: vi.fn(),
    validate: vi.fn(),
  },
  routerPush: vi.fn(),
}));

vi.mock('vue-router', () => ({
  useRouter: () => ({
    push: routerPush,
  }),
}));

vi.mock('@easyflow/locales', () => ({
  $t: (key: string) => key,
}));

vi.mock('@easyflow-core/form-ui', async () => {
  const vue = await import('vue');

  return {
    useEasyFlowForm: () => [
      vue.defineComponent({
        name: 'MockEasyFlowForm',
        setup() {
          return () => vue.h('div', { class: 'mock-form' });
        },
      }),
      formApi,
    ],
  };
});

vi.mock('@easyflow-core/shadcn-ui', async (importOriginal) => {
  const vue = await import('vue');
  const actual =
    await importOriginal<typeof import('@easyflow-core/shadcn-ui')>();

  return {
    ...actual,
    EasyFlowButton: vue.defineComponent({
      name: 'EasyFlowButton',
      props: {
        loading: {
          default: false,
          type: Boolean,
        },
      },
      emits: ['click'],
      setup(props, { attrs, emit, slots }) {
        return () =>
          vue.h(
            'button',
            {
              ...attrs,
              'data-loading': String(props.loading),
              type: 'button',
              onClick: () => emit('click'),
            },
            slots.default?.(),
          );
      },
    }),
    EasyFlowCheckbox: vue.defineComponent({
      name: 'EasyFlowCheckbox',
      props: {
        modelValue: {
          default: false,
          type: Boolean,
        },
        name: {
          default: '',
          type: String,
        },
      },
      emits: ['update:modelValue'],
      setup(props, { emit, slots }) {
        return () =>
          vue.h('label', [
            vue.h('input', {
              checked: props.modelValue,
              name: props.name,
              type: 'checkbox',
              onChange: (event: Event) => {
                emit(
                  'update:modelValue',
                  (event.target as HTMLInputElement).checked,
                );
              },
            }),
            slots.default?.(),
          ]);
      },
    }),
  };
});

describe('authenticationLogin', () => {
  const rememberKey = `REMEMBER_ME_ACCOUNT_${location.hostname}`;

  beforeEach(() => {
    localStorage.clear();
    vi.clearAllMocks();
    formApi.validate.mockResolvedValue({ valid: true });
    formApi.getValues.mockResolvedValue({ account: 'admin' });
  });

  it('restores remembered account into the account field', async () => {
    localStorage.setItem(rememberKey, 'remembered-user');

    mount(AuthenticationLogin, {
      props: {
        formSchema: [],
      },
    });

    await nextTick();

    expect(formApi.setFieldValue).toHaveBeenCalledWith(
      'account',
      'remembered-user',
    );
  });

  it('persists remembered account using the account field and renders overlay slot', async () => {
    localStorage.setItem(rememberKey, 'remembered-user');

    const wrapper = mount(AuthenticationLogin, {
      props: {
        formSchema: [],
        showRememberMe: true,
      },
      slots: {
        overlay: '<div id="captcha-box"></div>',
      },
    });

    await nextTick();
    await wrapper.get('button').trigger('click');

    expect(localStorage.getItem(rememberKey)).toBe('admin');
    expect(wrapper.emitted('submit')?.[0]).toEqual([{ account: 'admin' }]);
    expect(wrapper.find('#captcha-box').exists()).toBe(true);
  });
});
