/* eslint-disable @typescript-eslint/no-explicit-any */
import './style.css'

import { Backdrop, CircularProgress, ThemeOptions } from '@mui/material'
import Paper from '@mui/material/Paper'
import { createTheme, ThemeProvider } from '@mui/material/styles'
import Table from '@mui/material/Table'
import TableBody from '@mui/material/TableBody'
import TableCell from '@mui/material/TableCell'
import TableContainer from '@mui/material/TableContainer'
import TableHead from '@mui/material/TableHead'
import TableRow from '@mui/material/TableRow'
import { CSSProperties } from '@mui/styles'
import _find from 'lodash/find'
import _get from 'lodash/get'
import _has from 'lodash/has'
import _identity from 'lodash/identity'
import _isEmpty from 'lodash/isEmpty'
import _map from 'lodash/map'
import moment from 'moment-timezone'
import React, { useEffect, useMemo, useState } from 'react'
import SVG from 'react-inlinesvg'

import {
  getOrderDetails,
  removeFromResale,
  resaleTicket,
  updateOrderCustomFields,
  updateTicketHoldersCustomFields,
} from '../../api'
import EditSvg from '../../assets/images/edit.svg'
import { isBrowser } from '../../utils'
import ConfirmModal from '../confirmModal'
import { InitialValuesTypes, TicketResaleModal } from '../ticketResaleModal'
import { CustomFieldsForm } from './CustomFieldsForm'
import TicketsTable, { IActionColumns, ITicketTypes } from './ticketsTable'
import { isFieldUpdatable, renderCustomFieldValue } from './utils'

interface TicketTypes {
  currency: string;
  discount: string;
  name: string;
  price: string;
  quantity: string;
  total: string;
  groupName: string;
  guests_count: string;
  deposit_paid: string;
  remaining: string;
}

interface OrderDetailsTypes {
  columns: Array<{ label: string }>;
  onGetOrdersSuccess: (res: any) => void;
  onGetOrdersError: (err: any) => void;
  onReturnButtonClick: (data: any) => void;
  onRemoveFromResaleSuccess: () => void;
  onRemoveFromResaleError: (err: any) => void;
  onResaleTicketSuccess: () => void;
  onResaleTicketError: (err: any) => void;
  onUpdateOrderCustomFieldsSuccess: (val: any) => void;
  onUpdateOrderCustomFieldsError: (err: any) => void;
  onUpdateTicketHolderCustomFieldsSuccess: (val: any) => void;
  onUpdateTicketHolderCustomFieldsError: (err: any) => void;
  personalLinkIcon?: string;
  displayColumnNameInRow?: boolean;
  canSellTicket?: boolean;
  themeOptions?: ThemeOptions & {
    input?: CSSProperties;
    checkbox?: CSSProperties;
  };
  ticketsTableColumns?: Array<{
    id?: string | number;
    key: keyof ITicketTypes & keyof IActionColumns;
    label: string | number | null | undefined;
  }>;
  ordersPath?: string;
  orderId?: string | number;
  referralTitle?: string;
  itemsTitle?: string;
  ticketsTitle?: string;
  displayLoading?: boolean;
  onDataLoaded?: (data: any) => void;
}

export interface CustomFieldOption {
  id: string;
  name: string;
  value: string;
  order: string;
}

export interface CustomFieldTypes {
  description: string;
  enabled: string;
  id: string;
  label: string;
  name: string;
  orderId: string;
  required: boolean;
  settings: {
    showOnMyTickets: boolean;
    allowUpdate: boolean;
    className: string;
  };
  type: string;
  value: string | Array<string>;

  ticketHash?: string;
  options?: CustomFieldOption[];
}

const getTotal = (data: any) => {
  if (data?.total && data?.tickets && data.tickets[0]?.currency)
    return data.tickets[0].currency + data.total
  if (!data?.total || !_has(data, 'items.ticket_types.length')) return ''

  return data.items.ticket_types[0].currency + data.total
}

export const OrderDetailsContainer = ({
  columns = [],
  onGetOrdersSuccess = _identity,
  onGetOrdersError = _identity,
  onRemoveFromResaleSuccess = _identity,
  onRemoveFromResaleError = _identity,
  onResaleTicketSuccess = _identity,
  onResaleTicketError = _identity,
  onUpdateOrderCustomFieldsSuccess = _identity,
  onUpdateOrderCustomFieldsError = _identity,
  onUpdateTicketHolderCustomFieldsSuccess = _identity,
  onUpdateTicketHolderCustomFieldsError = _identity,
  onReturnButtonClick,
  personalLinkIcon = '',
  displayColumnNameInRow = false,
  canSellTicket = true,
  ticketsTableColumns,
  ordersPath,
  orderId: pOrderId,
  referralTitle = '',
  itemsTitle = '',
  ticketsTitle = 'Your Tickets',
  themeOptions,
  displayLoading = true,
  onDataLoaded = _identity,
}: OrderDetailsTypes) => {
  const [data, setData] = useState<any>({})
  const [removeFromResaleLoading, setRemoveFromResaleLoading] = useState(false)
  const [resaleTicketLoading, setResaleTicketLoading] = useState(false)
  const [showResaleModal, setShowResaleModal] = useState(false)
  const [showRemoveResaleModal, setShowRemoveResaleModal] = useState(false)
  const [activeTicket, setActiveTicket] = useState<any>(null)
  const [showOrderCustomFieldsSection, setShowOrderCustomFieldsSection] = useState(false)
  const [isLoading, setIsLoading] = useState(false)

  const isTable = _get(data, 'tickets[0].is_table', false)
  const columnsProps = isTable
    ? [
        { label: 'Items' },
        { label: 'Price' },
        { label: 'Guests count' },
        { label: 'Deposit paid' },
        { label: 'Remaining' },
      ]
    : columns
  const ticketHoldersCustomFields = _get(data, 'ticket_data_capture', [])

  const orderCustomFields = _get(data, 'data_capture', [])
  const [orderUpdatableCustomFields, orderNotUpdatableCustomFields] = useMemo(() => {
    const allowedFields: CustomFieldTypes[] = []
    const notAllowedFields: CustomFieldTypes[] = []

    orderCustomFields.forEach((field: CustomFieldTypes) => {
      if (isFieldUpdatable(field)) {
        allowedFields.push(field)
      } else {
        notAllowedFields.push(field)
      }
    })
    return [allowedFields, notAllowedFields]
  }, [orderCustomFields])
  const orderEditableFieldsFormInitialValues = useMemo(() => {
    const initialValues = orderUpdatableCustomFields.map((field: CustomFieldTypes) => [
      field.name,
      field.type === 'checkbox' ? Boolean(field.value) : field.value || '',
    ])
    return Object.fromEntries(initialValues)
  }, [orderUpdatableCustomFields])

  let orderId = String(pOrderId) || ''
  if (isBrowser && !pOrderId) {
    const params: URLSearchParams = new URL(`${window.location}`).searchParams
    orderId = params.get('o') || ''
  }

  let orderSummery = `ID ${data.id}, placed`
  if (data.date && data.timezone) {
    const date = moment.tz(data.date, data.timezone).format('dddd, DD MMMM YYYY')
    orderSummery += ` ${date}`
  }

  useEffect(() => {
    (async () => {
      try {
        let orderId = pOrderId || ''
        if (isBrowser && !pOrderId) {
          const params: URLSearchParams = new URL(`${window.location}`).searchParams
          orderId = params.get('o') || ''
        }
        setIsLoading(true)
        const response = await getOrderDetails(String(orderId))
        onGetOrdersSuccess(response)

        const data = _get(response, 'data.attributes')
        setData(data)
        setIsLoading(false)
        onDataLoaded(data)
      } catch (error) {
        onGetOrdersError(error)
        setIsLoading(false)
      }
    })()
  }, [onGetOrdersError, onGetOrdersSuccess, onDataLoaded, pOrderId])

  const handleSellTicket = (ticket: ITicketTypes) => {
    const ticketTypesArr = data.items.ticket_types
    const sellTicketType = _find(
      ticketTypesArr,
      ticketType => ticketType.hash === ticket.ticket_type_hash
    )
    setActiveTicket({
      ...ticket,
      ticket_type_is_active: sellTicketType?.active,
    })
    setShowResaleModal(true)
  }

  const handleOnClose = () => {
    setShowResaleModal(false)
    setActiveTicket(null)
  }

  const handleOnSubmit = async (values: InitialValuesTypes) => {
    if (resaleTicketLoading) {
      return
    }

    try {
      setResaleTicketLoading(true)
      const { to, first_name, last_name, email, confirm_email, confirm } = values
      const formData = new FormData()
      formData.append('to', to)
      formData.append('first_name', first_name)
      formData.append('last_name', last_name)
      formData.append('email', email)
      formData.append('confirm_email', confirm_email)
      formData.append('confirm', String(confirm))

      await resaleTicket(formData, activeTicket.hash)
      const response = await getOrderDetails(orderId)
      onGetOrdersSuccess(response)

      const data = _get(response, 'data.attributes')
      const updatedData = { ...data }
      updatedData?.tickets?.forEach((ticket: ITicketTypes) => {
        if (ticket.hash === activeTicket.hash) {
          ticket.is_sellable = false
          ticket.is_on_sale = true
        }
      })

      setData(updatedData)
      onResaleTicketSuccess()
    } catch (error) {
      onResaleTicketError(error)
    } finally {
      setShowResaleModal(false)
      setResaleTicketLoading(false)
    }
  }

  const handleRemoveFromResale = (ticket: ITicketTypes) => {
    setShowRemoveResaleModal(true)
    setActiveTicket(ticket)
  }

  const onCloseRemoveResale = () => {
    setShowRemoveResaleModal(false)
    setActiveTicket(null)
  }

  const onConfirmRemoveResale = async () => {
    if (removeFromResaleLoading) {
      return
    }

    try {
      setRemoveFromResaleLoading(true)
      await removeFromResale(activeTicket.hash)
      const response = await getOrderDetails(orderId)
      onGetOrdersSuccess(response)

      const data = _get(response, 'data.attributes')
      const updatedData = { ...data }
      updatedData?.tickets?.forEach((ticket: ITicketTypes) => {
        if (ticket.hash === activeTicket.hash) {
          ticket.is_sellable = true
          ticket.is_on_sale = false
        }
      })

      setData(updatedData)
      onRemoveFromResaleSuccess()
    } catch (error) {
      onRemoveFromResaleError(error)
    } finally {
      setShowRemoveResaleModal(false)
      setRemoveFromResaleLoading(false)
    }
  }

  const handleOrderCustomFieldsUpdate = async (values: Record<string, any>) => {
    setShowOrderCustomFieldsSection(false)
    try {
      // Collect all updatable and non updatable values for bulk update
      const fullUpdatableValues = orderNotUpdatableCustomFields.reduce(
        (acc, customField) => {
          acc[customField.name] = customField.value
          return acc
        },
        { ...values }
      )
      const eventId = _get(data, 'event_id')
      const response = await updateOrderCustomFields(
        eventId,
        orderId,
        fullUpdatableValues
      )
      const updatedCustomFields = _get(response, 'data.data.attributes', [])

      setData((prevState: Record<string, any>) => ({
        ...prevState,
        data_capture: updatedCustomFields,
      }))
      onUpdateOrderCustomFieldsSuccess(response)
    } catch (error) {
      onUpdateOrderCustomFieldsError(error)
    }
  }

  const handleTicketHoldersUpdate = async (
    values: Record<string, any>,
    ticketHash: string
  ) => {
    try {
      const eventId = _get(data, 'event_id')
      const response = await updateTicketHoldersCustomFields(eventId, values, ticketHash)
      const updatedFields = _get(response, 'data.data.attributes', [])
      const notUpdatedFields = ticketHoldersCustomFields.filter(
        (field: CustomFieldTypes) => field.ticketHash !== ticketHash
      )

      setData((prevState: Record<string, any>) => ({
        ...prevState,
        ticket_data_capture: [...updatedFields, ...notUpdatedFields],
      }))
      onUpdateTicketHolderCustomFieldsSuccess(response)
    } catch (error) {
      onUpdateTicketHolderCustomFieldsError(error)
    }
  }

  const theme = createTheme(themeOptions ?? {})

  if (isLoading || _isEmpty(data)) {
    if (displayLoading) {
      return (
        <ThemeProvider theme={theme}>
          <Backdrop
            sx={{ color: '#fff', backgroundColor: '#000000bd', zIndex: 1205 }}
            open={true}
          >
            <CircularProgress color="inherit" />
          </Backdrop>
        </ThemeProvider>
      )
    }

    return null
  }

  return (
    <ThemeProvider theme={theme}>
      <div className="order-details">
        <div className="layout-block">
          <h1 className="layout-title">Order Details</h1>
          {!_isEmpty(orderUpdatableCustomFields) && (
            <SVG src={EditSvg} onClick={() => setShowOrderCustomFieldsSection(true)} />
          )}
        </div>
        <div className="order-summary-box">
          <div className="summary-block">
            <div className="summary-item">
              <h6 className="sub-title">Order Summary</h6>
              <p className="order-summary-date">{orderSummery}</p>
            </div>
            <div className="summary-item">
              <div className="return-button-container">
                <button
                  type="button"
                  className="return-button"
                  onClick={() => {
                    if (isBrowser) {
                      window.location.assign(ordersPath ?? '/orders')
                    }
                  }}
                >
                  Back to Orders
                </button>
              </div>
            </div>
          </div>
          {!_isEmpty(orderCustomFields) && (
            <>
              <div className="custom-field-value-container">
                {orderCustomFields.map((customField: CustomFieldTypes) => (
                  <div className="info-item" key={customField.id}>
                    <b>{customField.label} :</b> {renderCustomFieldValue(customField)}
                  </div>
                ))}
              </div>
              {!_isEmpty(orderUpdatableCustomFields) && (
                <div
                  className={`custom-fields-block ${
                    showOrderCustomFieldsSection ? 'show' : ''
                  }`}
                >
                  <p className="title">Aditional Information Request</p>
                  <CustomFieldsForm
                    initialValues={orderEditableFieldsFormInitialValues}
                    fields={orderUpdatableCustomFields}
                    handleFormSubmit={handleOrderCustomFieldsUpdate}
                    handleFormClose={() => setShowOrderCustomFieldsSection(false)}
                  />
                </div>
              )}
            </>
          )}
          {!data?.disable_referral && (
            <>
              {referralTitle && (
                <h4 className="referral-title sub-title">{referralTitle}</h4>
              )}
              <div className="personal-link">
                <div className="link-item">
                  <span>Personal Share Link: </span>
                  <a href={data?.personal_share_link} target="_blank" rel="noreferrer">
                    {Boolean(personalLinkIcon) && (
                      <img src={personalLinkIcon} alt="Icon" />
                    )}
                    {data?.personal_share_link}
                  </a>
                </div>
                {data?.sales_referred ? (
                  <div className="link-item">
                    <p className="total-referrer">{`So far, you’ve referred ${data.sales_referred} tickets`}</p>
                  </div>
                ) : null}
              </div>
            </>
          )}
          {itemsTitle && <h4 className="items-title sub-title">{itemsTitle}</h4>}
          <TableContainer component={Paper}>
            <Table className="tt-type" aria-label="collapsible table">
              <TableHead>
                <TableRow>
                  {_map(columnsProps, item => (
                    <TableCell>{item.label || ''}</TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {data?.items?.ticket_types?.map((ticket: TicketTypes, index: number) =>
                  data?.tickets && !data?.tickets[0].is_table ? (
                    <TableRow key={index}>
                      <TableCell>
                        <b>Ticket Type:</b> {ticket.name}
                      </TableCell>
                      <TableCell>{ticket.currency + ticket.price}</TableCell>
                      <TableCell>{ticket.quantity}</TableCell>
                      <TableCell>{ticket.currency + ticket.total}</TableCell>
                    </TableRow>
                  ) : (
                    <TableRow key={index}>
                      <TableCell>
                        <b>Ticket Type:</b> {ticket.name}
                      </TableCell>
                      <TableCell>{ticket.currency + ticket.price}</TableCell>
                      <TableCell>{ticket.guests_count}</TableCell>
                      <TableCell>{ticket.deposit_paid}</TableCell>
                      <TableCell>{ticket.remaining}</TableCell>
                    </TableRow>
                  )
                )}
                {data?.items?.add_ons?.map((ticket: TicketTypes, index: number) => (
                  <TableRow key={index}>
                    <TableCell>
                      <div>
                        <b>Add-On</b>
                        <div>
                          {ticket.groupName && `${ticket.groupName}: `} {ticket.name}
                        </div>
                      </div>
                    </TableCell>
                    <TableCell>{ticket.currency + ticket.price}</TableCell>
                    <TableCell>{ticket.quantity}</TableCell>
                    <TableCell>{ticket.currency + ticket.total}</TableCell>
                  </TableRow>
                ))}
                <TableRow className="total-row">
                  <TableCell />
                  <TableCell />
                  <TableCell>Total</TableCell>
                  <TableCell>{getTotal(data)}</TableCell>
                </TableRow>
              </TableBody>
            </Table>
          </TableContainer>
        </div>
        <TicketsTable
          ticketsTitle={ticketsTitle}
          tickets={data.tickets}
          columns={
            ticketsTableColumns?.length
              ? ticketsTableColumns
              : [
                  { key: 'hash' as never, label: 'Ticket ID' },
                  { key: 'ticket_type' as never, label: 'Ticket Type' },
                  { key: 'holder_name' as never, label: 'Ticket Holder' },
                  { key: 'status' as never, label: 'Status' },
                  { key: 'download' as never, label: '' },
                  { key: 'sell_ticket' as never, label: '' },
                ]
          }
          handleSellTicket={handleSellTicket}
          handleRemoveFromResale={handleRemoveFromResale}
          displayColumnNameInRow={displayColumnNameInRow}
          canSellTicket={canSellTicket}
          ticketHoldersCustomFields={ticketHoldersCustomFields}
          handleTicketHoldersUpdate={handleTicketHoldersUpdate}
        />
        <div className="return-button-container">
          <button
            type="button"
            className="return-button"
            onClick={() => {
              if (onReturnButtonClick) {
                onReturnButtonClick(data)
              } else if (isBrowser) {
                window.location.assign(ordersPath ?? '/orders')
              }
            }}
          >
            Return to Order History
          </button>
        </div>
        {showResaleModal && (
          <TicketResaleModal
            ticket={activeTicket}
            onClose={handleOnClose}
            onSubmit={handleOnSubmit}
            loading={resaleTicketLoading}
          />
        )}
        {showRemoveResaleModal && (
          <ConfirmModal
            message="Are you sure you want to withdraw your ticket from resale?"
            onClose={onCloseRemoveResale}
            onConfirm={onConfirmRemoveResale}
            loading={removeFromResaleLoading}
          />
        )}
      </div>
    </ThemeProvider>
  )
}
