import React, { useEffect, useMemo, useState } from 'react';
import { useRouter } from 'next/router';
import { CheckOutlined, EditOutlined, InfoOutlined } from '@mui/icons-material';

import {
  ConvertedModel,
  createDefaultPlatformModels,
  createModelsListFromMetadataPlatform,
  getModelConfig,
  getModelEnabled,
} from './helpers';
import setupGetConfigurationErrorCode, {
  ConfigurationErrorOutputType,
} from '@/modules/feeds/Editor/components/Dialogs/ConfigurationErrorDialog/helpers/setupGetConfigurationErrorCode';
import {
  metadataPlatformModelsSelector,
  platformModelsSelector,
  typeSelector,
} from '@/modules/feeds/Editor/redux/selectors';
import { setAction } from '@/modules/feeds/Editor/redux/slices';

import { FormGroupTitle, FormRow } from '@/modules/@common/Form';
import { useAppDispatch, useAppSelector, useAppStore } from '@/modules/@common/store/hooks';
import { TableCellActions } from '@/modules/@common/Table';
import ConfigurationErrorDialog from '@/modules/feeds/Editor/components/Dialogs/ConfigurationErrorDialog/ConfigurationErrorDialog';
import ModelEditDialog from '@/modules/feeds/Editor/components/Dialogs/ModelEditDialog/ModelEditDialog';
import SpeechToTextProvider from '@/modules/feeds/Editor/components/FormElements/SpeechToTextProvider/SpeechToTextProvider';
import {
  IconButton,
  Stack,
  Switch,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Tooltip,
  Typography,
} from '@/mui/components';

function ModelTab() {
  const router = useRouter();
  const dispatch = useAppDispatch();
  const store = useAppStore();
  const metadataPlatform = useAppSelector(metadataPlatformModelsSelector);
  const type = useAppSelector(typeSelector);

  const [editModel, setEditModel] = useState<ConvertedModel | null>(null);
  const [configurationError, setConfigurationError] = useState<ConfigurationErrorOutputType>(null);

  const platformModels = useAppSelector(platformModelsSelector);

  const models = useMemo(
    () => createModelsListFromMetadataPlatform(metadataPlatform, type as Exclude<'', typeof type>),
    [metadataPlatform, type],
  );

  const isCreateNewForm = (router.query.id as string) === 'new';

  const getConfigurationErrorCode = setupGetConfigurationErrorCode(store);

  const handleChangeModelEnabled = (model: string) => {
    // LABELS should auto-enable if:
    // 1) user toggles a classification model, or
    // 2) user toggles LABELS while any classification model is already enabled
    const CLASSIFICATION = ['KEYWORDS_CLASSIFICATION', 'IAB_CLASSIFICATION'];
    const hasEnabledClassification = platformModels.some((m) => CLASSIFICATION.includes(m.model) && m.enabled);
    const shouldEnableLabelsModel = CLASSIFICATION.includes(model) || (model === 'LABELS' && hasEnabledClassification);

    const changedPlatformModels = platformModels.map((m) => {
      if (m.model === 'LABELS' && shouldEnableLabelsModel) {
        // ensure LABELS is enabled
        return m.enabled ? m : { ...m, enabled: true };
      }

      if (m.model === model) {
        // toggle the clicked model
        return { ...m, enabled: !m.enabled };
      }

      return m;
    });

    const error = getConfigurationErrorCode({ inputModels: changedPlatformModels });

    if (error) {
      setConfigurationError(error);
      return;
    }

    dispatch(
      setAction({
        platformModels: changedPlatformModels,
      }),
    );
  };

  const handleChangeModelConfig = (model: string, config: string) => {
    const changedPlatformModels = platformModels.map((entity) =>
      entity.model === model && config ? { ...entity, config } : entity,
    );

    dispatch(
      setAction({
        platformModels: changedPlatformModels,
      }),
    );
  };

  useEffect(() => {
    if (models.length !== platformModels.length) {
      const defaultPlatformModels = createDefaultPlatformModels(models, platformModels, isCreateNewForm);

      dispatch(
        setAction({
          platformModels: defaultPlatformModels,
        }),
      );
    }
  }, [platformModels, models, isCreateNewForm]);

  return (
    <>
      <FormRow label="Speech to Text">
        <SpeechToTextProvider />
      </FormRow>
      <FormGroupTitle>Models</FormGroupTitle>
      <TableContainer>
        <Table>
          <TableHead>
            <TableRow>
              <TableCell>Category</TableCell>
              <TableCell>Platform</TableCell>
              <TableCell>Model</TableCell>
              <TableCell>Enabled</TableCell>
              <TableCell>Configuration</TableCell>
              <TableCell />
            </TableRow>
          </TableHead>
          <TableBody>
            {models.map((model) => (
              <TableRow key={model.id} hover>
                <TableCell>
                  <Typography variant="body2" color="text.primary">
                    {model.category}
                  </Typography>
                </TableCell>
                <TableCell>
                  <Typography variant="body2" color="text.primary">
                    {model.platform}
                  </Typography>
                </TableCell>
                <TableCell>
                  <Typography variant="body2" color="text.primary">
                    <Stack direction="row" gap={1} alignItems="center">
                      {model.model}
                      {model.description && (
                        <Tooltip title={model.description}>
                          <InfoOutlined fontSize="small" htmlColor="info.main" />
                        </Tooltip>
                      )}
                    </Stack>
                  </Typography>
                </TableCell>
                <TableCell>
                  <Stack spacing={2} alignContent="center">
                    <Switch
                      checked={getModelEnabled(model.model, platformModels)}
                      color="primary"
                      size="small"
                      onChange={() => handleChangeModelEnabled(model.model)}
                    />
                  </Stack>
                </TableCell>
                <TableCell>
                  {getModelConfig(model.model, platformModels) !== '{}' ? (
                    <CheckOutlined htmlColor="success.main" fontSize="small" />
                  ) : (
                    <Typography variant="body2" color="text.primary">
                      -
                    </Typography>
                  )}
                </TableCell>
                <TableCellActions>
                  <Tooltip title="Set Configuration" disableInteractive>
                    <IconButton
                      size="small"
                      onClick={(e) => {
                        e.stopPropagation();
                        setEditModel(model);
                      }}
                    >
                      <EditOutlined />
                    </IconButton>
                  </Tooltip>
                </TableCellActions>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
      {editModel && (
        <ModelEditDialog
          model={editModel}
          value={getModelConfig(editModel.model, platformModels)}
          onClose={() => setEditModel(null)}
          onSave={(config) => handleChangeModelConfig(editModel?.model, config)}
        />
      )}
      {!!configurationError && (
        <ConfigurationErrorDialog
          code={configurationError.code}
          open={!!configurationError}
          lang={configurationError.lang}
          speechProvider={configurationError.speechProvider}
          onClose={() => setConfigurationError(null)}
        />
      )}
    </>
  );
}

export default ModelTab;
