import { nextTick, reactive } from 'vue';
import { createMemoryHistory, createRouter } from 'vue-router';

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

import {
  buildListRouteFullPath,
  buildListRouteStateQuery,
  defineListRouteStateSchema,
  enumListRouteField,
  mergeListRouteStateQuery,
  parseListRouteState,
  positiveIntegerListRouteField,
  stringListRouteField,
  watchListRouteState,
} from './useListRouteState';

interface TestListState {
  categoryId: string;
  keyword: string;
  pageNumber: number;
  pageSize: number;
  status: 'all' | 'enabled';
}

const schema = defineListRouteStateSchema<TestListState>({
  path: '/items',
  fields: {
    categoryId: stringListRouteField(),
    keyword: stringListRouteField({ trim: true }),
    pageNumber: positiveIntegerListRouteField({ defaultValue: 1 }),
    pageSize: positiveIntegerListRouteField({
      allowedValues: [10, 20],
      defaultValue: 10,
    }),
    status: enumListRouteField(['all', 'enabled'], 'all'),
  },
});

describe('list route state', () => {
  it('parses valid state and safely falls back for invalid values', () => {
    expect(
      parseListRouteState(
        {
          categoryId: '7',
          keyword: '  月报  ',
          pageNumber: '-2',
          pageSize: '999',
          status: 'unknown',
        },
        schema,
      ),
    ).toEqual({
      categoryId: '7',
      keyword: '月报',
      pageNumber: 1,
      pageSize: 10,
      status: 'all',
    });
  });

  it('omits defaults and preserves query fields owned by other features', () => {
    const state: TestListState = {
      categoryId: '',
      keyword: '',
      pageNumber: 1,
      pageSize: 10,
      status: 'all',
    };

    expect(buildListRouteStateQuery(state, schema)).toEqual({});
    expect(
      mergeListRouteStateQuery(
        {
          devLogin: 'admin',
          keyword: '旧关键字',
          pageNumber: '4',
        },
        state,
        schema,
      ),
    ).toEqual({ devLogin: 'admin' });
  });

  it('builds the exact current list full path', () => {
    const router = createRouter({
      history: createMemoryHistory(),
      routes: [{ component: {}, path: '/items' }],
    });

    const state: TestListState = {
      categoryId: '7',
      keyword: '月报',
      pageNumber: 3,
      pageSize: 20,
      status: 'enabled',
    };

    expect(
      buildListRouteFullPath(router, { devLogin: 'admin' }, state, schema),
    ).toBe(
      '/items?devLogin=admin&categoryId=7&keyword=%E6%9C%88%E6%8A%A5&pageNumber=3&pageSize=20&status=enabled',
    );
  });

  it('emits parsed state when the current list full path changes', async () => {
    const route = reactive({
      fullPath: '/items',
      path: '/items',
      query: {},
    }) as any;
    const onChange = vi.fn();
    const stop = watchListRouteState(route, schema, onChange);

    route.query = { keyword: '月报', pageNumber: '4', pageSize: '20' };
    route.fullPath = '/items?keyword=月报&pageNumber=4&pageSize=20';
    await nextTick();

    expect(onChange).toHaveBeenCalledOnce();
    expect(onChange).toHaveBeenCalledWith({
      categoryId: '',
      keyword: '月报',
      pageNumber: 4,
      pageSize: 20,
      status: 'all',
    });
    stop();
  });
});
