import merge from 'lodash/merge';
import create from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import { PlaylistListArgs, PlaylistListSort, SortOrder } from '/@/renderer/api/types';
import { DataTableProps } from '/@/renderer/store/settings.store';
import { SongListFilter } from '/@/renderer/store/song.store';
import { ListDisplayType, TableColumn, TablePagination } from '/@/renderer/types';

type TableProps = {
  pagination: TablePagination;
  scrollOffset: number;
} & DataTableProps;

type ListProps<T> = {
  display: ListDisplayType;
  filter: T;
  table: TableProps;
};

type DetailPaginationProps = TablePagination & {
  scrollOffset: number;
};

type DetailTableProps = DataTableProps & {
  id: {
    [key: string]: DetailPaginationProps & { filter: SongListFilter };
  };
};

type DetailProps = {
  display: ListDisplayType;
  table: DetailTableProps;
};

export type PlaylistListFilter = Omit<PlaylistListArgs['query'], 'startIndex' | 'limit'>;

interface PlaylistState {
  detail: DetailProps;
  list: ListProps<PlaylistListFilter>;
}

export interface PlaylistSlice extends PlaylistState {
  actions: {
    setDetailFilters: (id: string, data: Partial<SongListFilter>) => SongListFilter;
    setDetailTable: (data: Partial<DetailTableProps>) => void;
    setDetailTablePagination: (id: string, data: Partial<DetailPaginationProps>) => void;
    setFilters: (data: Partial<PlaylistListFilter>) => PlaylistListFilter;
    setStore: (data: Partial<PlaylistSlice>) => void;
    setTable: (data: Partial<TableProps>) => void;
    setTablePagination: (data: Partial<TableProps['pagination']>) => void;
  };
}

export const usePlaylistStore = create<PlaylistSlice>()(
  persist(
    devtools(
      immer((set, get) => ({
        actions: {
          setDetailFilters: (id, data) => {
            set((state) => {
              state.detail.table.id[id] = {
                ...state.detail.table.id[id],
                filter: {
                  ...state.detail.table.id[id].filter,
                  ...data,
                },
              };
            });

            return get().detail.table.id[id].filter;
          },
          setDetailTable: (data) => {
            set((state) => {
              state.detail.table = { ...state.detail.table, ...data };
            });
          },
          setDetailTablePagination: (id, data) => {
            set((state) => {
              state.detail.table.id[id] = {
                ...state.detail.table.id[id],
                ...data,
              };
            });
          },
          setFilters: (data) => {
            set((state) => {
              state.list.filter = { ...state.list.filter, ...data };
            });

            return get().list.filter;
          },
          setStore: (data) => {
            set({ ...get(), ...data });
          },
          setTable: (data) => {
            set((state) => {
              state.list.table = { ...state.list.table, ...data };
            });
          },
          setTablePagination: (data) => {
            set((state) => {
              state.list.table.pagination = { ...state.list.table.pagination, ...data };
            });
          },
        },
        detail: {
          display: ListDisplayType.TABLE,
          table: {
            autoFit: true,
            columns: [
              {
                column: TableColumn.ROW_INDEX,
                width: 50,
              },
              {
                column: TableColumn.TITLE_COMBINED,
                width: 500,
              },
              {
                column: TableColumn.DURATION,
                width: 100,
              },
              {
                column: TableColumn.ALBUM,
                width: 500,
              },
            ],
            id: {},
            rowHeight: 60,
          },
        },
        list: {
          display: ListDisplayType.TABLE,
          filter: {
            musicFolderId: undefined,
            sortBy: PlaylistListSort.NAME,
            sortOrder: SortOrder.ASC,
          },
          table: {
            autoFit: true,
            columns: [
              {
                column: TableColumn.ROW_INDEX,
                width: 50,
              },
              {
                column: TableColumn.TITLE,
                width: 500,
              },
              {
                column: TableColumn.SONG_COUNT,
                width: 100,
              },
            ],
            pagination: {
              currentPage: 1,
              itemsPerPage: 100,
              totalItems: 1,
              totalPages: 1,
            },
            rowHeight: 40,
            scrollOffset: 0,
          },
        },
      })),
      { name: 'store_playlist' },
    ),
    {
      merge: (persistedState, currentState) => {
        return merge(currentState, persistedState);
      },
      name: 'store_playlist',
      version: 1,
    },
  ),
);

export const usePlaylistStoreActions = () => usePlaylistStore((state) => state.actions);

export const useSetPlaylistStore = () => usePlaylistStore((state) => state.actions.setStore);

export const useSetPlaylistFilters = () => usePlaylistStore((state) => state.actions.setFilters);

export const usePlaylistFilters = () => {
  return usePlaylistStore((state) => [state.list.filter, state.actions.setFilters]);
};

export const usePlaylistListStore = () => usePlaylistStore((state) => state.list);

export const usePlaylistTablePagination = () =>
  usePlaylistStore((state) => state.list.table.pagination);

export const useSetPlaylistTablePagination = () =>
  usePlaylistStore((state) => state.actions.setTablePagination);

export const useSetPlaylistTable = () => usePlaylistStore((state) => state.actions.setTable);

export const usePlaylistDetailStore = () => usePlaylistStore((state) => state.detail);

export const usePlaylistDetailTablePagination = (id: string) =>
  usePlaylistStore((state) => state.detail.table.id[id]);

export const useSetPlaylistDetailTablePagination = () =>
  usePlaylistStore((state) => state.actions.setDetailTablePagination);

export const useSetPlaylistDetailTable = () =>
  usePlaylistStore((state) => state.actions.setDetailTable);

export const useSetPlaylistDetailFilters = () =>
  usePlaylistStore((state) => state.actions.setDetailFilters);
