import React, { useEffect } from 'react';
import { useDispatch, useSelector, useStore } from 'react-redux';
import NextLink from 'next/link';
import { useRouter } from 'next/router';

import {
  PUBLISH_DESTINATION_TYPES,
  PUBLISH_SETTINGS,
  SETTINGS_STATUS_DISCONNECTED,
  STATUS_SETTINGS,
  TAB_GENERAL,
  TYPE_FACEBOOK,
  TYPE_YOUTUBE,
} from '../constants';
import { PCN_POST_DESTINATIONS, PCN_PUT_DESTINATIONS } from '@/modules/@common/acl/constants';

import { publishersSelector } from '../../DestinationList/redux/selectors';
import { getPublishersAction } from '../../DestinationList/redux/slices';
import * as selectors from '../redux/selectors';
import {
  clearFormAction,
  createDestinationAction,
  exchangeFacebookAuthCodeAction,
  exchangeGoogleAuthCodeAction,
  getDestinationByIdAction,
  getViewabilityConfigAction,
  removeErrorByPropAction,
  setActiveTabIdAction,
  setErrorByPropAction,
  setScrollToFieldNameAction,
  updateDestinationAction,
  updateDestinationFormAction,
  validateFields,
} from '../redux/slices';
import { getInputPropsByName } from '@/modules/@common/Form/helpers';
import { hasPermission } from '@/modules/@common/user/helpers';
import { getUserPermissionsSelector } from '@/modules/@common/user/redux/selectors';

import { Form, FormContent, FormRow, FormSection } from '@/modules/@common/Form';
import { SignButton } from './SignButton/SignButton';
import {
  Autocomplete,
  Button,
  Checkbox,
  FormControl,
  FormControlLabel,
  FormHelperText,
  GridList,
  InputLabel,
  MenuItem,
  Select,
  Stack,
  TabContent,
  TextField,
  Typography,
} from '@/mui/components';

import styles from './styles.module.scss';

const DISPLAY_NAME_MAX_LENGTH = 100;

function Destination() {
  const size = 'small';
  const store = useStore();
  const dispatch = useDispatch();
  const router = useRouter();

  const name = useSelector(selectors.nameSelector);
  const visibility = useSelector(selectors.visibilitySelector);
  const status = useSelector(selectors.statusSelector);
  const accessToken = useSelector(selectors.accessTokenSelector);
  const channels = useSelector(selectors.channelsSelector);
  const defaultChannel = useSelector(selectors.defaultChannelSelector);
  const playlists = useSelector(selectors.playlistsSelector);
  const viewabilityConfig = useSelector(selectors.viewabilityConfigSelector);
  const isLoading = useSelector(selectors.isLoadingSelector);
  const publisherId = useSelector(selectors.publisherIdSelector);
  const publisher = useSelector(selectors.publisherSelector);
  const type = useSelector(selectors.typeSelector);
  const activeTabId = useSelector(selectors.activeTabIdSelector);
  const scheme = useSelector(selectors.schemeSelector);
  const publishers = useSelector(publishersSelector);
  const userPermissions = useSelector(getUserPermissionsSelector);

  const publishSettings = {
    title: useSelector(selectors.titleSelector),
    language: useSelector(selectors.languageSelector),
    category: useSelector(selectors.categorySelector),
    manualTags: useSelector(selectors.manualTagsSelector),
    thumbnail: useSelector(selectors.thumbnailSelector),
    autoTags: useSelector(selectors.autoTagsSelector),
    description: useSelector(selectors.descriptionSelector),
    closedCaptions: useSelector(selectors.closedCaptionsSelector),
  };

  const destinationId = +router.query.id;
  const destinationPlatform = router.query.platform.toUpperCase();

  let viewabilities; // []

  const isDeniedByPermission = destinationId
    ? !hasPermission(PCN_PUT_DESTINATIONS, userPermissions)
    : !hasPermission(PCN_POST_DESTINATIONS, userPermissions);

  if (destinationId) {
    const config = viewabilityConfig.find((conf) => conf.mediaPlatform === type);

    const transitions = config?.transitions.find((transition) => transition.name === visibility)?.transitions ?? [];

    viewabilities =
      config?.viewabilities
        ?.filter((viewabilitiy) => transitions.includes(viewabilitiy.name) || viewabilitiy.name === visibility)
        ?.map((viewabilitiy) => ({
          label: viewabilitiy.name.toLowerCase(),
          value: viewabilitiy.name,
        })) ?? [];
  } else {
    viewabilities =
      viewabilityConfig
        .find((config) => config.mediaPlatform === type)
        ?.viewabilities.filter((viewabilitiy) => !viewabilitiy.onlyForExisting)
        ?.map((viewabilitiy) => ({
          label: viewabilitiy.name.toLowerCase(),
          value: viewabilitiy.name,
        })) ?? [];
  }

  const handleOnChange = (fieldName, fieldValue) => {
    if (fieldName === 'defaultChannel') {
      const channel = channels.find((ch) => ch.id === fieldValue);

      return dispatch(
        updateDestinationFormAction({
          [fieldName]: fieldValue,
          defaultChannelName: channel?.title ?? '',
          pageAccessToken: channel?.token ?? '',
        }),
      );
    }

    if (fieldName === 'defaultPlaylist') {
      const defaultPlaylistName = playlists.find((playlist) => playlist.id === fieldValue)?.title;

      return dispatch(
        updateDestinationFormAction({
          [fieldName]: fieldValue,
          defaultPlaylistName,
        }),
      );
    }

    return dispatch(
      updateDestinationFormAction({
        [fieldName]: fieldValue,
      }),
    );
  };

  const handleAuthResponse = (responseEvent) => {
    if (responseEvent?.data?.type === 'ac_auth_fb') {
      dispatch(exchangeFacebookAuthCodeAction(responseEvent?.data));
    }
    if (responseEvent?.data?.type === 'ac_auth_g') {
      dispatch(exchangeGoogleAuthCodeAction(responseEvent?.data));
    }
  };

  let channelTitle = '';

  if (destinationPlatform === TYPE_YOUTUBE) {
    channelTitle = 'Default Channel';
  } else if (destinationPlatform === TYPE_FACEBOOK) {
    channelTitle = 'Default Page';
  }

  useEffect(() => {
    dispatch(getViewabilityConfigAction(destinationId));

    if (destinationPlatform) {
      dispatch(
        updateDestinationFormAction({
          type: destinationPlatform,
        }),
      );
    }

    if (destinationId) {
      dispatch(
        getDestinationByIdAction({
          id: destinationId,
        }),
      );
    }

    window.addEventListener('message', handleAuthResponse);

    return () => window.removeEventListener('message', handleAuthResponse);
  }, [destinationPlatform]);

  useEffect(() => {
    if (status === SETTINGS_STATUS_DISCONNECTED) {
      dispatch(
        updateDestinationFormAction({
          accessToken: '',
        }),
      );
    }
  }, [status]);

  useEffect(() => {
    if (channels?.length) {
      dispatch(
        updateDestinationFormAction({
          defaultChannel: channels[0].id,
          defaultChannelName: channels[0].title,
          pageAccessToken: channels[0].token || '',
        }),
      );
    }

    if (playlists?.length) {
      dispatch(
        updateDestinationFormAction({
          defaultPlaylist: playlists[0].id,
          defaultPlaylistName: playlists[0].title,
        }),
      );
    }
  }, [channels, playlists]);

  const saveToServerForm = () => {
    const state = store.getState();
    const allProps = selectors.fullAccessToStoreFieldsForValidation(state);

    const { validation, errorList } = validateFields(
      selectors
        .schemeSelector(state)
        .filter(({ fieldName }) => {
          if (fieldName === 'platform') {
            return !allProps.accessToken;
          }

          return true;
        })
        .map(({ fieldName }) => fieldName),
      allProps,
    );

    if (errorList.length) {
      const errorField = errorList.find((error) => error.tabId === activeTabId) ?? errorList[0];

      dispatch(setActiveTabIdAction(errorField.tabId));
      dispatch(setScrollToFieldNameAction(errorField.fieldName));
    } else if (destinationId) {
      dispatch(updateDestinationAction(destinationId));
    } else {
      dispatch(createDestinationAction());
    }

    dispatch(setErrorByPropAction(validation));
  };

  const defaultChannelScheme = getInputPropsByName(scheme, ['defaultChannel']);

  const destinationType = PUBLISH_DESTINATION_TYPES.find((dest) => dest.value === destinationPlatform);

  return (
    <div className={styles.Wrapper}>
      <Stack direction="column" fullWidth justifyContent="center" className={styles.Title}>
        <Typography component="div" variant="h6" noWrap>
          {destinationId ? `${destinationType?.label} ${name} > Settings` : 'New Publish Destination'}
        </Typography>
      </Stack>
      <Stack
        spacing={1}
        fullWidth
        direction="row"
        alignItems="center"
        justifyContent="space-between"
        className={styles.Controls}
      >
        <Stack spacing={2} justifyContent="flex-end" alignItems="center" direction="row">
          <Button
            size="small"
            variant="outlined"
            component={NextLink}
            href="/publishing"
            onClick={() => dispatch(clearFormAction())}
          >
            Cancel
          </Button>
          {!isDeniedByPermission && (
            <Button size="small" variant="contained" color="primary" disabled={isLoading} onClick={saveToServerForm}>
              Save
            </Button>
          )}
        </Stack>
      </Stack>
      <Form size={size} className={styles.Container} scrollFieldSelector={selectors.scrollFieldSelector}>
        <TabContent component={FormContent} selectedId={activeTabId} id={TAB_GENERAL}>
          <FormSection>
            <FormRow label="Authorization">
              <SignButton size={size} disabled={isDeniedByPermission} />
            </FormRow>
            <FormRow label="Display Name">
              <TextField
                size={size}
                value={name}
                placeholder="Enter Name"
                {...getInputPropsByName(scheme, ['name'])}
                disabled={isDeniedByPermission}
                inputProps={{ maxLength: DISPLAY_NAME_MAX_LENGTH }}
                onChange={(e) => handleOnChange('name', e.target.value)}
                onFocus={() => dispatch(removeErrorByPropAction(['name']))}
              />
            </FormRow>
            <FormRow label="Hub">
              <Autocomplete
                value={publishers?.find((pub) => +pub.id === +publisherId) || publisher}
                size={size}
                onOpen={() => dispatch(getPublishersAction())}
                onChange={(e, value) => handleOnChange('publisherId', value?.id)}
                options={publishers}
                optionLabelKey="name"
                optionValueKey="id"
                disabled={isDeniedByPermission}
                renderInput={(params$) => (
                  <TextField
                    {...params$}
                    {...getInputPropsByName(scheme, ['publisherId'])}
                    placeholder="Select Hub"
                    onChange={(e) => dispatch(getPublishersAction(e.target.value))}
                    onFocus={() => dispatch(removeErrorByPropAction(['publisherId']))}
                  />
                )}
              />
            </FormRow>
            <FormRow label="Visibility Settings">
              <Select
                size={size}
                placeholder="Select visibility"
                value={visibility}
                onChange={(event) => handleOnChange('visibility', event.target.value)}
                disabled={isDeniedByPermission}
              >
                {viewabilities.map((visibilityObj) => (
                  <MenuItem key={visibilityObj.value} value={visibilityObj.value}>
                    {visibilityObj.label}
                  </MenuItem>
                ))}
              </Select>
            </FormRow>
            <FormRow label="Status">
              <Select
                size={size}
                placeholder="Select status"
                value={status}
                disabled={!accessToken || isDeniedByPermission}
                onChange={(event) => handleOnChange('status', event.target.value)}
              >
                {STATUS_SETTINGS.map((statusObj) => (
                  <MenuItem
                    key={statusObj.value}
                    disabled={statusObj.value === SETTINGS_STATUS_DISCONNECTED}
                    value={statusObj.value}
                  >
                    {statusObj.label}
                  </MenuItem>
                ))}
              </Select>
            </FormRow>
            <FormRow label={channelTitle} tooltip={!channels.length && `${channelTitle} will be used to post`}>
              <FormControl fullWidth size={size}>
                {defaultChannelScheme.label && defaultChannelScheme.required && (
                  <InputLabel required size={size} error={defaultChannelScheme.error}>
                    Required
                  </InputLabel>
                )}
                <Select
                  size={size}
                  placeholder="Select channel"
                  label={defaultChannelScheme.label}
                  value={defaultChannel || 'none'}
                  readOnly={!channels || !channels.length || destinationId || isDeniedByPermission}
                  disabled={!channels || !channels.length}
                  onChange={(event) => handleOnChange('defaultChannel', event.target.value)}
                  onFocus={() => dispatch(removeErrorByPropAction(['defaultChannel']))}
                >
                  {!channels.length && (
                    <MenuItem value="none" disabled>
                      {'No any '}
                      {TYPE_YOUTUBE === destinationPlatform && 'channels'}
                      {TYPE_FACEBOOK === destinationPlatform && 'pages'}
                    </MenuItem>
                  )}
                  {channels.map((channel) => (
                    <MenuItem key={channel.id} value={channel.id}>
                      {channel.title}
                    </MenuItem>
                  ))}
                </Select>
                {defaultChannelScheme.helperText && (
                  <FormHelperText error={defaultChannelScheme.error}>{defaultChannelScheme.helperText}</FormHelperText>
                )}
              </FormControl>
            </FormRow>
            <FormRow label="Publish Settings">
              <GridList direction="column" rowCount={2}>
                {PUBLISH_SETTINGS.map((setting) => (
                  <FormControlLabel
                    size={size}
                    key={setting.value}
                    control={
                      <Checkbox
                        key={setting.value}
                        size={size}
                        disabled={setting.propertyName === 'title' || isDeniedByPermission}
                        checked={publishSettings[setting.propertyName]}
                        color="primary"
                        onChange={() => {
                          handleOnChange(setting.propertyName, !publishSettings[setting.propertyName]);
                        }}
                      />
                    }
                    label={setting.label}
                  />
                ))}
              </GridList>
            </FormRow>
          </FormSection>
        </TabContent>
      </Form>
    </div>
  );
}

export default Destination;
