import React from 'react'

import { type BreadcrumbType } from '../Breadcrumbs/Common/BreadcrumbTypes'
import { getEnvironmentName } from '../../services/apiEndpointHelpers'
import { type IconStringList } from '../Icons/Icon.models'
import { useMediaQuery } from '../../hooks/responsiveHooks'
import { type AccountPopoverProps } from '../AccountPopover/AccountPopover'
import commonStyles from './Common/_left-nav-common.module.scss'
import LeftNavDesktop from './Desktop/LeftNavDesktop'
import LeftNavMobile from './Mobile/LeftNavMobile'
import { type LanguageSelectorProps } from './Common/LanguageSelector/LanguageSelector'

export type LeftNavLinkObj = {
  /** The url for the page associated with this link */
  link: string
  /** The icon that will appear to the left of the SidebarLink name */
  icon: IconStringList
  /** The SidebarLink name */
  name: string
  /** Optional permissions needed to view this SidebarLink */
  permissions?: string[]
  /** Optional property - designates a link as a footer link */
  footerLink?: boolean
  /** Optional property for exact match of url with breadcrumb link */
  exactLinkMatch?: boolean
}

export type LeftNavProps = {
  /** The logo will appear in the Sidebar header */
  logo: {
    /** The logo image url needed to display the logo */
    url: string
    /** The Abbreviated image url */
    abbreviatedUrl?: string
    /** The Isolated image url  **/
    isolatedUrl?: string
    /** Optional maximum height for the logo */
    maxHeight?: string | number
  }
  /** The array of leftNavLinks */
  leftNavLinks?: LeftNavLinkObj[]
  /** The array of Breadcrumbs */
  breadcrumbs: BreadcrumbType[]
  /** Props for populating the account popover in the footer */
  accountPopoverProps: Omit<
    AccountPopoverProps,
    'expanded' | 'closeMobileDrawer'
  >
  /** Component to use for routing. We need this to be defined in each application using the LeftNav. */
  routerComponent: React.ElementType
  /** Prop to use for routing within the routerComponent. We need this to be defined in each application using the LeftNav. */
  routerProp: string
  /** User permission list */
  userPermissions: string[]
  /** Function to navigate to the homepage */
  navigate: () => void
  /** Footer element */
  footer?: ({
    sidebarExpanded,
  }: {
    sidebarExpanded: boolean
  }) => React.JSX.Element
  mobileProps?: {
    /** Optionally pass in children elements to the mobile header. */
    mobileHeaderChildren?: React.ReactNode
    /** Optionally place the hamburger menu to the right instead of the default left corner. */
    rightHamburgerMenu?: boolean
  }
  /** Optional prop to correctly calculate the height of the desktop sidebar. This is used in instances where there is an element above or below the sidebar. i.e. A banner above the application. */
  heightOffset?: number
  /** This prop will determine which environment the user is seeing the Sidebar. This will provide visual queues to the user so they can quickly know which environment they are in. */
  environment?: 'development' | 'staging' | 'demo' | 'production'
  /** Optional prop to configure language settings */
  languageConfig?: Omit<LanguageSelectorProps, 'expanded'>
  /** Optional prop to hide the logo */
  hideLogo?: boolean
  /** Optional prop to hide the copyright */
  hideCopyright?: boolean
  /** Optional prop to add a test id to the LeftNav for QA testing */
  qaTestId?: string
  /** Optional prop to match a specific link segment index to the breadcrumb link */
  linkSegmentIndexToMatch?: number
}

function getEnvForToggle(): LeftNavProps['environment'] {
  const environmentName = getEnvironmentName()
  if (environmentName === 'stage') {
    return 'staging'
  }
  return environmentName
}

// NOTE: This function filters out links if the user does not have the correct permissions to view them.
const MenuFilter = (leftNavLinks: LeftNavLinkObj[], permissions: string[]) => {
  const filteredLinks = leftNavLinks.filter((link) => {
    if (!link.permissions) {
      return true
    }

    return link.permissions.some((permission) =>
      permissions.includes(permission),
    )
  })

  return filteredLinks
}

const LeftNav = (props: LeftNavProps): React.JSX.Element => {
  const isMobile = useMediaQuery({ type: 'max', breakpoint: 'md' })
  const { leftNavLinks, userPermissions } = props
  const parsedLinks = MenuFilter(
    leftNavLinks ? leftNavLinks : [],
    userPermissions,
  )

  const leftNavProps = {
    // We want environment defined first so that an app has the option to override the environment prop.
    environment: getEnvForToggle(),
    ...props,
    // We want leftNavLinks to be the parsedLinks so it needs to be last.
    leftNavLinks: parsedLinks,
  }

  return isMobile ? (
    <LeftNavMobile {...leftNavProps} />
  ) : (
    <LeftNavDesktop {...leftNavProps} />
  )
}

const Divider = () => <div className={commonStyles.divider} />

LeftNav.Divider = Divider

export { LeftNav }
