import { usePrivateUser } from 'web/hooks/use-user'
import React, { ReactNode, useEffect, useState } from 'react'
import { LoadingIndicator } from 'web/components/loading-indicator'
import { Row } from 'web/components/layout/row'
import clsx from 'clsx'
import {
  notification_subscription_types,
  notification_destination_types,
} from 'common/user'
import { updatePrivateUser } from 'web/lib/firebase/users'
import { Col } from 'web/components/layout/col'
import {
  CashIcon,
  ChatIcon,
  ChevronDownIcon,
  ChevronUpIcon,
  CurrencyDollarIcon,
  InboxInIcon,
  InformationCircleIcon,
  LightBulbIcon,
  TrendingUpIcon,
  UserIcon,
  UsersIcon,
} from '@heroicons/react/outline'
import { WatchMarketModal } from 'web/components/contract/watch-market-modal'
import { filterDefined } from 'common/util/array'
import toast from 'react-hot-toast'
import { SwitchSetting } from 'web/components/switch-setting'

export function NotificationSettings(props: {
  navigateToSection: string | undefined
}) {
  const { navigateToSection } = props
  const privateUser = usePrivateUser()
  const [showWatchModal, setShowWatchModal] = useState(false)

  if (!privateUser || !privateUser.notificationSubscriptionTypes) {
    return <LoadingIndicator spinnerClassName={'border-gray-500 h-4 w-4'} />
  }

  const emailsEnabled: Array<keyof notification_subscription_types> = [
    'all_comments_on_watched_markets',
    'all_replies_to_my_comments_on_watched_markets',
    'all_comments_on_contracts_with_shares_in_on_watched_markets',

    'all_answers_on_watched_markets',
    'all_replies_to_my_answers_on_watched_markets',
    'all_answers_on_contracts_with_shares_in_on_watched_markets',

    'your_contract_closed',
    'all_comments_on_my_markets',
    'all_answers_on_my_markets',

    'resolutions_on_watched_markets_with_shares_in',
    'resolutions_on_watched_markets',

    'trending_markets',
    'onboarding_flow',
    'thank_you_for_purchases',

    // TODO: add these
    'tagged_user',
    // 'contract_from_followed_user',
    // 'referral_bonuses',
    // 'unique_bettors_on_your_contract',
    // 'on_new_follow',
    // 'profit_loss_updates',
    // 'tips_on_your_markets',
    // 'tips_on_your_comments',
    // maybe the following?
    // 'probability_updates_on_watched_markets',
    // 'limit_order_fills',
  ]
  const browserDisabled: Array<keyof notification_subscription_types> = [
    'trending_markets',
    'profit_loss_updates',
    'onboarding_flow',
    'thank_you_for_purchases',
  ]

  type sectionData = {
    label: string
    subscriptionTypeToDescription: {
      [key in keyof Partial<notification_subscription_types>]: string
    }
  }

  const comments: sectionData = {
    label: 'New Comments',
    subscriptionTypeToDescription: {
      all_comments_on_watched_markets: 'All new comments',
      all_comments_on_contracts_with_shares_in_on_watched_markets: `Only on markets you're invested in`,
      all_replies_to_my_comments_on_watched_markets:
        'Only replies to your comments',
      // comments_by_followed_users_on_watched_markets: 'By followed users',
    },
  }

  const answers: sectionData = {
    label: 'New Answers',
    subscriptionTypeToDescription: {
      all_answers_on_watched_markets: 'All new answers',
      all_answers_on_contracts_with_shares_in_on_watched_markets: `Only on markets you're invested in`,
      all_replies_to_my_answers_on_watched_markets:
        'Only replies to your answers',
      // answers_by_followed_users_on_watched_markets: 'By followed users',
      // answers_by_market_creator_on_watched_markets: 'By market creator',
    },
  }
  const updates: sectionData = {
    label: 'Updates & Resolutions',
    subscriptionTypeToDescription: {
      market_updates_on_watched_markets: 'All creator updates',
      market_updates_on_watched_markets_with_shares_in: `Only creator updates on markets you're invested in`,
      resolutions_on_watched_markets: 'All market resolutions',
      resolutions_on_watched_markets_with_shares_in: `Only market resolutions you're invested in`,
      // probability_updates_on_watched_markets: 'Probability updates',
    },
  }
  const yourMarkets: sectionData = {
    label: 'Markets You Created',
    subscriptionTypeToDescription: {
      your_contract_closed: 'Your market has closed (and needs resolution)',
      all_comments_on_my_markets: 'Comments on your markets',
      all_answers_on_my_markets: 'Answers on your markets',
      subsidized_your_market: 'Your market was subsidized',
      tips_on_your_markets: 'Likes on your markets',
    },
  }
  const bonuses: sectionData = {
    label: 'Bonuses',
    subscriptionTypeToDescription: {
      betting_streaks: 'Betting streak bonuses',
      referral_bonuses: 'Referral bonuses from referring users',
      unique_bettors_on_your_contract: 'Unique bettor bonuses on your markets',
    },
  }
  const otherBalances: sectionData = {
    label: 'Other',
    subscriptionTypeToDescription: {
      loan_income: 'Automatic loans from your profitable bets',
      limit_order_fills: 'Limit order fills',
      tips_on_your_comments: 'Tips on your comments',
    },
  }
  const userInteractions: sectionData = {
    label: 'Users',
    subscriptionTypeToDescription: {
      tagged_user: 'A user tagged you',
      on_new_follow: 'Someone followed you',
      contract_from_followed_user: 'New markets created by users you follow',
    },
  }
  const generalOther: sectionData = {
    label: 'Other',
    subscriptionTypeToDescription: {
      trending_markets: 'Weekly interesting markets',
      thank_you_for_purchases: 'Thank you notes for your purchases',
      onboarding_flow: 'Explanatory emails to help you get started',
      // profit_loss_updates: 'Weekly profit/loss updates',
    },
  }

  const NotificationSettingLine = (
    description: string,
    key: keyof notification_subscription_types,
    value: notification_destination_types[]
  ) => {
    const previousInAppValue = value.includes('browser')
    const previousEmailValue = value.includes('email')
    const [inAppEnabled, setInAppEnabled] = useState(previousInAppValue)
    const [emailEnabled, setEmailEnabled] = useState(previousEmailValue)
    const loading = 'Changing Notifications Settings'
    const success = 'Changed Notification Settings!'
    const highlight = navigateToSection === key

    useEffect(() => {
      if (
        inAppEnabled !== previousInAppValue ||
        emailEnabled !== previousEmailValue
      ) {
        toast.promise(
          updatePrivateUser(privateUser.id, {
            notificationSubscriptionTypes: {
              ...privateUser.notificationSubscriptionTypes,
              [key]: filterDefined([
                inAppEnabled ? 'browser' : undefined,
                emailEnabled ? 'email' : undefined,
              ]),
            },
          }),
          {
            success,
            loading,
            error: 'Error changing notification settings. Try again?',
          }
        )
      }
    }, [
      inAppEnabled,
      emailEnabled,
      previousInAppValue,
      previousEmailValue,
      key,
    ])

    return (
      <Row
        className={clsx(
          'my-1 gap-1 text-gray-300',
          highlight ? 'rounded-md bg-indigo-100 p-1' : ''
        )}
      >
        <Col className="ml-3 gap-2 text-sm">
          <Row className="gap-2 font-medium text-gray-700">
            <span>{description}</span>
          </Row>
          <Row className={'gap-4'}>
            {!browserDisabled.includes(key) && (
              <SwitchSetting
                checked={inAppEnabled}
                onChange={setInAppEnabled}
                label={'Website'}
              />
            )}
            {emailsEnabled.includes(key) && (
              <SwitchSetting
                checked={emailEnabled}
                onChange={setEmailEnabled}
                label={'Email'}
              />
            )}
          </Row>
        </Col>
      </Row>
    )
  }

  const getUsersSavedPreference = (
    key: keyof notification_subscription_types
  ) => {
    return privateUser.notificationSubscriptionTypes[key] ?? []
  }

  const Section = (icon: ReactNode, data: sectionData) => {
    const { label, subscriptionTypeToDescription } = data
    const expand =
      navigateToSection &&
      Object.keys(subscriptionTypeToDescription).includes(navigateToSection)
    const [expanded, setExpanded] = useState(expand)

    // Not working as the default value for expanded, so using a useEffect
    useEffect(() => {
      if (expand) setExpanded(true)
    }, [expand])

    return (
      <Col className={clsx('ml-2 gap-2')}>
        <Row
          className={'mt-1 cursor-pointer items-center gap-2 text-gray-600'}
          onClick={() => setExpanded(!expanded)}
        >
          {icon}
          <span>{label}</span>

          {expanded ? (
            <ChevronUpIcon className="h-5 w-5 text-xs text-gray-500">
              Hide
            </ChevronUpIcon>
          ) : (
            <ChevronDownIcon className="h-5 w-5 text-xs text-gray-500">
              Show
            </ChevronDownIcon>
          )}
        </Row>
        <Col className={clsx(expanded ? 'block' : 'hidden', 'gap-2 p-2')}>
          {Object.entries(subscriptionTypeToDescription).map(([key, value]) =>
            NotificationSettingLine(
              value,
              key as keyof notification_subscription_types,
              getUsersSavedPreference(
                key as keyof notification_subscription_types
              )
            )
          )}
        </Col>
      </Col>
    )
  }

  return (
    <div className={'p-2'}>
      <Col className={'gap-6'}>
        <Row className={'gap-2 text-xl text-gray-700'}>
          <span>Notifications for Watched Markets</span>
          <InformationCircleIcon
            className="-mb-1 h-5 w-5 cursor-pointer text-gray-500"
            onClick={() => setShowWatchModal(true)}
          />
        </Row>
        {Section(<ChatIcon className={'h-6 w-6'} />, comments)}
        {Section(<LightBulbIcon className={'h-6 w-6'} />, answers)}
        {Section(<TrendingUpIcon className={'h-6 w-6'} />, updates)}
        {Section(<UserIcon className={'h-6 w-6'} />, yourMarkets)}
        <Row className={'gap-2 text-xl text-gray-700'}>
          <span>Balance Changes</span>
        </Row>
        {Section(<CurrencyDollarIcon className={'h-6 w-6'} />, bonuses)}
        {Section(<CashIcon className={'h-6 w-6'} />, otherBalances)}
        <Row className={'gap-2 text-xl text-gray-700'}>
          <span>General</span>
        </Row>
        {Section(<UsersIcon className={'h-6 w-6'} />, userInteractions)}
        {Section(<InboxInIcon className={'h-6 w-6'} />, generalOther)}
        <WatchMarketModal open={showWatchModal} setOpen={setShowWatchModal} />
      </Col>
    </div>
  )
}
