import React, { FC, useCallback, useEffect, useRef, useState } from 'react'
import { InputControl, Text, Badge } from '@wordpress/ui'
import { ServiceIcon } from '@mybring/iconsystem'
import { Button, Notice, Popover } from '@wordpress/components'
import { Icon, pencil } from '@wordpress/icons'
import {
  MybringCustomerAndServices,
  Order,
  ServiceDetails,
} from '../model/models'
import ShippingOptionSelector from './ShippingOptionSelector'
import apiFetch from '@wordpress/api-fetch'
import { useI18n } from '@wordpress/react-i18n'
import OrderListDetails from './OrderListDetails'
import { sprintf } from '@wordpress/i18n'

export declare interface OrderListItemProps {
  order: Order
  mapServiceId: (_: string | undefined) => string | undefined | React.ReactNode
  customers: Array<MybringCustomerAndServices>
  customerNumber?: string
  onSave: (_orderId: string, _?: Order) => void
  error: string | undefined
}

const OrderListItem: FC<OrderListItemProps> = ({
  order,
  customers,
  customerNumber,
  mapServiceId,
  onSave,
  error,
}) => {
  const [editable, setEditable] = React.useState(false)
  const [editedOrder, setEditedOrder] = React.useState<Order>(order)
  const [displayOrderDetails, setDisplayOrderDetails] = useState<boolean>(false)
  const [displayValidationErrors, setDisplayValidationErrors] =
    useState<boolean>(false)
  const [availableServicesForOrder, setAvailableServicesForOrder] = useState<
    Array<ServiceDetails>
  >([])
  const shippingOptionSelectRef = useRef<HTMLSelectElement | null>(null)

  const { __, _nx } = useI18n()

  useEffect(() => {
    if (!editable) {
      setEditedOrder(order)
    }
  }, [order, editable])

  useEffect(() => {
    if (editable) {
      setTimeout(() => shippingOptionSelectRef.current?.focus(), 50)
    }
  }, [editable])

  const getServiceIcon = useCallback((serviceId?: string): string => {
    switch (serviceId) {
      case null:
        return ''
      case '3584':
        return 'serviceicon-mailbox'
      case '5800':
      case '5801':
      case '0340':
      case '0342':
        return 'serviceicon-pointer'
      case '5100':
        return 'serviceicon-crate'
      case '5400':
        return 'serviceicon-crate-on-pallet'
      case '5000':
      case '0330':
      case '0332':
        return 'serviceicon-building'
      default:
        return 'serviceicon-door'
    }
  }, [])

  const onEdit = useCallback(async () => {
    if (availableServicesForOrder.length === 0) {
      setAvailableServicesForOrder(
        await apiFetch({ path: '/posten-bring-checkout/services' })
      )
    }
    setEditable(true)
    shippingOptionSelectRef.current?.focus()
  }, [availableServicesForOrder.length])

  const onChange = (field: string, value: string | number) => {
    if (editedOrder) {
      setEditedOrder({
        ...editedOrder,
        [field]: value,
      })
    }
  }

  const onSaveChanges = () => {
    onSave(order.order_id, editedOrder)
    setEditable(false)
  }

  return (
    <li className="order-list-item" key={order.order_id}>
      <div className="order-list-item__wrapper">
        <div className="order-list-item__content flex align-ic flex-dir-row">
          <div className="pas flex flex-dir-row gas align-ic">
            <div className="flex flex-dir-row gam align-ic">
              <div className="mrxl order-id">
                <Button
                  role="button"
                  onClick={() => setDisplayOrderDetails(visible => !visible)}
                >
                  <Text variant={'heading-xl'}>#{order.order_id}</Text>
                  {displayOrderDetails && (
                    <Popover
                      onClickOutside={() => setDisplayOrderDetails(false)}
                      focusOnMount={false}
                      onClose={() => setDisplayOrderDetails(false)}
                    >
                      <OrderListDetails order={order} />
                    </Popover>
                  )}
                </Button>
              </div>
              {!editable ? (
                <div className="flex flex-dir-row gas align-ic">
                  {order.order_shipping_option ? (
                    <>
                      <ServiceIcon
                        name={getServiceIcon(order.order_shipping_option)}
                        height={26}
                        className="flex"
                      />
                      <div
                        className="mll"
                        style={{ minWidth: '210px' }}
                      >{`${mapServiceId(order.order_shipping_option)} - ${
                        order.total_weight / 1000
                      } kg`}</div>
                    </>
                  ) : (
                    <>
                      {!order.order_validation_errors.some(
                        value => value.bookingDisabled
                      ) && (
                        <div style={{ minWidth: '277px' }}>
                          <Badge intent="medium">
                            {__(
                              'No shipping option selected',
                              'posten-bring-checkout'
                            )}
                          </Badge>
                        </div>
                      )}
                    </>
                  )}
                  {error && (
                    <Notice
                      status="error"
                      isDismissible={false}
                      politeness="assertive"
                    >
                      {__(
                        'An error occurred! We have been notified and are investigating. Please try again later, or contact us via ',
                        'posten-bring-checkout'
                      )}
                      <a
                        href={`mailto:${__(
                          'checkout.implementering@posten.no',
                          'posten-bring-checkout'
                        )}`}
                      >
                        {__(
                          'checkout.implementering@posten.no',
                          'posten-bring-checkout'
                        )}
                      </a>
                    </Notice>
                  )}
                  {!error &&
                  !order.order_validation_errors.some(
                    value => value.bookingDisabled
                  ) ? (
                    <>
                      <Button
                        aria-label={__('Edit', 'posten-bring-checkout')}
                        role="button"
                        variant={'tertiary'}
                        onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
                          e.preventDefault()
                          onEdit()
                        }}
                      >
                        <Icon icon={pencil} />
                      </Button>
                      {order.nvit &&
                        order.items.some(
                          i => i.hs_code == null || i.hs_code === ''
                        ) && (
                          <>
                            <Badge intent="informational">NVIT</Badge>
                            <Badge intent="low">
                              {sprintf(
                                _nx(
                                  '%d item requires an HS code',
                                  '%d items require an HS code',
                                  order.items.filter(
                                    i => i.hs_code == null || i.hs_code === ''
                                  ).length,
                                  'Validation message presented when one or more items requires an HS code and shipment is labelled as an NVIT (Norske varer i transitt) shipment',
                                  'posten-bring-checkout'
                                ),
                                order.items.filter(
                                  i => i.hs_code == null || i.hs_code === ''
                                ).length
                              )}
                            </Badge>
                          </>
                        )}
                    </>
                  ) : (
                    <>
                      {!error && (
                        <Button
                          role="button"
                          variant={'tertiary'}
                          onClick={() =>
                            setDisplayValidationErrors(visible => !visible)
                          }
                        >
                          ⚠️{' '}
                          {__(
                            'View validation errors',
                            'posten-bring-checkout'
                          )}
                          {displayValidationErrors && (
                            <Popover
                              focusOnMount={false}
                              onClickOutside={() =>
                                setDisplayValidationErrors(false)
                              }
                              onFocusOutside={() =>
                                setDisplayValidationErrors(false)
                              }
                              placement={'bottom-start'}
                            >
                              <div
                                style={{ padding: '.5rem', minWidth: '300px' }}
                              >
                                <Text variant={'heading-sm'}>
                                  {__(
                                    'Validation errors',
                                    'posten-bring-checkout'
                                  )}
                                </Text>
                                <ul>
                                  {order.order_validation_errors.map(
                                    (validationError, index) => (
                                      <li key={index}>
                                        {validationError.message}
                                      </li>
                                    )
                                  )}
                                </ul>
                              </div>
                            </Popover>
                          )}
                        </Button>
                      )}
                    </>
                  )}
                </div>
              ) : (
                <div className="flex flex-dir-row gas align-ic">
                  <ServiceIcon
                    name={getServiceIcon(
                      editedOrder?.order_shipping_option ||
                        order.order_shipping_option
                    )}
                    height={26}
                    className="flex mrl"
                  />
                  <ShippingOptionSelector
                    selectedShippingOption={
                      editedOrder?.order_shipping_option ||
                      order.order_shipping_option
                    }
                    setSelectedShippingOption={selected => {
                      onChange('order_shipping_option', selected)
                    }}
                    availableServices={availableServicesForOrder}
                    selectedCustomer={
                      customerNumber || customers[0].customerNumber
                    }
                    customersAndServices={customers}
                    preSelectedShippingOption={undefined}
                    label={undefined}
                    ref={shippingOptionSelectRef}
                  />
                  <InputControl
                    className="weight-input"
                    type={'number'}
                    label={''}
                    min={0.1}
                    hideLabelFromVision={true}
                    value={
                      editedOrder?.total_weight
                        ? editedOrder.total_weight / 1000
                        : editedOrder?.total_weight
                    }
                    step={0.1}
                    suffix={'kg'}
                    onChange={e =>
                      onChange('total_weight', e.target.valueAsNumber * 1000)
                    }
                  />
                  <Button
                    type="button"
                    variant={'tertiary'}
                    onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
                      e.preventDefault()
                      onSaveChanges()
                    }}
                  >
                    {__('Save', 'posten-bring-checkout')}
                  </Button>
                  <Button
                    type="button"
                    variant={'tertiary'}
                    onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
                      e.preventDefault()
                      setEditable(false)
                      setEditedOrder(order)
                    }}
                  >
                    {__('Cancel', 'posten-bring-checkout')}
                  </Button>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </li>
  )
}

export default OrderListItem
