import { useQuery, useMutation, gql } from '@apollo/client'
import DialogActions from '@mui/material/DialogActions'
import IconButton from '@mui/material/IconButton'
import SvgIcon from '@mui/material/SvgIcon'
import * as R from 'ramda'
import React, { useState } from 'react'
import LogsDowloaderPopover from '../../components/LogsDownloaderPopper'
import Modal from '../../components/Modal'
import { HelpTooltip } from '../../components/Tooltip'
import TitleSection from '../../components/layout/TitleSection'
import DataTable from '../../components/tables/DataTable'
import { P, Label1 } from '../../components/typography'
import EditIcon from '../../styling/icons/action/edit/enabled.svg?react'
import ReverseHistoryIcon from '../../styling/icons/circle buttons/history/white.svg?react'
import HistoryIcon from '../../styling/icons/circle buttons/history/zodiac.svg?react'

import { Button, SupportLinkButton } from '../../components/buttons'
import { RadioGroup } from '../../components/inputs'
import { EmptyTable } from '../../components/table'
import { fromNamespace, toNamespace } from '../../utils/config'
import { MANUAL, AUTOMATIC } from '../../utils/constants'
import { onlyFirstToUpper } from '../../utils/string'

import CashUnitDetails from './CashUnitDetails'
import CashCassettesFooter from './CashUnitsFooter'
import CashboxHistory from './CashboxHistory'
import Wizard from './Wizard/Wizard'
import helper from './helper'

const GET_MACHINES_AND_CONFIG = gql`
  query getData($billFilters: JSONObject) {
    machines {
      name
      id: deviceId
      model
      cashUnits {
        cashbox
        cassette1
        cassette2
        cassette3
        cassette4
        recycler1
        recycler2
        recycler3
        recycler4
        recycler5
        recycler6
      }
      numberOfCassettes
      numberOfRecyclers
    }
    unpairedMachines {
      id: deviceId
      name
    }
    config
    bills(filters: $billFilters) {
      id
      fiat
      created
      deviceId
    }
  }
`

const SAVE_CONFIG = gql`
  mutation Save($config: JSONObject) {
    saveConfig(config: $config)
  }
`

const SET_CASSETTE_BILLS = gql`
  mutation MachineAction(
    $deviceId: ID!
    $action: MachineAction!
    $cashUnits: CashUnitsInput
  ) {
    machineAction(deviceId: $deviceId, action: $action, cashUnits: $cashUnits) {
      deviceId
      cashUnits {
        cashbox
        cassette1
        cassette2
        cassette3
        cassette4
        recycler1
        recycler2
        recycler3
        recycler4
        recycler5
        recycler6
      }
    }
  }
`

const GET_BATCHES_CSV = gql`
  query cashboxBatchesCsv(
    $from: DateTimeISO
    $until: DateTimeISO
    $timezone: String
  ) {
    cashboxBatchesCsv(from: $from, until: $until, timezone: $timezone)
  }
`

const widths = {
  name: 250,
  cashbox: 200,
  cassettes: 575,
  edit: 90,
}

const CashCassettes = () => {
  const [showHistory, setShowHistory] = useState(false)
  const [editingSchema, setEditingSchema] = useState(null)
  const [selectedRadio, setSelectedRadio] = useState(null)

  const { data, loading: dataLoading } = useQuery(GET_MACHINES_AND_CONFIG, {
    variables: {
      billFilters: {
        batch: 'none',
      },
    },
  })
  const [wizard, setWizard] = useState(false)
  const [machineId, setMachineId] = useState('')

  const machines = R.path(['machines'])(data) ?? []
  const unpairedMachines = R.path(['unpairedMachines'])(data) ?? []
  const config = R.path(['config'])(data) ?? {}
  const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
    refetchQueries: () => ['getData'],
  })
  const [saveConfig] = useMutation(SAVE_CONFIG, {
    onCompleted: () => setEditingSchema(false),
    refetchQueries: () => ['getData'],
  })

  const timezone = R.path(['config', 'locale_timezone'], data)

  const bills = R.groupBy(bill => bill.deviceId)(R.path(['bills'])(data) ?? [])
  const deviceIds = R.uniq(
    R.map(R.prop('deviceId'))(R.path(['bills'])(data) ?? []),
  )
  const cashout = data?.config && fromNamespace('cashOut')(data.config)
  const locale = data?.config && fromNamespace('locale')(data.config)
  const fiatCurrency = locale?.fiatCurrency

  const getCashoutSettings = id => fromNamespace(id)(cashout)

  const onSave = (id, cashUnits) => {
    return setCassetteBills({
      variables: {
        action: 'setCassetteBills',
        deviceId: id,
        cashUnits,
      },
    })
  }

  const cashboxReset =
    data?.config && fromNamespace('cashIn')(data.config).cashboxReset

  const cashboxResetSave = rawConfig => {
    const config = toNamespace('cashIn')(rawConfig)
    return saveConfig({ variables: { config } })
  }

  const saveCashboxOption = selection => {
    if (selection) {
      cashboxResetSave({ cashboxReset: selection })
      setEditingSchema(false)
    }
  }

  const radioButtonOptions = [
    { display: 'Automatic', code: AUTOMATIC },
    { display: 'Manual', code: MANUAL },
  ]

  const handleRadioButtons = evt => {
    const selectedRadio = R.path(['target', 'value'])(evt)
    setSelectedRadio(selectedRadio)
  }

  const elements = helper.getElements(
    config,
    bills,
    setWizard,
    widths,
    setMachineId,
  )

  const InnerCashUnitDetails = ({ it }) => (
    <CashUnitDetails
      machine={it}
      bills={bills[it.id] ?? []}
      currency={fiatCurrency}
      config={config}
    />
  )

  return (
    !dataLoading && (
      <>
        <TitleSection
          title="Cash boxes & cassettes"
          buttons={[
            {
              text: 'Cash box history',
              icon: HistoryIcon,
              inverseIcon: ReverseHistoryIcon,
              toggle: setShowHistory,
            },
            {
              component: showHistory ? (
                <LogsDowloaderPopover
                  className="ml-4"
                  title="Download logs"
                  name="cashboxHistory"
                  query={GET_BATCHES_CSV}
                  getLogs={logs => R.path(['cashboxBatchesCsv'])(logs)}
                  timezone={timezone}
                  args={{ timezone }}
                />
              ) : (
                <></>
              ),
            },
          ]}
          className="flex items-center mr-[1px]"
          appendix={
            <HelpTooltip width={220}>
              <P>
                For details on configuring cash boxes and cassettes, please read
                the relevant knowledgebase article:
              </P>
              <SupportLinkButton
                link="https://support.lamassu.is/hc/en-us/articles/4420839641229-Cash-Boxes-Cassettess"
                label="Cash Boxes & Cassettes"
                bottomSpace="1"
              />
            </HelpTooltip>
          }>
          {!showHistory && (
            <div className="flex flex-col items-end">
              <Label1 noMargin className="text-comet">
                Cash box resets
              </Label1>
              <div className="flex items-center justify-end -mr-1">
                {cashboxReset && (
                  <P noMargin className="mr-2">
                    {onlyFirstToUpper(cashboxReset)}
                  </P>
                )}
                <IconButton onClick={() => setEditingSchema(true)}>
                  <SvgIcon>
                    <EditIcon />
                  </SvgIcon>
                </IconButton>
              </div>
            </div>
          )}
        </TitleSection>
        {!showHistory && (
          <>
            <DataTable
              loading={dataLoading}
              elements={elements}
              data={machines}
              Details={InnerCashUnitDetails}
              emptyText="No machines so far"
              expandable
              tableClassName="mb-20"
            />

            {data && R.isEmpty(machines) && (
              <EmptyTable message="No machines so far" />
            )}
          </>
        )}
        {showHistory && (
          <CashboxHistory
            machines={R.concat(machines, unpairedMachines)}
            currency={fiatCurrency}
            timezone={timezone}
          />
        )}
        <CashCassettesFooter
          currencyCode={fiatCurrency}
          machines={machines}
          config={config}
          bills={R.path(['bills'])(data)}
          deviceIds={deviceIds}
        />
        {wizard && (
          <Wizard
            machine={R.find(R.propEq('id', machineId), machines)}
            cashoutSettings={getCashoutSettings(machineId)}
            onClose={() => {
              setWizard(false)
            }}
            error={error?.message}
            save={onSave}
            locale={locale}
          />
        )}
        {editingSchema && (
          <Modal
            title={'Cash box resets'}
            width={478}
            handleClose={() => setEditingSchema(null)}
            open={true}>
            <P className="text-comet mt-0">
              We can automatically assume you emptied a bill validator's cash
              box when the machine detects that it has been removed.
            </P>
            <RadioGroup
              name="set-automatic-reset"
              value={selectedRadio ?? cashboxReset}
              options={[radioButtonOptions[0]]}
              onChange={handleRadioButtons}
            />
            <P className="text-comet mt-0">
              Assume the cash box is emptied whenever it's removed, creating a
              new batch on the history screen and setting its current balance to
              zero.
            </P>
            <RadioGroup
              name="set-manual-reset"
              value={selectedRadio ?? cashboxReset}
              options={[radioButtonOptions[1]]}
              onChange={handleRadioButtons}
            />
            <P className="text-comet mt-0">
              Cash boxes won't be assumed emptied when removed, nor their counts
              modified. Instead, to update the count and create a new batch,
              you'll click the 'Edit' button on this panel.
            </P>
            <DialogActions>
              <Button onClick={() => saveCashboxOption(selectedRadio)}>
                Confirm
              </Button>
            </DialogActions>
          </Modal>
        )}
      </>
    )
  )
}

export default CashCassettes
