import CircularProgress from '@mui/material/CircularProgress'
import Paper from '@mui/material/Paper'
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 _identity from 'lodash/identity'
import _isEmpty from 'lodash/isEmpty'
import _map from 'lodash/map'
import React, { Fragment, useState } from 'react'

import { downloadPDF } from '../../utils'
import SnackbarAlert from '../common/SnackbarAlert'
import { CustomFieldTypes } from './index'
import { TicketHolderCustomFields } from './TicketHolderCustomFields'

interface IAddOnTypes {
  name: string;
  groupName: string;
  status: string;
}

export interface ITicketTypes {
  add_ons?: IAddOnTypes[];
  hash: string;
  ticket_type: string;
  holder_name: string;
  status: string;
  pdf_link: string;
  is_sellable: boolean;
  is_on_sale?: boolean;
  event_name: string;
  currency: string;
  ticket_type_hash: string;
  ticket_type_is_active?: boolean;
  canSellTicket?: boolean;
  retain_amount_on_sale: number | string;
  ticketsTitle: string;
}

export interface IActionColumns {
  download?: boolean;
  sell_ticket?: boolean;
}

interface TicketsTableTypes {
  canSellTicket?: boolean;
  tickets: ITicketTypes[];
  columns: Array<{
    id?: string | number;
    key: keyof ITicketTypes & keyof IActionColumns;
    label: string | number | null | undefined;
  }>;
  handleSellTicket: (ticket: ITicketTypes) => void;
  handleRemoveFromResale: (ticket: ITicketTypes) => void;
  handleTicketHoldersUpdate: (values: Record<string, any>, ticketHash: string) => void;

  icon?: string;
  displayColumnNameInRow?: boolean;
  ticketsTitle?: string;
  ticketHoldersCustomFields?: Array<CustomFieldTypes>;
}

type PdfDownload = {
  hash: string;
  loading: boolean;
}

const TicketsTable = ({
  tickets = [],
  columns = [],
  icon = '',
  displayColumnNameInRow = false,
  canSellTicket = true,
  ticketsTitle = 'Your Tickets',
  ticketHoldersCustomFields = [],
  handleSellTicket = _identity,
  handleRemoveFromResale = _identity,
  handleTicketHoldersUpdate = _identity,
}: TicketsTableTypes) => {
  const [pdfError, setPdfError] = useState<string | null>(null)
  const [pdfDownload, setPdfDownload] = useState<PdfDownload>({
    hash: '',
    loading: false,
  })

  const getRow = (ticket: ITicketTypes) =>
    _map(columns, (column, columnIndex) => {
      if (column.key === 'download') {
        const ticketIsDownloading =
          pdfDownload.loading && pdfDownload.hash === ticket.hash

        if (!ticket.pdf_link || ticket.status === 'Sold' || ticket.is_on_sale)
          return <TableCell key={columnIndex}>{null}</TableCell>

        return (
          <TableCell key={columnIndex}>
            {Boolean(icon) && <img src={icon} alt="nodata" />}
            <span
              aria-hidden={true}
              className="action-button"
              onClick={async () => {
                if (ticketIsDownloading) {
                  return
                }

                setPdfDownload({ hash: ticket.hash, loading: true })
                try {
                  const pdfDownloadError = await downloadPDF(ticket.pdf_link)
                  if (pdfDownloadError) {
                    setPdfError(pdfDownloadError?.message)
                  }
                } catch (err) {
                  if (err && typeof err === 'string') {
                    setPdfError(err)
                  }
                } finally {
                  setPdfDownload({ hash: '', loading: false })
                }
              }}
            >
              {ticketIsDownloading ? <CircularProgress size="22px" /> : 'Download'}
            </span>
          </TableCell>
        )
      }

      if (column.key === 'sell_ticket') {
        return (
          <TableCell key={columnIndex}>
            {ticket.is_sellable && canSellTicket && (
              <span
                aria-hidden={true}
                className="action-button"
                onClick={() => handleSellTicket(ticket)}
              >
                Sell Ticket
              </span>
            )}
            {ticket.is_on_sale && (
              <span
                aria-hidden={true}
                className="action-button"
                onClick={() => handleRemoveFromResale(ticket)}
              >
                Remove from Resale
              </span>
            )}
          </TableCell>
        )
      }

      return displayColumnNameInRow ? (
        <TableCell key={columnIndex}>
          <div className="cell-block">
            <span>{column.label}</span>
            <span>{ticket[column.key]}</span>
          </div>
        </TableCell>
      ) : (
        <TableCell key={columnIndex}>
          <div className="cell-block">
            <span>{ticket[column.key]}</span>
          </div>
        </TableCell>
      )
    })

  return (
    <div className="tickets-box">
      <SnackbarAlert
        type="error"
        isOpen={!!pdfError}
        message={pdfError || ''}
        onClose={() => setPdfError(null)}
      />
      <h4 className="sub-title tickets-title">{ticketsTitle}</h4>
      <TableContainer component={Paper}>
        <Table aria-label="collapsible table">
          {displayColumnNameInRow ? null : (
            <TableHead>
              <TableRow>
                {_map(columns, item => (
                  <TableCell key={item.key}>{item.label || ''}</TableCell>
                ))}
              </TableRow>
            </TableHead>
          )}
          <TableBody>
            {tickets.map((ticket: ITicketTypes, index: number) => {
              const holderCustomFields = ticketHoldersCustomFields.filter(
                (field: CustomFieldTypes) => field?.ticketHash === ticket?.hash
              )

              return (
                <Fragment key={index}>
                  <TableRow>{getRow(ticket)}</TableRow>
                  {!_isEmpty(holderCustomFields) && (
                    <TableRow>
                      <TableCell colSpan={columns.length}>
                        <TicketHolderCustomFields
                          ticket={ticket}
                          holderCustomFields={holderCustomFields}
                          handleTicketHoldersUpdate={handleTicketHoldersUpdate}
                        />
                      </TableCell>
                    </TableRow>
                  )}
                  {!!ticket.add_ons?.length && (
                    <TableRow>
                      <TableCell colSpan={6}>
                        <Table className="ticket-add-on-table">
                          <TableHead>
                            <TableRow>
                              <TableCell>Add-On</TableCell>
                              <TableCell>Status</TableCell>
                            </TableRow>
                          </TableHead>
                          <TableBody>
                            {ticket.add_ons.map((add_on: IAddOnTypes, index: number) => (
                              <TableRow key={index}>
                                <TableCell>
                                  {add_on.groupName && `${add_on.groupName}: `}{' '}
                                  {add_on.name}
                                </TableCell>
                                <TableCell>{add_on.status}</TableCell>
                              </TableRow>
                            ))}
                          </TableBody>
                        </Table>
                      </TableCell>
                    </TableRow>
                  )}
                </Fragment>
              )
            })}
          </TableBody>
        </Table>
      </TableContainer>
    </div>
  )
}

export default TicketsTable
