import { dateFormat, gendUrl, throttle } from "@/util";
import * as URL from "./URL";
import {
  basePath,
  errorHook,
  gHeaders,
  gParams,
  gPaths,
  lifeHook,
  Param,
} from "./state";
import { ElMessage } from "element-plus";
import { Relics, Scene, ScenePoint, ResPage, UserInfo, Device } from "./type";

const error = throttle((msg: string) => ElMessage.error(msg), 2000);

type Other = { params?: Param; paths?: Param };
export const sendFetch = <T>(
  url: string,
  init: RequestInit,
  other?: Other
): Promise<T> => {
  const headers = init.headers as Record<string, string>;
  let sendUrl = url;

  if (other) {
    if (other.paths) {
      sendUrl = gendUrl(url, { ...gPaths, ...other.paths });
    }

    if (other.params) {
      sendUrl =
        sendUrl + "?" + new URLSearchParams({ ...gParams, ...other.params });
    }
  }
  lifeHook.forEach(({ start }) => start());

  return fetch(basePath + sendUrl, {
    ...init,
    headers: headers
      ? {
          ...headers,
          ...gHeaders,
        }
      : gHeaders,
  })
    .then((res) => {
      lifeHook.forEach(({ end }) => end());
      if (res.status === 200) {
        return res.json();
      } else {
        ElMessage.error("请求错误");
        throw "请求错误";
      }
    })
    .then((data) => {
      if (data.code !== 0) {
        error(data.message);
        errorHook.map((err) => {
          err(data.code, data.msg);
        });
        throw data.message;
      } else {
        return data.data;
      }
    });
};

export type LoginProps = {
  password: string;
  phoneNum: string;
};
export const loginFetch = (props: LoginProps) =>
  sendFetch<{ user: UserInfo; token: string }>(URL.login, {
    method: "post",
    body: JSON.stringify(props),
  });

export const userInfoFetch = () =>
  sendFetch<UserInfo>(URL.getUserInfo, { method: "post" });

export type PageProps<T> = {
  pageNum: number;
  pageSize: number;
} & T;

export type RelicsPageProps = PageProps<{
  name?: string;
  category?: number;
  level?: number;
}>;
export const relicsPageFetch = (body: RelicsPageProps) =>
  sendFetch<ResPage<Relics>>(URL.getRelicsPage, {
    method: "post",
    body: JSON.stringify(body),
  });

export const relicsInfoFetch = (relicsId: number) =>
  sendFetch<Relics>(
    URL.getRelicsInfo,
    {
      method: "post",
      body: JSON.stringify({}),
    },
    { paths: { relicsId } }
  );

export const relicsSelfCheckFetch = (relicsId: number) =>
  sendFetch<Relics>(
    URL.relicsSelfCheck,
    {
      method: "post",
      body: JSON.stringify({}),
    },
    { paths: { relicsId } }
  );

export const addRelicsFetch = (relics: Relics) => {
  return sendFetch(URL.addRelics, {
    method: "post",
    body: JSON.stringify({ ...relics, relicsId: null }),
  });
};

export const delRelicsFetch = (relicsId: number) =>
  sendFetch(URL.delRelics, {
    method: "post",
    body: JSON.stringify({ relicsId }),
  });

export const updateRelicsFetch = (relics: Relics) =>
  sendFetch(URL.updateRelicsName, {
    method: "post",
    body: JSON.stringify(relics),
  });

export const relicsScenesFetch = async (relicsId: number) => {
  const scenes = await sendFetch<Scene[]>(
    URL.getRelicsScenes,
    { method: "post", body: JSON.stringify({}) },
    { paths: { relicsId } }
  );

  scenes.forEach((scene) => {
    scene.sceneId = scene.id;
  });
  return scenes;
};
export const addRelicsScenesFetch = (
  relicsId: number,
  scenes: Pick<Scene, "sceneCode" | "id">[]
) =>
  sendFetch(
    URL.addRelicsScene,
    { method: "post", body: JSON.stringify(scenes) },
    { paths: { relicsId } }
  );
export const delRelicsScenesFetch = (
  relicsId: number,
  scenes: Pick<Scene, "sceneCode" | "id">[]
) =>
  sendFetch(
    URL.delRelicsScene,
    { method: "post", body: JSON.stringify(scenes) },
    { paths: { relicsId } }
  );
export const updateRelicsScenePosNameFetch = (posId: number, name: string) =>
  sendFetch(URL.updateRelicsScenePosName, {
    method: "post",
    body: JSON.stringify({ id: posId, name }),
  });

export const relicsScenePosInfoFetch = (posId: number) =>
  sendFetch<ScenePoint>(
    URL.getRelicsScenePosInfo,
    {
      method: "post",
      body: JSON.stringify({}),
    },
    { paths: { posId } }
  );

export type ScenePageProps = PageProps<{
  sceneCode?: string;
  sceneName?: string;
  title?: string;
  cameraType?: number;
  algorithmTime?: [Date, Date];
  shootTime?: [Date, Date];
  endTime?: string;
  sceneSource?: number;
  snCode?: string;
  startTime?: string;
  userName?: string;
}>;
export const scenePageFetch = (props: ScenePageProps) =>
  sendFetch<ResPage<Scene>>(URL.getScenesPage, {
    method: "post",
    body: JSON.stringify({
      ...props,
      algorithmTime: null,
      startTime:
        props.shootTime &&
        dateFormat(props.shootTime[0], "yyyy-MM-dd 00:00:00"),
      endTime:
        props.shootTime &&
        dateFormat(props.shootTime[1], "yyyy-MM-dd 23:59:59"),
    }),
  });

export const delSceneFetch = (sceneId: number) =>
  sendFetch(
    URL.delScene,
    {
      method: "post",
      body: JSON.stringify({}),
    },
    { paths: { sceneId } }
  );

export type DevicePageProps = PageProps<{
  cameraSn?: string;
  cameraType?: number;
}>;
export const devicePageFetch = (props: DevicePageProps) =>
  sendFetch<ResPage<Device>>(URL.getDevicePage, {
    method: "post",
    body: JSON.stringify(props),
  });

export const delDeviceFetch = (deviceId: number) =>
  sendFetch(
    URL.delDevice,
    {
      method: "post",
      body: JSON.stringify({}),
    },
    { paths: { deviceId } }
  );
export const addDeviceFetch = (sn: string) =>
  sendFetch(URL.addDevice, {
    method: "post",
    body: JSON.stringify({ cameraSn: sn }),
  });
