import React, { useEffect, useState, forwardRef } from 'react'
import Card from '@mui/material/Card/index.js'
import CardHeader from '@mui/material/CardHeader/index.js'
import CardContent from '@mui/material/CardContent/index.js'
import Button from '@mui/material/Button/index.js'
import TextField from '@mui/material/TextField/index.js'

import NumberFormat from 'react-number-format'

import { AccountBalanceIcon } from '../PixelIcon/index.js'

import FarmhandContext from '../Farmhand/Farmhand.context.js'
import { moneyString } from '../../utils/moneyString.js'
import { dollarString } from '../../utils/dollarString.js'
import { moneyTotal } from '../../utils/moneyTotal.js'
import {
  STANDARD_LOAN_AMOUNT,
  LOAN_INTEREST_RATE,
  LOAN_GARNISHMENT_RATE,
} from '../../constants.js'
import { Div } from '../Elements/index.js'

type MoneyNumberFormatProps = {
  max: number
  min: number
  onChange: (v: number) => void
  setLoanInputValue?: React.Dispatch<React.SetStateAction<number>>
} & Record<string, unknown>

const MoneyNumberFormat = forwardRef<HTMLInputElement, any>(
  (props: any, ref) => {
    const {
      max,
      min,
      onChange,
      setLoanInputValue,
      ...rest
    }: MoneyNumberFormatProps = props

    return (
      <NumberFormat
        fixedDecimalScale
        thousandSeparator
        getInputRef={ref}
        {...{
          ...rest,
          allowNegative: false,
          decimalScale: 2,
          prefix: '$',
          isAllowed: ({ floatValue = 0 }) => min >= 0 && floatValue <= max,
          onValueChange: ({ floatValue = 0 }) => onChange(floatValue),
        }}
      />
    )
  }
)

interface AccountingViewProps {
  handleClickLoanPaydownButton: (amount: number) => void
  handleClickTakeOutLoanButton: (amount: number) => void
  loanBalance: number
  money: number
}

const AccountingView = ({
  handleClickLoanPaydownButton,
  handleClickTakeOutLoanButton,
  loanBalance,
  money,
}: AccountingViewProps) => {
  const [loanInputValue, setLoanInputValue] = useState(
    Math.min(loanBalance, money)
  )

  useEffect(
    () => setLoanInputValue(Math.min(loanBalance, money)),
    [loanBalance, money]
  )

  return (
    <Div className="AccountingView">
      <Card sx={{ '& .MuiCardContent-root': { paddingTop: 0 } }}>
        <CardHeader
          {...{
            avatar: <AccountBalanceIcon />,
            title: 'Loan Balance',
            subheader: <p>{moneyString(loanBalance)}</p>,
          }}
        />
        <CardContent>
          <Div
            className="loan-container"
            sx={{
              '& p': { margin: '1em 0' },
              '& button': { margin: '1em' },
            }}
          >
            <TextField
              variant="standard"
              {...{
                value: loanInputValue,
                inputProps: {
                  max: loanBalance,
                  min: 0,

                  // Enable a helpful number input for iOS.
                  // https://css-tricks.com/finger-friendly-numerical-inputs-with-inputmode/
                  pattern: '[0-9]*',
                },

                onChange: value => {
                  // NOTE: value is naturally a number here, but it must be cast explicitly to work around an unhelpful type definition
                  setLoanInputValue(Number(value))
                },
                InputProps: {
                  inputComponent: MoneyNumberFormat,
                },
              }}
            />
            <Button
              {...{
                color: 'primary',
                disabled: loanBalance === 0,
                variant: 'contained',
                onClick: () => {
                  handleClickLoanPaydownButton(loanInputValue)
                  setLoanInputValue(loanBalance - loanInputValue)
                },
              }}
            >
              Pay into loan
            </Button>
            <p>
              You may take out a Hardship Assistance Loan if your funds fall
              below {dollarString(STANDARD_LOAN_AMOUNT)}. So long as you have an
              outstanding loan balance, all farm product sales are garnished by{' '}
              {LOAN_GARNISHMENT_RATE * 100}% until the loan is repaid. The loan
              interest rate is {LOAN_INTEREST_RATE * 100}% per day, compounded
              daily.
            </p>
          </Div>
          <Button
            {...{
              color: 'error',
              disabled: money >= STANDARD_LOAN_AMOUNT,
              onClick: () => {
                handleClickTakeOutLoanButton(STANDARD_LOAN_AMOUNT)
                setLoanInputValue(
                  Math.min(
                    moneyTotal(loanInputValue, STANDARD_LOAN_AMOUNT),
                    moneyTotal(money, STANDARD_LOAN_AMOUNT)
                  )
                )
              },
              variant: 'contained',
            }}
          >
            Take out a {dollarString(STANDARD_LOAN_AMOUNT)} loan
          </Button>
        </CardContent>
      </Card>
    </Div>
  )
}

export default function Consumer(props: Partial<AccountingViewProps>) {
  return (
    <FarmhandContext.Consumer>
      {({ gameState, handlers }) => (
        <AccountingView {...{ ...gameState, ...handlers, ...props }} />
      )}
    </FarmhandContext.Consumer>
  )
}
