import {
  mdiAlertCircleOutline,
  mdiChartTimelineVariant,
  mdiClockOutline,
  mdiFileDownloadOutline,
  mdiFilterVariant,
  mdiMapMarkerDistance,
  mdiPackageVariantClosedCheck,
  mdiPlus,
  mdiTable,
  mdiTruckCheckOutline,
  mdiTruckDeliveryOutline,
} from '@mdi/js'
import Head from 'next/head'
import { uniqueId } from 'lodash'
import React, { ReactElement, useEffect, useMemo, useState } from 'react'
import CardBox from '../../components/CardBox'
import LayoutAuthenticated from '../../layouts/Authenticated'
import SectionMain from '../../components/SectionMain'
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'
import { getPageTitle } from '../../config'
import TableShipments from '../../components/Shipments/TableShipments'
import BaseButton from '../../components/BaseButton'
import BaseIcon from '../../components/BaseIcon'
import axios from 'axios'
import Link from 'next/link'
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
import CardBoxModal from '../../components/CardBoxModal'
import DragDropFilePicker from '../../components/DragDropFilePicker'
import { setRefetch, uploadCsv } from '../../stores/shipments/shipmentsSlice'
import { hasPermission } from '../../helpers/userPermissions'

type ShipmentRow = {
  id: string
  shipment_number?: string
  tracking_number?: string
  carrier?: string
  shipment_status?: string
  shipped_at?: string
  delivered_at?: string
  order?: {
    order_number?: string
    po_number?: string
    order_total?: number | string
    requested_delivery_date?: string
    account?: {
      account_name?: string
    }
    location?: {
      location_name?: string
      city?: string
      state?: string
    }
  }
}

const shipmentStatuses = ['preparing', 'shipped', 'delivered', 'exception']

const carrierLabels: Record<string, string> = {
  company_truck: 'Company truck',
  ups: 'UPS',
  fedex: 'FedEx',
  other: 'Other carrier',
}

const currencyFormatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  maximumFractionDigits: 0,
})

const dateFormatter = new Intl.DateTimeFormat('en-US', {
  month: 'short',
  day: 'numeric',
})

const timeFormatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: '2-digit',
})

const formatCurrency = (value?: number | string) => {
  const amount = Number(value || 0)

  if (!Number.isFinite(amount)) {
    return '$0'
  }

  return currencyFormatter.format(amount)
}

const formatDate = (value?: string) => {
  if (!value) {
    return 'Not scheduled'
  }

  return dateFormatter.format(new Date(value))
}

const formatTime = (value?: string) => {
  if (!value) {
    return 'Pending'
  }

  return timeFormatter.format(new Date(value))
}

const formatStatus = (status?: string) => {
  if (!status) {
    return 'Unknown'
  }

  return status
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ')
}

const formatCarrier = (carrier?: string) => {
  if (!carrier) {
    return 'Carrier pending'
  }

  return carrierLabels[carrier] || formatStatus(carrier)
}

const statusClasses = (status?: string) => {
  if (status === 'preparing') {
    return 'border-amber-200 bg-amber-50 text-amber-800'
  }

  if (status === 'shipped') {
    return 'border-blue-200 bg-blue-50 text-blue-800'
  }

  if (status === 'delivered') {
    return 'border-emerald-200 bg-emerald-50 text-emerald-800'
  }

  if (status === 'exception') {
    return 'border-rose-200 bg-rose-50 text-rose-800'
  }

  return 'border-slate-200 bg-white text-slate-700'
}

const isOpenShipment = (shipment: ShipmentRow) =>
  !['delivered'].includes(shipment.shipment_status || '')

const isDueToday = (shipment: ShipmentRow) => {
  const dateValue =
    shipment.order?.requested_delivery_date ||
    shipment.shipped_at ||
    shipment.delivered_at

  if (!dateValue) {
    return false
  }

  const date = new Date(dateValue)
  const today = new Date()

  return (
    date.getFullYear() === today.getFullYear() &&
    date.getMonth() === today.getMonth() &&
    date.getDate() === today.getDate()
  )
}

const StatusPill = ({ status }: { status?: string }) => (
  <span
    className={`inline-flex rounded-full border px-2.5 py-1 text-xs font-bold ${statusClasses(
      status,
    )}`}
  >
    {formatStatus(status)}
  </span>
)

const EmptyQueue = ({ label }: { label: string }) => (
  <div className='rounded-xl border border-dashed border-slate-300 bg-slate-50 p-4 text-sm font-medium text-slate-500 lg:col-span-2'>
    {label}
  </div>
)

const ShipmentsTablesPage = () => {
  const [filterItems, setFilterItems] = useState<any[]>([])
  const [csvFile, setCsvFile] = useState<File | null>(null)
  const [isModalActive, setIsModalActive] = useState(false)
  const [shipmentsQueue, setShipmentsQueue] = useState<ShipmentRow[]>([])
  const [shipmentsError, setShipmentsError] = useState('')
  const [isShipmentsLoading, setIsShipmentsLoading] = useState(false)
  const { currentUser } = useAppSelector((state) => state.auth)
  const dispatch = useAppDispatch()

  const [filters] = useState([
    { label: 'Shipment number', title: 'shipment_number' },
    { label: 'Tracking number', title: 'tracking_number' },
    { label: 'Shipped at', title: 'shipped_at', date: 'true' },
    { label: 'Delivered at', title: 'delivered_at', date: 'true' },
    { label: 'Order', title: 'order' },
    {
      label: 'Carrier',
      title: 'carrier',
      type: 'enum',
      options: ['company_truck', 'ups', 'fedex', 'other'],
    },
    {
      label: 'Shipment status',
      title: 'shipment_status',
      type: 'enum',
      options: ['preparing', 'shipped', 'delivered', 'exception'],
    },
  ])

  const hasCreatePermission =
    currentUser && hasPermission(currentUser, 'CREATE_SHIPMENTS')
  const hasReadPermission =
    currentUser && hasPermission(currentUser, 'READ_SHIPMENTS')

  useEffect(() => {
    if (!hasReadPermission) {
      return
    }

    const loadShipmentsQueue = async () => {
      setIsShipmentsLoading(true)
      setShipmentsError('')

      try {
        const { data } = await axios.get('/shipments', {
          params: {
            page: 0,
            limit: 24,
          },
        })
        setShipmentsQueue(data.rows || [])
      } catch (error) {
        console.error('Failed to load dispatch queue', error)
        setShipmentsError('Unable to load dispatch queue.')
      } finally {
        setIsShipmentsLoading(false)
      }
    }

    void loadShipmentsQueue()
  }, [hasReadPermission])

  const openShipments = useMemo(
    () => shipmentsQueue.filter(isOpenShipment),
    [shipmentsQueue],
  )
  const todayShipments = useMemo(
    () => shipmentsQueue.filter(isDueToday),
    [shipmentsQueue],
  )
  const exceptionShipments = useMemo(
    () =>
      shipmentsQueue.filter(
        (shipment) => shipment.shipment_status === 'exception',
      ),
    [shipmentsQueue],
  )
  const shippedValue = useMemo(
    () =>
      shipmentsQueue.reduce(
        (sum, shipment) => sum + Number(shipment.order?.order_total || 0),
        0,
      ),
    [shipmentsQueue],
  )
  const statusCounts = useMemo(() => {
    const counts: Record<string, number> = {}

    shipmentStatuses.forEach((status) => {
      counts[status] = shipmentsQueue.filter(
        (shipment) => shipment.shipment_status === status,
      ).length
    })

    return counts
  }, [shipmentsQueue])
  const carrierCounts = useMemo(() => {
    const counts: Record<string, number> = {}

    shipmentsQueue.forEach((shipment) => {
      const carrier = shipment.carrier || 'pending'
      counts[carrier] = (counts[carrier] || 0) + 1
    })

    return counts
  }, [shipmentsQueue])
  const dispatchQueue = useMemo(
    () =>
      [...openShipments]
        .sort((left, right) => {
          const leftTime = new Date(
            left.shipped_at ||
              left.order?.requested_delivery_date ||
              left.delivered_at ||
              '',
          ).getTime()
          const rightTime = new Date(
            right.shipped_at ||
              right.order?.requested_delivery_date ||
              right.delivered_at ||
              '',
          ).getTime()

          return (leftTime || 0) - (rightTime || 0)
        })
        .slice(0, 6),
    [openShipments],
  )

  const addFilter = () => {
    const newItem = {
      id: uniqueId(),
      fields: {
        filterValue: '',
        filterValueFrom: '',
        filterValueTo: '',
        selectedField: '',
      },
    }
    newItem.fields.selectedField = filters[0].title
    setFilterItems([...filterItems, newItem])
  }

  const getShipmentsCSV = async () => {
    const response = await axios({
      url: '/shipments?filetype=csv',
      method: 'GET',
      responseType: 'blob',
    })
    const type = response.headers['content-type']
    const blob = new Blob([response.data], { type: type })
    const link = document.createElement('a')
    link.href = window.URL.createObjectURL(blob)
    link.download = 'shipmentsCSV.csv'
    link.click()
  }

  const onModalConfirm = async () => {
    if (!csvFile) {
      setShipmentsError('Choose a CSV file before confirming import.')
      return
    }

    await dispatch(uploadCsv(csvFile))
    dispatch(setRefetch(true))
    setCsvFile(null)
    setIsModalActive(false)
  }

  const onModalCancel = () => {
    setCsvFile(null)
    setIsModalActive(false)
  }

  return (
    <>
      <Head>
        <title>{getPageTitle('Dispatch and shipments')}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton
          icon={mdiChartTimelineVariant}
          title='Dispatch and shipments'
          main
        >
          <div className='flex flex-wrap gap-2'>
            {hasCreatePermission && (
              <BaseButton
                href='/shipments/shipments-new'
                color='info'
                icon={mdiPlus}
                label='Create shipment'
              />
            )}
            <BaseButton
              color='info'
              outline
              icon={mdiFilterVariant}
              label='Add filter'
              onClick={addFilter}
            />
          </div>
        </SectionTitleLineWithButton>

        {shipmentsError && (
          <div className='mb-5 rounded-2xl border border-rose-200 bg-rose-50 p-4 text-sm font-semibold text-rose-800'>
            {shipmentsError}
          </div>
        )}

        <section className='mb-6 overflow-hidden rounded-2xl border border-slate-200 bg-slate-950 text-white shadow-sm'>
          <div className='grid gap-6 p-6 xl:grid-cols-[minmax(0,1fr)_390px] xl:p-8'>
            <div>
              <p className='text-xs font-semibold uppercase tracking-[0.24em] text-emerald-300'>
                Delivery dispatch board
              </p>
              <h1 className='mt-4 max-w-4xl text-3xl font-semibold leading-tight lg:text-4xl'>
                Move restaurant purchase orders from dock staging to buyer
                receiving without losing the delivery trail.
              </h1>
              <p className='mt-4 max-w-3xl text-sm leading-7 text-slate-300'>
                Coordinate company trucks, parcel carriers, DoorDash Drive, or
                Shippo-style handoffs from one operations screen. Exceptions,
                tracking numbers, and delivery dates stay visible before the
                raw shipments table.
              </p>
              <div className='mt-6 flex flex-wrap gap-2'>
                {[
                  'Dock staging',
                  'Carrier handoff',
                  'Tracking ready',
                  'Delivery exceptions',
                ].map((label) => (
                  <span
                    key={label}
                    className='rounded-full border border-white/10 bg-white/5 px-3 py-1 text-xs font-semibold text-slate-200'
                  >
                    {label}
                  </span>
                ))}
              </div>
            </div>
            <div className='grid gap-3 sm:grid-cols-2 xl:grid-cols-1'>
              <div className='rounded-xl border border-white/10 bg-white/5 p-4'>
                <p className='text-xs uppercase tracking-[0.18em] text-slate-400'>
                  Shipment value
                </p>
                <p className='mt-2 text-2xl font-semibold'>
                  {formatCurrency(shippedValue)}
                </p>
              </div>
              <div className='rounded-xl border border-white/10 bg-white/5 p-4'>
                <p className='text-xs uppercase tracking-[0.18em] text-slate-400'>
                  Dispatch state
                </p>
                <p className='mt-2 text-2xl font-semibold'>
                  {isShipmentsLoading
                    ? 'Refreshing'
                    : `${openShipments.length} open`}
                </p>
              </div>
            </div>
          </div>
        </section>

        <section className='mb-6 grid gap-4 sm:grid-cols-2 xl:grid-cols-5'>
          {[
            {
              label: 'Open handoffs',
              value: openShipments.length,
              detail: 'Not delivered yet',
              icon: mdiTruckDeliveryOutline,
            },
            {
              label: 'Due today',
              value: todayShipments.length,
              detail: 'Dock or buyer receiving',
              icon: mdiClockOutline,
            },
            {
              label: 'Preparing',
              value: statusCounts.preparing || 0,
              detail: 'Awaiting carrier',
              icon: mdiPackageVariantClosedCheck,
            },
            {
              label: 'In transit',
              value: statusCounts.shipped || 0,
              detail: 'Tracking active',
              icon: mdiMapMarkerDistance,
            },
            {
              label: 'Exceptions',
              value: exceptionShipments.length,
              detail: 'Needs operator review',
              icon: mdiAlertCircleOutline,
            },
          ].map((card) => (
            <div
              key={card.label}
              className='rounded-2xl border border-slate-200 bg-white p-4 shadow-sm'
            >
              <div className='flex items-start justify-between gap-3'>
                <div>
                  <p className='text-xs font-semibold uppercase tracking-[0.16em] text-slate-400'>
                    {card.label}
                  </p>
                  <p className='mt-3 text-3xl font-semibold text-slate-950'>
                    {card.value}
                  </p>
                </div>
                <span className='inline-flex h-10 w-10 items-center justify-center rounded-xl bg-emerald-50 text-emerald-700'>
                  <BaseIcon path={card.icon} size='20' />
                </span>
              </div>
              <p className='mt-3 text-sm text-slate-500'>{card.detail}</p>
            </div>
          ))}
        </section>

        <section className='mb-6 grid gap-5 xl:grid-cols-[minmax(0,1.25fr)_minmax(340px,0.75fr)]'>
          <CardBox className='border border-slate-200 bg-white shadow-sm'>
            <div className='mb-5 flex flex-wrap items-start justify-between gap-3 border-b border-slate-100 pb-4'>
              <div>
                <p className='text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700'>
                  Dispatch queue
                </p>
                <h2 className='mt-2 text-2xl font-semibold text-slate-950'>
                  Shipments to work next
                </h2>
              </div>
              <BaseButton
                color='info'
                outline
                icon={mdiFileDownloadOutline}
                label='Export CSV'
                onClick={getShipmentsCSV}
              />
            </div>
            <div className='grid gap-3 lg:grid-cols-2'>
              {dispatchQueue.map((shipment) => (
                <Link
                  key={shipment.id}
                  href={`/shipments/shipments-view/?id=${shipment.id}`}
                  className='block rounded-2xl border border-slate-200 bg-slate-50 p-4 transition hover:border-emerald-200 hover:bg-emerald-50/70'
                >
                  <div className='flex items-start justify-between gap-3'>
                    <div className='min-w-0'>
                      <p className='truncate text-lg font-semibold text-slate-950'>
                        {shipment.shipment_number || 'Shipment'}
                      </p>
                      <p className='mt-1 truncate text-sm text-slate-500'>
                        {shipment.order?.account?.account_name ||
                          'Buyer account pending'}
                      </p>
                    </div>
                    <StatusPill status={shipment.shipment_status} />
                  </div>
                  <div className='mt-4 grid gap-3 text-sm text-slate-600 sm:grid-cols-2'>
                    <div>
                      <p className='text-xs uppercase tracking-[0.14em] text-slate-400'>
                        Order
                      </p>
                      <p className='mt-1 font-semibold text-slate-900'>
                        {shipment.order?.order_number || 'Pending'}
                      </p>
                    </div>
                    <div>
                      <p className='text-xs uppercase tracking-[0.14em] text-slate-400'>
                        Carrier
                      </p>
                      <p className='mt-1 font-semibold text-slate-900'>
                        {formatCarrier(shipment.carrier)}
                      </p>
                    </div>
                    <div>
                      <p className='text-xs uppercase tracking-[0.14em] text-slate-400'>
                        Ship time
                      </p>
                      <p className='mt-1 font-semibold text-slate-900'>
                        {formatTime(shipment.shipped_at)}
                      </p>
                    </div>
                    <div>
                      <p className='text-xs uppercase tracking-[0.14em] text-slate-400'>
                        Tracking
                      </p>
                      <p className='mt-1 truncate font-semibold text-slate-900'>
                        {shipment.tracking_number || 'Not assigned'}
                      </p>
                    </div>
                  </div>
                </Link>
              ))}
              {!dispatchQueue.length && (
                <EmptyQueue label='No open shipments in the current dispatch queue.' />
              )}
            </div>
          </CardBox>

          <CardBox className='border border-slate-200 bg-white shadow-sm'>
            <div className='mb-5 border-b border-slate-100 pb-4'>
              <p className='text-xs font-semibold uppercase tracking-[0.2em] text-blue-700'>
                Carrier lanes
              </p>
              <h2 className='mt-2 text-2xl font-semibold text-slate-950'>
                Delivery mix
              </h2>
            </div>
            <div className='space-y-3'>
              {Object.entries({
                company_truck: 'Company truck',
                ups: 'UPS',
                fedex: 'FedEx',
                other: 'Other',
              }).map(([carrier, label]) => (
                <div
                  key={carrier}
                  className='rounded-xl border border-slate-200 bg-slate-50 p-4'
                >
                  <div className='flex items-center justify-between gap-3'>
                    <span className='text-sm font-semibold text-slate-900'>
                      {label}
                    </span>
                    <span className='text-2xl font-semibold text-slate-950'>
                      {carrierCounts[carrier] || 0}
                    </span>
                  </div>
                  <p className='mt-2 text-sm text-slate-500'>
                    {carrier === 'company_truck' &&
                      'Local route and dock handoff managed by the distributor team.'}
                    {carrier === 'ups' &&
                      'Parcel shipment ready for UPS label and tracking.'}
                    {carrier === 'fedex' &&
                      'Parcel shipment ready for FedEx label and tracking.'}
                    {carrier === 'other' &&
                      'External courier or custom freight workflow.'}
                  </p>
                </div>
              ))}
            </div>
          </CardBox>
        </section>

        <section className='mb-6 grid gap-5 xl:grid-cols-[minmax(0,0.85fr)_minmax(0,1.15fr)]'>
          <CardBox className='border border-slate-200 bg-white shadow-sm'>
            <div className='mb-5 border-b border-slate-100 pb-4'>
              <p className='text-xs font-semibold uppercase tracking-[0.2em] text-violet-700'>
                Status lanes
              </p>
              <h2 className='mt-2 text-2xl font-semibold text-slate-950'>
                Dispatch workflow
              </h2>
            </div>
            <div className='space-y-3'>
              {shipmentStatuses.map((status) => (
                <div
                  key={status}
                  className='rounded-xl border border-slate-200 bg-slate-50 p-4'
                >
                  <div className='flex items-center justify-between gap-3'>
                    <StatusPill status={status} />
                    <span className='text-2xl font-semibold text-slate-950'>
                      {statusCounts[status] || 0}
                    </span>
                  </div>
                  <p className='mt-2 text-sm text-slate-500'>
                    {status === 'preparing' &&
                      'Package the order, assign carrier, and confirm pickup.'}
                    {status === 'shipped' &&
                      'Track delivery progress and buyer receiving window.'}
                    {status === 'delivered' &&
                      'Close the delivery loop and keep tracking evidence.'}
                    {status === 'exception' &&
                      'Resolve address, carrier, temperature, or delivery issues.'}
                  </p>
                </div>
              ))}
            </div>
          </CardBox>

          <CardBox className='border border-slate-200 bg-white shadow-sm'>
            <div className='mb-5 border-b border-slate-100 pb-4'>
              <p className='text-xs font-semibold uppercase tracking-[0.2em] text-emerald-700'>
                Delivery automation
              </p>
              <h2 className='mt-2 text-2xl font-semibold text-slate-950'>
                Integration-ready handoff
              </h2>
            </div>
            <div className='grid gap-3 sm:grid-cols-2'>
              {[
                {
                  title: 'DoorDash Drive quote',
                  text: 'Use for local restaurant deliveries and delivery window pricing.',
                },
                {
                  title: 'Shippo parcel rates',
                  text: 'Use for UPS/FedEx style parcel labels and tracking options.',
                },
                {
                  title: 'QuickBooks invoice',
                  text: 'Keep delivery, order total, and invoice sync aligned.',
                },
                {
                  title: 'CSV export/import',
                  text: 'Move shipment rows through warehouse or carrier spreadsheets.',
                },
              ].map((item) => (
                <div
                  key={item.title}
                  className='rounded-xl border border-slate-200 bg-slate-50 p-4'
                >
                  <p className='font-semibold text-slate-950'>{item.title}</p>
                  <p className='mt-2 text-sm leading-6 text-slate-500'>
                    {item.text}
                  </p>
                </div>
              ))}
            </div>
          </CardBox>
        </section>

        <CardBox
          className='mb-6 border border-slate-200 bg-white shadow-sm'
          cardBoxClassName='flex flex-wrap gap-3'
        >
          <BaseButton
            color='info'
            outline
            icon={mdiFilterVariant}
            label='Add filter'
            onClick={addFilter}
          />
          <BaseButton
            color='info'
            outline
            icon={mdiFileDownloadOutline}
            label='Export CSV'
            onClick={getShipmentsCSV}
          />

          {hasCreatePermission && (
            <BaseButton
              color='info'
              outline
              label='Import CSV'
              onClick={() => setIsModalActive(true)}
            />
          )}

          <div className='md:inline-flex items-center ms-auto'>
            <div id='delete-rows-button'></div>
          </div>

          <div className='md:inline-flex items-center ms-auto'>
            <Link
              className='inline-flex items-center gap-2 rounded-xl border border-slate-200 px-3 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50'
              href='/shipments/shipments-table'
            >
              <BaseIcon path={mdiTable} size='16' />
              Table view
            </Link>
          </div>
        </CardBox>

        <CardBox className='mb-6 border border-slate-200 bg-white shadow-sm' hasTable>
          <TableShipments
            filterItems={filterItems}
            setFilterItems={setFilterItems}
            filters={filters}
            showGrid={false}
          />
        </CardBox>
      </SectionMain>
      <CardBoxModal
        title='Upload shipments CSV'
        buttonColor='info'
        buttonLabel='Confirm'
        isActive={isModalActive}
        onConfirm={onModalConfirm}
        onCancel={onModalCancel}
      >
        <DragDropFilePicker
          file={csvFile}
          setFile={setCsvFile}
          formats='.csv'
        />
      </CardBoxModal>
    </>
  )
}

ShipmentsTablesPage.getLayout = function getLayout(page: ReactElement) {
  return (
    <LayoutAuthenticated permission='READ_SHIPMENTS'>
      {page}
    </LayoutAuthenticated>
  )
}

export default ShipmentsTablesPage
