import {useEffect, useState} from 'react';
import {AxiosRequestConfig, ValidationOptions} from '@szyx-mobile/use-axios';
import {RequestError} from '@szyx-mobile/use-request';
import z from 'zod';
import {useApi} from './useApi';

type List<T> = {
  records: T[];
};

type Root<T> = T[];

interface PageOptions extends ValidationOptions {
  pageSize?: number; // 默认为 10
  path?: 'list' | 'root'; // 默认为 'list'
  pagination?: 'cursor' | 'offset'; // 默认为 'cursor' offset 代表传入 current 和 size 进行分页，cursor 代表传入 startNum 和 endNum 进行分页
}

const usePageApi = <
  S extends z.ZodTypeAny,
  T extends z.infer<S> = unknown,
  P extends List<T> | Root<T> = List<T>,
  D = Record<string, unknown>,
>(
  url: string,
  method: 'GET' | 'POSTJSON' | 'POSTFORM',
  params?: D,
  validationSchema?: S,
  options?: PageOptions,
  config?: AxiosRequestConfig<D>,
): {
  response?: T[];
  error?: RequestError<unknown, D>;
  loading: boolean;
  fetch: React.Dispatch<React.SetStateAction<'reload' | 'loadmore'>>;
  cancel: () => void;
} => {
  const [data, setData] = useState<T[] | undefined>(undefined);
  const [status, setStatus] = useState<'loaded' | 'reload' | 'loadmore'>(
    'loaded',
  );

  const listSchema: z.ZodSchema<List<T>> = z.object({
    records: z.array(validationSchema ?? z.any()),
  });

  const rootSchema: z.ZodSchema<Root<T>> = z.array(validationSchema ?? z.any());

  const {error, loading, fetchAsync, cancel} = useApi<
    typeof listSchema | typeof rootSchema,
    P
  >(
    url,
    method,
    options?.pagination === 'offset'
      ? {
          ...params,
          current:
            status === 'loadmore'
              ? Math.ceil((data ?? []).length / (options?.pageSize ?? 10)) + 1
              : 1,
          size: options?.pageSize ?? 10,
        }
      : {
          ...params,
          startNum: status === 'loadmore' ? (data ?? []).length : 0,
          endNum:
            status === 'loadmore'
              ? (data ?? []).length + (options?.pageSize ?? 10) - 1
              : (options?.pageSize ?? 10) - 1,
        },
    options?.path === 'root' ? rootSchema : listSchema,
    options,
    config,
  );

  useEffect(() => {
    if (
      status === 'loaded' ||
      (status === 'loadmore' &&
        ((data ?? []).length === 0 ||
          (data ?? []).length % (options?.pageSize ?? 10) !== 0))
    ) {
      return;
    }
    fetchAsync()
      .then(r => {
        if (status === 'reload') {
          switch (options?.path) {
            case 'root':
              const rr = r as Root<T>;
              setData(rr);
              setStatus('loaded');
              break;
            default:
              const lr = r as List<T>;
              setData(lr.records);
              setStatus('loaded');
              break;
          }
        } else {
          switch (options?.path) {
            case 'root':
              const rr = r as Root<T>;
              setData(d => {
                return [...(d ?? []), ...rr];
              });
              setStatus('loaded');
              break;
            default:
              const lr = r as List<T>;
              setData(d => {
                return [...(d ?? []), ...lr.records];
              });
              setStatus('loaded');
              break;
          }
        }
      })
      .catch(() => {
        setStatus('loaded');
      });
  }, [data, fetchAsync, options?.pageSize, options?.path, status]);

  const typedFetch = setStatus as React.Dispatch<
    React.SetStateAction<'reload' | 'loadmore'>
  >;

  return {response: data, error, loading, fetch: typedFetch, cancel};
};

export type {AxiosRequestConfig};
export {usePageApi};
