import { useQuery } from '@tanstack/react-query';
import { $proxyapi } from '@/api/api';
import { DashboardResponseData } from '@/services/DashboardService';
import { IAlarm } from '@/interfaces/alarms';

interface DashboardResponseError {
  result: 2;
};

type ISuccessResponse<T> = {
  result: 0;
} & T;
type withKey<K extends string, T> = Record<K, T>

type ITopResponse<F extends string, V> = withKey<F, V[]>

export interface DashboardTodayResponseData {
  result: 0;
  infos: {
    alarmVehiCount: number;
    companyCount: number;
    driverCount: number;
    licheng: string;
    onlineVehiCount: number;
    todayOnlineVehiCount: number;
    vehiCount: number;
    workTime: number;
  };
}

export interface IDashboardResponseBasicPanelData {
  result: 0;
  infos: {
    alarmCount: number[];
    interValDate: number[];
    vehicleOnlineConditions: Array<{
      gpsDate: number;
      count: number;
    }>;
    vehiStatus: number[];
    armHandle: {
      inspectNum: number;
      noReplayNum: number;
      replayNum: number;
    };
    alarmThrends: Array<{
      gpsDate: number;
      handleAlarmCount: number;
      licheng: number;
      totalAlarmCount: number;
      vehiId: number;
      vehiIdno: number;
      workTime: number;
    }>
  }
}

interface IUseDashboardDayData {
  searchDays: number
  vehiclesStatus: 0 | 1;
}

export interface IInstrumentPanelData {
  result: 0;
  info: IAlarm;
}

export type IInstrumentPanelAlarmData = ISuccessResponse<{
  chartsData: Array<Array<IAlarm>>;
  interValDate: Array<number>;
}>

export type IInstrumentPanelAlarmHandleRateData = ISuccessResponse<{
  chartsData: Record<string, IAlarm>;
  interValDate: Array<number>;
}>

export interface IVehicleTopItem {
  gpsDate: number;
  handleAlarmCount: number;
  licheng: number;
  totalAlarmCount: number;
  vehiId: number;
  vehiIdno: string;
  workTime: number;
}

export type IDashboardResponseTopAlarmData = ISuccessResponse<ITopResponse<'infos', IVehicleTopItem>>;
export type IDashboardResponseTopLichengData = ISuccessResponse<ITopResponse<'lichengTop', IVehicleTopItem>>;
export type IDashboardResponseTopWorktimeData = ISuccessResponse<ITopResponse<'workTimeTop', IVehicleTopItem>>;
export type IDriverScoreTopData = ISuccessResponse<ITopResponse<'driverChartsData', IAlarm>>;
export type ICompanyArmTopData = ISuccessResponse<ITopResponse<'companyChartsData', IAlarm>>;
export type IVehicleArmTopData = ISuccessResponse<ITopResponse<'vehicleChartsData', IAlarm>>;

export const useDashboardDayData = ({
  searchDays,
  vehiclesStatus
}: IUseDashboardDayData) => {
  const query = useQuery({
    queryKey: ['today', searchDays, vehiclesStatus],
    refetchInterval: 5000,
    queryFn: async () => {
      const basicPanel = $proxyapi.get<DashboardResponseError | IDashboardResponseBasicPanelData>(
        '/report/StandardReportAlarmSuBiao_getV6BasicPanelData.action',
        {
          params: {
            searchDays,
            isChangedVehicle: true
          }
        },
      ).then((res) => res.data);

      const summary = $proxyapi.get<DashboardResponseError | DashboardTodayResponseData>(
        '/report/StandardReportAlarmSuBiao_getBoardSummary.action',
        {
          params: {
            searchDays
          }
        },
      ).then((res) => res.data);
      

      const alarmTop = $proxyapi.get<DashboardResponseError | IDashboardResponseTopAlarmData>(
        '/report/StandardReportAlarmSuBiao_getV6VehicleAlarmTop.action',
        {
          params: {
            searchDays,
            status: vehiclesStatus,
            isChangedVehicle: false
          }
        },
      ).then((res) => res.data);

      const lichengTop = $proxyapi.get<DashboardResponseError | IDashboardResponseTopLichengData>(
        '/report/StandardReportAlarmSuBiao_getV6VehicleLichengTop.action',
        {
          params: {
            searchDays,
            status: vehiclesStatus,
            isChangedVehicle: false
          }
        },
      ).then((res) => res.data);

      const workTop = $proxyapi.get<DashboardResponseError | IDashboardResponseTopWorktimeData>(
        '/report/StandardReportAlarmSuBiao_getV6VehicleWorkTimeTop.action',
        {
          params: {
            searchDays,
            status: vehiclesStatus,
            isChangedVehicle: false
          }
        },
      ).then((res) => res.data);

      const instrumentPanel = $proxyapi.get<DashboardResponseError | IInstrumentPanelData>(
        '/report/StandardReportAlarmSuBiao_getInstrumentPanel.action',
        {
          params: {
            searchDays,
            isChangedVehicle: false
          }
        },
      ).then((res) => res.data);

      const instrumentPanelAlarm = $proxyapi.get<DashboardResponseError | IInstrumentPanelAlarmData>(
        '/report/StandardReportAlarmSuBiao_getInstrumentPanelAlarm.action',
        {
          params: {
            searchDays,
            value: 0
          }
        },
      ).then((res) => res.data);

      const vehicleArmTop = $proxyapi.get<DashboardResponseError | IVehicleArmTopData>(
        '/report/StandardReportAlarmSuBiao_getVehicleArmTop.action',
        {
          params: {
            searchDays,
            status: 1,
            isChangedVehicle: false
          }
        },
      ).then((res) => res.data);

      const driverScoreTop = $proxyapi.get<DashboardResponseError | IDriverScoreTopData>(
        '/report/StandardReportAlarmSuBiao_getDriverScoreTop.action',
        {
          params: {
            searchDays,
            status: 0,
            isChangedVehiGroup: false
          }
        },
      ).then((res) => res.data);

      const companyArmTop = $proxyapi.get<DashboardResponseError | ICompanyArmTopData>(
        '/report/StandardReportAlarmSuBiao_getCompanyArmTop.action',
        {
          params: {
            searchDays,
            status: 1,
            isChangedVehiGroup: false
          }
        },
      ).then((res) => res.data);

      const instrumentPanelAlarmHandleRate = $proxyapi.get<DashboardResponseError | IInstrumentPanelAlarmHandleRateData>(
        '/report/StandardReportAlarmSuBiao_getInstrumentPanelAlarmHandleRate.action',
        {
          params: {
            searchDays,
            status: 1,
            isChangedVehiGroup: false
          }
        },
      ).then((res) => res.data);
      

      const res = await resolveObject({
        summary,
        basicPanel,
        alarmTop,
        lichengTop,
        workTop,
        instrumentPanel,
        vehicleArmTop,
        driverScoreTop,
        companyArmTop,
        instrumentPanelAlarmHandleRate,
        instrumentPanelAlarm
      }) as {
        summary: Unpromise<typeof summary>;
        basicPanel: Unpromise<typeof basicPanel>;
        alarmTop: Unpromise<typeof alarmTop>;
        lichengTop: Unpromise<typeof lichengTop>;
        workTop: Unpromise<typeof workTop>;
        instrumentPanel: Unpromise<typeof instrumentPanel>;
        vehicleArmTop: Unpromise<typeof vehicleArmTop>;
        driverScoreTop: Unpromise<typeof driverScoreTop>;
        companyArmTop: Unpromise<typeof companyArmTop>;
        instrumentPanelAlarm: Unpromise<typeof instrumentPanelAlarm>;
      };

      
      if(Object.values(res).some((el) => el.result !== 0)) {
        return {
          summary: null,
          basicPanel: null,
          alarmTop: null,
          lichengTop: null,
          workTop: null,
          instrumentPanel: null,
          vehicleArmTop: null,
          driverScoreTop: null,
          companyArmTop: null,
          instrumentPanelAlarmHandleRate: null,
          instrumentPanelAlarm: null
        }
      }
      
      return res as {
        summary: DashboardTodayResponseData;
        basicPanel: IDashboardResponseBasicPanelData;
        alarmTop: IDashboardResponseTopAlarmData;
        lichengTop: IDashboardResponseTopLichengData;
        workTop: IDashboardResponseTopWorktimeData;
        instrumentPanel: IInstrumentPanelData;
        vehicleArmTop: IVehicleArmTopData;
        driverScoreTop: IDriverScoreTopData;
        companyArmTop: ICompanyArmTopData;
        instrumentPanelAlarm: IInstrumentPanelAlarmData;
        instrumentPanelAlarmHandleRate: IInstrumentPanelAlarmHandleRateData;
      };
    },
  });

  return query;
};

type Unpromise<T extends Promise<any>> = T extends Promise<infer U> ? U : never;

function resolveObject<T extends Record<string, Promise<any>>>(obj: T)
{
  return Promise.all(
    Object.entries(obj).map(async ([k, v]) => [k, await v])
  ).then(Object.fromEntries);
}