import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'clsx';

import { VIDEO_MONETIZATION_DISABLED, VIDEO_MONETIZATION_ENABLED } from '@/modules/players/Editor/constants';

import { getInputPropsByName } from '@/modules/@common/Form/helpers';
import {
  castToInt,
  isAmpTypes,
  isOutstreamType,
  isStoriesTypes,
  isVerticalType,
} from '@/modules/players/Editor/helpers';
import * as playerSelectors from '@/modules/players/Editor/redux/selectors';
import { removeErrorByPropAction, setAction } from '@/modules/players/Editor/redux/slices';

import { FormGroup, FormGroupTitle, FormRow, FormRowItem, FormSection, useFormSettings } from '@/modules/@common/Form';
import IntervalsList from '../../IntervalsList/IntervalsList';
import {
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  List,
  ListItem,
  MenuItem,
  Select,
  Stack,
  Switch,
  TextField,
  Typography,
} from '@/mui/components';

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

const clipOptions = Array.from({ length: 10 }, (_, i) => {
  const value = i + 1;
  return {
    value,
    label: `${value} Clip${value > 1 ? 's' : ''}`,
  };
});

function VideoAdsTab() {
  const { size } = useFormSettings();
  const dispatch = useDispatch();

  const playerType = useSelector(playerSelectors.playerTypeSelector);

  const adManagerDesktop = useSelector(playerSelectors.adManagerDesktopSelector);
  const fallbackDisplayMonetizationDesktop = useSelector(playerSelectors.fallbackDisplayMonetizationDesktopSelector);

  const adManagerMobile = useSelector(playerSelectors.adManagerMobileSelector);
  const fallbackDisplayMonetizationMobile = useSelector(playerSelectors.fallbackDisplayMonetizationMobileSelector);

  const clipNotInViewPlayAdsDesktop = useSelector(playerSelectors.clipNotInViewPlayAdsDesktopSelector);
  const clipNotInViewPlayAdsMobile = useSelector(playerSelectors.clipNotInViewPlayAdsMobileSelector);

  const maxAdsPerClipChecked = useSelector(playerSelectors.maxAdsPerClipCheckedSelector);

  const maxAdsPerClip = useSelector(playerSelectors.maxAdsPerClipSelector);
  const maxAdsPerClipOptions = useSelector(playerSelectors.maxAdsPerClipOptionsSelector);

  const firstAdRequestDelay = useSelector(playerSelectors.firstAdRequestDelaySelector);

  const preRollOptions = useSelector(playerSelectors.preRollOptionsSelector);
  const preRoll = useSelector(playerSelectors.preRollSelector);
  const preRollWaitMs = useSelector(playerSelectors.preRollWaitMsSelector);

  const prerollOnly = useSelector(playerSelectors.prerollOnlySelector);
  const prerollOnlyClipsCount = useSelector(playerSelectors.prerollOnlyClipsCountSelector);

  const adIndicator = useSelector(playerSelectors.adIndicatorSelector);
  const adIndicatorText = useSelector(playerSelectors.adIndicatorTextSelector);

  const skipAdButton = useSelector(playerSelectors.skipAdButtonSelector);
  const skipAdAppearAfter = useSelector(playerSelectors.skipAdAppearAfterSelector);
  const skipAdAppearAfterDefault = useSelector(playerSelectors.skipAdAppearAfterDefaultSelector);

  const inviewAdInterval = useSelector(playerSelectors.inviewAdIntervalSelector);
  const notInviewAdInterval = useSelector(playerSelectors.notInviewAdIntervalSelector);
  const inviewAdIntervalMobile = useSelector(playerSelectors.inviewAdIntervalMobileSelector);
  const notInviewAdIntervalMobile = useSelector(playerSelectors.notInviewAdIntervalMobileSelector);

  const scheme = useSelector(playerSelectors.schemeSelector);

  const showDesktopMonetization = !isAmpTypes(playerType?.id);
  const showMaxAdsPerVideo = !isStoriesTypes(playerType?.id) && !isOutstreamType(playerType?.id);
  const showPreRoll = !isOutstreamType(playerType?.id);
  const showClipNotInViewPlayAds = !isOutstreamType(playerType?.id);

  const shouldShowPrerollOnly = isStoriesTypes(playerType?.id) || isVerticalType(playerType?.id);

  const handleSetState = (state) => dispatch(setAction(state));
  const [confirmationDialog, setConfirmationDialog] = useState(null);
  const [pendingFirstAdDelay, setPendingFirstAdDelay] = useState(null);

  const handleConfirm = () => {
    if (confirmationDialog?.type === 'FIRST_AD_DELAY') {
      handleSetState({ firstAdRequestDelay: pendingFirstAdDelay });
      setPendingFirstAdDelay(null);
    }

    if (confirmationDialog?.type === 'DISABLE_NOT_INVIEW_ADS') {
      handleSetState({
        clipNotInViewPlayAdsDesktop: 0,
        clipNotInViewPlayAdsMobile: 0,
      });
    }

    setConfirmationDialog(null);
  };

  const handleCancel = () => {
    setConfirmationDialog(null);
  };

  return (
    <>
      <FormSection>
        {showDesktopMonetization && (
          <FormRow label="Desktop Monetization" fullWidth>
            <FormRowItem itemsInRow={4}>
              <Switch
                color="primary"
                size={size}
                checked={adManagerDesktop === VIDEO_MONETIZATION_ENABLED}
                onChange={({ target }) =>
                  handleSetState({
                    adManagerDesktop: target.checked ? VIDEO_MONETIZATION_ENABLED : VIDEO_MONETIZATION_DISABLED,
                    fallbackDisplayMonetizationDesktop: target.checked || fallbackDisplayMonetizationDesktop,
                  })
                }
              />
            </FormRowItem>
            {adManagerDesktop === VIDEO_MONETIZATION_ENABLED && (
              <Stack fullWidth className={styles.InRowFormRowRoot}>
                <FormRow
                  fullWidth
                  label="Desktop Display Fallback Ads"
                  tooltip="When enabled, the player will attempt to show display ads (in a video-like format) as fallback pre-roll or mid-roll ads whenever a video ad auction results in no fill."
                >
                  <Switch
                    color="primary"
                    size={size}
                    checked={!!fallbackDisplayMonetizationDesktop}
                    onChange={({ target }) =>
                      handleSetState({
                        fallbackDisplayMonetizationDesktop: target.checked,
                      })
                    }
                  />
                </FormRow>
              </Stack>
            )}
          </FormRow>
        )}
        <FormRow label="Mobile Monetization" fullWidth>
          <FormRowItem itemsInRow={4}>
            <Switch
              color="primary"
              size={size}
              checked={adManagerMobile === VIDEO_MONETIZATION_ENABLED}
              onChange={({ target }) =>
                handleSetState({
                  adManagerMobile: target.checked ? VIDEO_MONETIZATION_ENABLED : VIDEO_MONETIZATION_DISABLED,
                  fallbackDisplayMonetizationMobile: target.checked || fallbackDisplayMonetizationMobile,
                })
              }
            />
          </FormRowItem>
          {adManagerMobile === VIDEO_MONETIZATION_ENABLED && (
            <Stack fullWidth className={styles.InRowFormRowRoot}>
              <FormRow
                label="Mobile Display Fallback Ads"
                tooltip="When enabled, the player will attempt to show display ads (in a video-like format) as fallback pre-roll or mid-roll ads whenever a video ad auction results in no fill."
              >
                <Switch
                  color="primary"
                  size={size}
                  checked={!!fallbackDisplayMonetizationMobile}
                  onChange={({ target }) =>
                    handleSetState({
                      fallbackDisplayMonetizationMobile: target.checked,
                    })
                  }
                />
              </FormRow>
            </Stack>
          )}
        </FormRow>
        {showClipNotInViewPlayAds && (
          <FormRow label="Play Ads when Player is Not-Inview">
            <Switch
              color="primary"
              size={size}
              checked={!!(clipNotInViewPlayAdsDesktop && clipNotInViewPlayAdsMobile)}
              onChange={({ target }) => {
                if (!target.checked) {
                  if (clipNotInViewPlayAdsDesktop && clipNotInViewPlayAdsMobile) {
                    setConfirmationDialog({
                      title: 'Disable non-viewable Video Ads',
                      primary:
                        'Disabling non-viewable video ads will significantly reduce the revenue generated by this player by limiting ad delivery when the player is not in view.',
                      secondary: 'Please consult your dedicated Account Manager before proceeding.',
                      important: true,
                      type: 'DISABLE_NOT_INVIEW_ADS',
                    });
                  }
                } else {
                  handleSetState({
                    clipNotInViewPlayAdsDesktop: target.checked ? 1 : 0,
                    clipNotInViewPlayAdsMobile: target.checked ? 1 : 0,
                  });
                }
              }}
            />
          </FormRow>
        )}
        {showMaxAdsPerVideo && (
          <FormRow label="Max ads per Video">
            <Switch
              color="primary"
              size={size}
              checked={!!maxAdsPerClipChecked}
              onChange={({ target }) =>
                handleSetState({
                  maxAdsPerClipChecked: target.checked ? 1 : 0,
                })
              }
            />
            <Select
              size={size}
              disabled={!maxAdsPerClipChecked}
              value={maxAdsPerClip}
              onChange={({ target }) =>
                handleSetState({
                  maxAdsPerClip: target.value,
                })
              }
            >
              {maxAdsPerClipOptions.map((count) => (
                <MenuItem key={`${count}`} value={count}>
                  {count}
                </MenuItem>
              ))}
            </Select>
          </FormRow>
        )}
        {shouldShowPrerollOnly && (
          <FormRow
            label="Pre-Roll Only Every"
            tooltip="When enabled, the player will serve only preroll ads while in a viewable state, at a fixed interval of clips as defined here. For the best user experience, it is strongly recommended to enable this setting alongside 'True Pre-Roll'."
          >
            <Switch
              color="primary"
              size={size}
              checked={!!prerollOnly}
              onChange={({ target }) => {
                handleSetState({
                  prerollOnly: target.checked,
                });
              }}
            />
            <Select
              shape="rounded"
              size={size}
              variant="outlined"
              value={prerollOnlyClipsCount}
              onChange={({ target }) => handleSetState({ prerollOnlyClipsCount: target.value })}
              disabled={!prerollOnly}
            >
              {clipOptions.map(({ value, label }) => (
                <MenuItem key={value} value={value}>
                  {label}
                </MenuItem>
              ))}
            </Select>
          </FormRow>
        )}
        {showPreRoll && (
          <FormRow
            label=" “True Pre-Roll” Timeout (ms)"
            tooltip="Set the duration the player will wait for a Pre-roll Ad before starting the video. During this time,
            a loading spinner will be displayed until an Ad is available or the timeout is reached."
          >
            <Switch
              color="primary"
              size={size}
              checked={!!preRoll}
              onChange={({ target }) => {
                handleSetState({
                  preRoll: target.checked ? 1 : 0,
                  ...(!target.checked && {
                    preRollWaitMs: preRollOptions.preRollWaitMs.defaultValue,
                  }),
                });
                if (!target.checked) {
                  dispatch(removeErrorByPropAction(['preRollWaitMs']));
                }
              }}
            />
            <TextField
              size={size}
              disabled={!preRoll}
              value={preRollWaitMs}
              onChange={({ target }) => handleSetState({ preRollWaitMs: target.value })}
              onBlur={({ target }) => handleSetState({ preRollWaitMs: castToInt(target.value) })}
              {...getInputPropsByName(scheme, ['preRollWaitMs'], preRoll ? 'Required' : '')}
              onFocus={() => dispatch(removeErrorByPropAction(['preRollWaitMs']))}
            />
          </FormRow>
        )}
        <FormRow
          label="First Ad Request Delay (ms)"
          tooltip={
            <>
              <Typography variant="caption" component="div">
                This setting enables you to introduce a delay, in milliseconds, for the first ad request when playing
                the initial video. Use this feature if you prefer to include only midroll ads in the first video.
                Examples:
              </Typography>
              <List listStyle="initial" disablePadding dense>
                <ListItem disablePadding dense>
                  0 milliseconds: Immediate ad request with the start of the video.
                </ListItem>
                <ListItem disablePadding dense>
                  5000 milliseconds: 5-second delay before the first ad request.
                </ListItem>
              </List>
            </>
          }
        >
          <TextField
            size={size}
            value={firstAdRequestDelay}
            onChange={({ target }) => {
              if (!firstAdRequestDelay && target.value && target.value !== '0') {
                setPendingFirstAdDelay(target.value);
                setConfirmationDialog({
                  title: 'Apply First Ad Request Delay',
                  primary:
                    'Applying a first ad request delay may impact monetization, as ad requests will be delayed until the player becomes viewable. This can heavily reduce monetization for players that load below the fold.',
                  secondary: 'For more information, please consult your dedicated Account Manager.',
                  important: false,
                  type: 'FIRST_AD_DELAY',
                });
              } else {
                handleSetState({ firstAdRequestDelay: target.value });
              }
            }}
            onBlur={({ target }) => handleSetState({ firstAdRequestDelay: castToInt(target.value) })}
            {...getInputPropsByName(scheme, ['firstAdRequestDelay'])}
            onFocus={() => dispatch(removeErrorByPropAction(['firstAdRequestDelay']))}
          />
        </FormRow>
        <FormRow
          label="Ad Indicator"
          tooltip="Text that appear at the top right of the player indicating that Ad is playing."
        >
          <Switch
            color="primary"
            size={size}
            checked={!!adIndicator}
            onChange={({ target }) =>
              handleSetState({
                adIndicator: target.checked ? 1 : 0,
              })
            }
          />
        </FormRow>
        {!!adIndicator && (
          <FormGroup>
            <FormRow label="Ad Indicator Text">
              <TextField
                size={size}
                disabled={!adIndicator}
                variant="outlined"
                value={adIndicatorText}
                onChange={({ target }) =>
                  handleSetState({
                    adIndicatorText: target.value,
                  })
                }
              />
            </FormRow>
          </FormGroup>
        )}
        <FormRow label="Skip Ad Button">
          <Switch
            color="primary"
            size={size}
            checked={!!skipAdButton}
            onChange={({ target }) => {
              handleSetState({
                skipAdButton: target.checked ? 1 : 0,
                ...(!target.checked && {
                  skipAdAppearAfter: skipAdAppearAfterDefault,
                }),
              });
              if (!target.checked) {
                dispatch(removeErrorByPropAction(['skipAdAppearAfter']));
              }
            }}
          />
        </FormRow>
        {!!skipAdButton && (
          <FormGroup>
            <FormRow label="Skip Ad Appears After (ms)">
              <TextField
                size={size}
                disabled={!skipAdButton}
                value={skipAdAppearAfter}
                onChange={({ target }) => handleSetState({ skipAdAppearAfter: target.value })}
                onBlur={({ target }) => handleSetState({ skipAdAppearAfter: castToInt(target.value) })}
                {...getInputPropsByName(scheme, ['skipAdAppearAfter'])}
                onFocus={() => dispatch(removeErrorByPropAction(['skipAdAppearAfter']))}
              />
            </FormRow>
          </FormGroup>
        )}
        <FormGroupTitle>Mid-Roll Settings</FormGroupTitle>
        <FormRow fullWidth>
          <div
            className={classNames(styles.IntervalsList, {
              [styles.IntervalsList___withDesktop]: showDesktopMonetization,
            })}
          >
            <IntervalsList
              intervalsHeaderName="Mid-Roll Intervals (ms)"
              desktopInViewInterval={inviewAdInterval}
              desktopNotInViewInterval={notInviewAdInterval}
              mobileInViewInterval={inviewAdIntervalMobile}
              mobileNotInViewInterval={notInviewAdIntervalMobile}
              desktopInViewStateName="inviewAdInterval"
              desktopNotInViewStateName="notInviewAdInterval"
              mobileInViewStateName="inviewAdIntervalMobile"
              mobileNotInViewStateName="notInviewAdIntervalMobile"
              showDesktopIntervals={showDesktopMonetization}
            />
          </div>
        </FormRow>
      </FormSection>
      {confirmationDialog && (
        <Dialog open={!!confirmationDialog} onClose={handleCancel} maxWidth="md">
          <DialogTitle onClose={() => setConfirmationDialog(null)}>{confirmationDialog.title}</DialogTitle>
          <DialogContent>
            <Stack gap={1} fullWidth>
              <Typography component="div" variant="body2">
                {confirmationDialog.primary}
              </Typography>
              <Typography
                component="div"
                variant="body2"
                color={confirmationDialog.important ? 'error.main' : 'text.primary'}
                fontWeight={confirmationDialog.important ? 600 : 400}
              >
                {confirmationDialog.secondary}
              </Typography>
            </Stack>
          </DialogContent>
          <DialogActions>
            <Button variant="outlined" color="primary" onClick={handleCancel}>
              Cancel
            </Button>
            <Button variant="contained" color="primary" onClick={handleConfirm}>
              Confirm
            </Button>
          </DialogActions>
        </Dialog>
      )}
    </>
  );
}

export default VideoAdsTab;
