import { type FC, useEffect } from 'react';
import { Helmet } from 'react-helmet-async';
import { useMutation, useQuery } from 'react-query';
import {
  useLocation,
  useNavigate,
  useParams,
  useSearchParams,
} from 'react-router-dom';

import { AxiosError } from 'axios';
import { once } from 'lodash-es';
import Divider from '@material-hu/mui/Divider';
import Stack from '@material-hu/mui/Stack';

import Skeleton from '@material-hu/components/design-system/Skeleton';
import HuTabs from '@material-hu/components/design-system/Tabs';

import { logEvent } from 'src/config/logging';
import { queryClient } from 'src/config/react-query';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import {
  downloadTaskCertificate,
  getApprovalGroupsCount,
  getTask,
  getTasksCount,
} from 'src/pages/dashboard/serviceManagement/services';
import { ServiceManagementRole } from 'src/pages/dashboard/serviceManagement/types';
import { isApprovalTask } from 'src/pages/dashboard/serviceManagement/utils';
import { EventName } from 'src/types/amplitude';
import { FeatureFlags } from 'src/types/featureFlags';
import { insertIf } from 'src/utils/arrays';
import { downloadBlob } from 'src/utils/files';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  TaskVisitProvider,
  useTaskVisit,
} from '../../contexts/TaskVisitContext';
import useSnackbar from '../../hooks/useSnackbar';
import useTaskActivitiesUptader from '../../hooks/useTaskActivitiesUptader';
import useTaskStateUpdater from '../../hooks/useTaskStateUpdater';
import useVisitTask from '../../hooks/useVisitTask';
import { serviceManagementKeys } from '../../queries';
import { serviceManagementRoutes } from '../../routes';

import ActivitiesTab from './components/ActivitiesTab';
import ApprovalInformation from './components/ApprovalInformation';
import ApprovalsTab from './components/ApprovalsTab';
import Header from './components/Header';
import Information from './components/Information';
import RequestTab from './components/RequestTab';
import ServiceInformation from './components/ServiceInformation';
import TasksTab from './components/TasksTab';

export type CatalogItemDetailsProps = {
  isAgentSide?: boolean;
};

export type TabsType = (typeof tabs)[keyof typeof tabs];

const TAB = 'tab';
export const tabs = {
  request: 'request',
  activities: 'activities',
  approvals: 'approvals',
  tasks: 'tasks',
} as const;

const ServiceItemDetailsInner: FC<CatalogItemDetailsProps> = props => {
  const { isAgentSide = false } = props;
  const { id } = useParams();
  const HugoThemeProvider = useHuGoTheme();
  const navigate = useNavigate();
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const { t } = useLokaliseTranslation('service_management');

  const { showSnackbar } = useSnackbar();

  const navigatedFromServiceMgmt =
    location.state?.navigatedFromServiceMgmt || false;

  const navigatedFromPortal = location.state?.navigatedFromPortal || false;
  const navigatedFromAgent = location.state?.navigatedFromAgent || false;
  const defaultApproval = navigatedFromAgent || navigatedFromPortal;

  const getTabFromUrl = (): TabsType => {
    const urlTab = searchParams.get(TAB) as TabsType | null;
    if (urlTab && Object.values(tabs).includes(urlTab)) {
      return urlTab;
    }
    // Fallback for navigation via location.state (in-app navigation)
    if (navigatedFromPortal || navigatedFromAgent) {
      return tabs.approvals;
    }
    return tabs.request;
  };

  const tab = getTabFromUrl();

  const setTab = (newTab: TabsType) => {
    setSearchParams(
      prev => {
        prev.set(TAB, newTab);
        return prev;
      },
      { replace: true, state: location.state },
    );
  };

  const logDetailViewedEvent = once(() => {
    logEvent(EventName.SERVICE_MGMT_REQUEST_DETAIL_VIEWED, {
      role: isAgentSide
        ? ServiceManagementRole.AGENT
        : ServiceManagementRole.INITIATOR,
      serviceId: taskData?.catalogItem?.id,
      serviceName: taskData?.catalogItem?.name,
      requestId: taskData?.id,
    });
  });

  const { data: taskData, isLoading: loadingTaskData } = useQuery({
    queryKey: serviceManagementKeys.tasks.detail(id!),
    queryFn: () => getTask(id!),
    enabled: !!id,
    select: response => response.data,
    onError: error => {
      if (error instanceof AxiosError && error.response?.status === 404) {
        navigate(serviceManagementRoutes.servicePortal());
      }
    },
  });

  const invalidateQueries = () => {
    queryClient.invalidateQueries(serviceManagementKeys.tasks.detail(id!));
    queryClient.invalidateQueries(
      serviceManagementKeys.activities.list(taskData?.parentTask?.id!),
    );
  };

  useTaskActivitiesUptader(id!);
  useTaskStateUpdater(id!);

  const { mutate: visitTaskMutate } = useVisitTask();
  const { visitedTaskIdRef } = useTaskVisit();
  const bubblesEnabled = useFeatureFlag(
    FeatureFlags.SERVICE_MANAGEMENT_BUBBLES_ENABLED,
  );

  // `Comments` (inside `RequestTab`) is the source of truth for the read state of
  // comments. When it's mounted, we let it fire the visit with the actual data.
  // `RequestTab` is always mounted on the user side; on the agent side it only
  // mounts when the active tab is `request`.
  const willRenderComments = !isAgentSide || tab === tabs.request;

  useEffect(() => {
    if (!taskData) return;
    logDetailViewedEvent();

    // Intentionally NOT called when the flag is OFF: the `visit` endpoint
    // exists exclusively for the red-bubbles lifecycle (no analytics, audit
    // or read-state side effects beyond it). Legacy `markLastReadComment`
    // from `Comments.tsx` keeps handling the unread state in that mode.
    if (!bubblesEnabled) return;

    // Flag ON: defer to `Comments.tsx` when it's going to mount; it has the real
    // read state and will resolve everything in one atomic call.
    if (willRenderComments) return;

    // When coming from the approvals portal or agent workspace approvals, the
    // first visit must target the approval subtask (not the parent). The
    // parent-task visit (with lastReadCommentId) is deferred to Comments.tsx
    // when the agent switches to the request tab.
    if (defaultApproval) {
      if (visitedTaskIdRef.current === defaultApproval) return;
      visitedTaskIdRef.current = defaultApproval;
      visitTaskMutate({ taskId: defaultApproval });
      return;
    }
  }, [
    taskData,
    bubblesEnabled,
    willRenderComments,
    defaultApproval,
    visitedTaskIdRef,
    visitTaskMutate,
  ]);

  const handleOnClose: () => void = () => {
    invalidateQueries();

    const cameFromInApp =
      navigatedFromServiceMgmt || navigatedFromAgent || navigatedFromPortal;

    if (cameFromInApp) {
      navigate(-1);
      return;
    }

    navigate(
      isAgentSide
        ? serviceManagementRoutes.agentWorkspace()
        : serviceManagementRoutes.servicePortal(),
    );
  };

  const { data: approvalsCount, isLoading: loadingApprovalsCount } = useQuery(
    serviceManagementKeys.approvalGroups.count(taskData?.id!, undefined),
    () => getApprovalGroupsCount(taskData?.id!, undefined),
    {
      select: response => response.data.count,
    },
  );

  const { data: tasksCount, isLoading: loadingTasksCount } = useQuery(
    serviceManagementKeys.tasks.childrenCount(taskData?.id!, undefined),
    () => getTasksCount(taskData?.id!, undefined),
    {
      select: response => response.data.count,
    },
  );

  const {
    mutate: handleDownloadCertificate,
    isLoading: isDownloadingCertificate,
  } = useMutation(() => downloadTaskCertificate(id!), {
    onSuccess: ({ data }) => {
      const taskNumber = taskData?.taskNumber ?? '';
      const employeeInternalId = taskData?.initiator?.employeeInternalId ?? '';
      const now = new Date();
      const timestamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}_${String(now.getMinutes()).padStart(2, '0')}_${String(now.getSeconds()).padStart(2, '0')}_${String(now.getMilliseconds()).padStart(3, '0')}`;
      const fileName = `${taskNumber}_${employeeInternalId}_${timestamp}.pdf`;
      downloadBlob(data, fileName);
      showSnackbar({
        title: t('download_certificate.success'),
        variant: 'success',
      });
      logEvent(EventName.SERVICE_MGMT_CERTIFICATE_DOWNLOADED, {
        role: isAgentSide
          ? ServiceManagementRole.AGENT
          : ServiceManagementRole.INITIATOR,
        requestId: taskData?.id,
        serviceId: taskData?.catalogItem?.id,
        serviceName: taskData?.catalogItem?.name,
      });
    },
    onError: () => {
      showSnackbar({
        title: t('download_certificate.error_title'),
        description: t('download_certificate.error_description'),
        variant: 'error',
      });
    },
  });

  const loadingTabs =
    loadingApprovalsCount || loadingTaskData || loadingTasksCount;

  const tabsArray = [
    { label: t('request'), value: tabs.request },
    ...insertIf((tasksCount ?? 0) > 0, {
      label: t('subtasks.title'),
      value: tabs.tasks,
    }),
    ...insertIf((approvalsCount ?? 0) > 0, {
      label: t('approvals.title'),
      value: tabs.approvals,
    }),
    { label: t('activity'), value: tabs.activities },
  ];

  const isApproval = isApprovalTask(taskData);

  return (
    <HugoThemeProvider>
      <Helmet>
        <title>{formatTitle(t('request'))}</title>
      </Helmet>
      <Stack
        sx={{
          backgroundColor: theme =>
            theme.palette.new.background.layout.tertiary,
          height: '100%',
        }}
      >
        <Header
          onClose={handleOnClose}
          task={taskData}
          loading={loadingTaskData}
          onDownloadCertificate={() => handleDownloadCertificate()}
          isDownloadingCertificate={isDownloadingCertificate}
        />
        <Divider />
        {isApproval && (
          <>
            <ApprovalInformation
              task={taskData}
              loading={loadingTaskData}
              invalidateQueries={invalidateQueries}
            />
            <Divider />
          </>
        )}
        {!isAgentSide && !isApproval && (
          <>
            <Information
              task={taskData}
              loading={loadingTaskData}
            />
            <Divider />
          </>
        )}
        {!isAgentSide && (
          <RequestTab
            taskData={taskData!}
            isAgentSide={isAgentSide}
            loading={loadingTaskData}
          />
        )}
        {isAgentSide && (
          <Stack
            sx={{ flexDirection: 'row', height: '100%', overflow: 'hidden' }}
          >
            <Stack sx={{ mt: 1, flex: 3, position: 'relative' }}>
              {!loadingTabs && (
                <HuTabs
                  tabs={tabsArray}
                  value={tab}
                  onTabChange={value => setTab(value as TabsType)}
                  sx={{ pl: 2 }}
                />
              )}
              {loadingTabs && (
                <>
                  <Stack
                    sx={{ flexDirection: 'row', gap: 1.5, pl: 2.5, pb: 1 }}
                  >
                    <Skeleton
                      variant="text"
                      width={70}
                      height={40}
                    />
                    <Skeleton
                      variant="text"
                      width={75}
                      height={40}
                    />
                  </Stack>
                  <Divider />
                </>
              )}
              {tab === tabs.request && (
                <RequestTab
                  taskData={taskData!}
                  isAgentSide={isAgentSide}
                  loading={loadingTaskData}
                />
              )}
              {tab === tabs.activities && (
                <ActivitiesTab taskData={taskData!} />
              )}
              {tab === tabs.approvals && (
                <ApprovalsTab
                  taskData={taskData!}
                  defaultApproval={defaultApproval}
                />
              )}
              {tab === tabs.tasks && <TasksTab taskData={taskData!} />}
            </Stack>
            <Stack
              sx={{
                flex: 1,
                borderLeft: theme => `1px solid ${theme.palette.divider}`,
              }}
            >
              <ServiceInformation
                loading={loadingTaskData}
                taskData={isApproval ? taskData?.parentTask : taskData}
                isAgentSide={isAgentSide}
              />
            </Stack>
          </Stack>
        )}
      </Stack>
    </HugoThemeProvider>
  );
};

const ServiceItemDetails: FC<CatalogItemDetailsProps> = props => (
  <TaskVisitProvider>
    <ServiceItemDetailsInner {...props} />
  </TaskVisitProvider>
);

export default ServiceItemDetails;
