import { Suspense, useEffect, useRef, useState } from 'react';
import { Alert, AlertIcon, Container, Tabs, Tab, TabList, TabPanels, TabPanel } from '@chakra-ui/react';
import { useParams } from 'react-router-dom';

import { Breadcrumb } from '../../components/common';
import { ROUTES } from '../../constants/paths';
import { useMyToast } from '../../hooks';
import { JobUpdationForm, JobRecordTable } from '../../components/jobs';
import {
  DATE_TIME_FORMAT,
  EVENT_NAMES,
  ORDER,
  PAGINATION,
  STATUS_MESSAGES,
  TIME_INTERVALS,
} from '../../constants/define';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { convertDateToString, getDiff } from '../../utilities/functions';

const JobDetailPage = () => {
  const { jobId } = useParams(),
    toast = useMyToast(),
    formikRef = useRef(),
    queryClient = useQueryClient(),
    [page, setPage] = useState(PAGINATION.PAGE),
    [pageSize, setPageSize] = useState(PAGINATION.PAGE_SIZE),
    [order, setOrder] = useState({
      id: ORDER.ORDER_BY,
      desc: true,
    }),
    [logs, setLogs] = useState([]);

  const { data } = useQuery({
    queryKey: [EVENT_NAMES.JOBS.VIEW, jobId],
    queryFn: async () => {
      const response = await window.grpcAPIs[EVENT_NAMES.JOBS.VIEW](jobId);
      return response;
    },
    initialData: async () => {
      const job = queryClient.getQueryData([EVENT_NAMES.JOBS.VIEW, jobId]);
      return job;
    },
    staleTime: TIME_INTERVALS.TEN_MINUTES_IN_MILLISECONDS,
    initialDataUpdatedAt: () => queryClient.getQueryState([EVENT_NAMES.JOBS.VIEW, jobId])?.dataUpdatedAt,
  });

  const { data: records, isLoading: isFetchingRecords } = useQuery({
    queryKey: [EVENT_NAMES.RECORDS.LIST, jobId, page, pageSize, order?.id, order?.desc],
    queryFn: () => {
      return window.grpcAPIs[EVENT_NAMES.RECORDS.LIST]({
        jobId,
        page,
        pageSize,
        // orderBy: order,
      });
    },
    onSuccess: (data) => {
      setPage(data?.page || PAGINATION.PAGE);
      setPageSize(data?.pageSize || PAGINATION.PAGE_SIZE);
    },
    staleTime: TIME_INTERVALS.TEN_MINUTES_IN_MILLISECONDS,
    placeholderData: [],
  });

  useEffect(() => {
    setLogs(
      records?.data?.reverse()?.map((record) => ({
        time: convertDateToString(record?.scratchDatetime, DATE_TIME_FORMAT.DATE_TIME),
        message: record?.status,
        success: record?.status === 'success',
      })),
    );
  }, [records?.data]);

  const breadcrumbItems = [
    {
      title: 'Jobs',
      href: ROUTES.DASHBOARD.JOBS.ROOT.path,
    },
    {
      title: data?.name || '',
      isCurrentPage: true,
    },
  ];

  const { mutate, isLoading, error, isError } = useMutation({
    mutationKey: [EVENT_NAMES.JOBS.UPDATE, jobId],
    mutationFn: () => {
      const values = formikRef.current.values;
      const initialValues = formikRef.current.initialValues;
      const diffValues = getDiff(values, initialValues);
      return window.grpcAPIs[EVENT_NAMES.JOBS.UPDATE]({
        id: jobId,
        ...diffValues,
      });
    },
    onSuccess: (newData) => {
      formikRef.current.resetForm({
        values: {
          ...data,
          ...newData,
        },
      });
      queryClient.setQueryData([EVENT_NAMES.JOBS.VIEW, jobId], newData);
      queryClient.invalidateQueries({
        queryKey: [EVENT_NAMES.JOBS.LIST],
      });
      toast({
        title: 'Success',
        description: STATUS_MESSAGES.UPDATE_SUCCESS,
        status: 'success',
      });
    },
  });

  const {
    mutate: runJob,
    isLoading: isRunning,
    error: runError,
    isError: isRunError,
  } = useMutation({
    mutationKey: [EVENT_NAMES.JOBS.RUN_JOB, jobId],
    mutationFn: () => {
      return window.grpcAPIs[EVENT_NAMES.JOBS.RUN_JOB](jobId);
    },
    onMutate: () => {
      setLogs([
        ...logs,
        {
          time: convertDateToString(new Date(), DATE_TIME_FORMAT.DATE_TIME),
          message: '...running job',
        },
      ]);
    },
    onSettled: () => {
      queryClient.invalidateQueries({
        queryKey: [EVENT_NAMES.RECORDS.LIST],
      });
    },
    onSuccess: () => {
      toast({
        title: 'Success',
        description: STATUS_MESSAGES.RUN_SUCCESS,
        status: 'success',
      });
    },
  });

  const hanldePaginationChange = (page, pageSize) => {
    setPage(page);
    setPageSize(pageSize);
  };

  const handleSort = (value) => {
    setOrder({
      id: value.id,
      desc: !order.desc,
    });
  };

  return (
    <Container maxWidth="container.xl" spacing={4}>
      <Breadcrumb breadcrumbItems={breadcrumbItems} fontSize="lg" />
      {isError && (
        <Alert my={5} status="error">
          <AlertIcon />
          {error?.message}
        </Alert>
      )}
      {isRunError && (
        <Alert my={5} status="error">
          <AlertIcon />
          {runError?.message}
        </Alert>
      )}
      <Suspense fallback={<div>...loading</div>}>
        {data && (
          <Tabs>
            <TabList>
              <Tab>Details</Tab>
              <Tab>Records</Tab>
            </TabList>
            <TabPanels>
              <TabPanel>
                <JobUpdationForm
                  job={data}
                  logs={logs}
                  formRef={formikRef}
                  onUpdate={mutate}
                  onRun={runJob}
                  isRunning={isRunning}
                  isLoading={isLoading}
                />
              </TabPanel>
              <TabPanel>
                <JobRecordTable
                  jobId={jobId}
                  records={records?.data || []}
                  onSort={handleSort}
                  loading={isFetchingRecords}
                  order={{
                    ...(order?.id
                      ? {
                          id: order?.id,
                          desc: order?.desc,
                        }
                      : {}),
                    onOrderBy: handleSort,
                  }}
                  pagination={{
                    currentPage: page,
                    pageSize,
                    total: data?.total || 0,
                    onPaginationChange: hanldePaginationChange,
                  }}
                />
              </TabPanel>
            </TabPanels>
          </Tabs>
        )}
      </Suspense>
    </Container>
  );
};

export default JobDetailPage;
