import { useMutation, useQueryClient } from '@tanstack/react-query'
import { usePOSStore } from '@/stores/pos.store'
import { posMutations, posKeys, type Transaction } from '@/api/pos'
import { Button } from '@/components/ui/button'
import { Separator } from '@/components/ui/separator'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { X, Banknote, CreditCard, FileText, Ban, UserRound, Tag } from 'lucide-react'
import { toast } from 'sonner'
import { useState } from 'react'
import { POSPaymentDialog } from './pos-payment-dialog'
import { POSCustomerDialog } from './pos-customer-dialog'
import { ManagerOverrideDialog, requiresOverride, requiresDiscountOverride } from './pos-manager-override'
import type { TransactionLineItem } from '@/api/pos'

interface POSCartPanelProps {
  transaction: Transaction | null
}

export function POSCartPanel({ transaction }: POSCartPanelProps) {
  const queryClient = useQueryClient()
  const { currentTransactionId, setTransaction, accountName, accountPhone, accountEmail } = usePOSStore()
  const [paymentMethod, setPaymentMethod] = useState<string | null>(null)
  const [customerOpen, setCustomerOpen] = useState(false)
  const [overrideOpen, setOverrideOpen] = useState(false)
  const [priceItemId, setPriceItemId] = useState<string | null>(null)
  const [pendingDiscount, setPendingDiscount] = useState<{ lineItemId: string; amount: number; reason: string } | null>(null)
  const [pendingOrderDiscount, setPendingOrderDiscount] = useState<{ amount: number; reason: string } | null>(null)
  const [discountOverrideOpen, setDiscountOverrideOpen] = useState(false)
  const lineItems = transaction?.lineItems ?? []

  const drawerSessionId = usePOSStore((s) => s.drawerSessionId)
  const drawerOpen = !!drawerSessionId

  const removeItemMutation = useMutation({
    mutationFn: (lineItemId: string) =>
      posMutations.removeLineItem(currentTransactionId!, lineItemId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: posKeys.transaction(currentTransactionId!) })
    },
    onError: (err) => toast.error(err.message),
  })

  const discountMutation = useMutation({
    mutationFn: (data: { lineItemId: string; amount: number; reason: string }) =>
      posMutations.applyDiscount(currentTransactionId!, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: posKeys.transaction(currentTransactionId!) })
      setPriceItemId(null)
      toast.success('Price adjusted')
    },
    onError: (err) => toast.error(err.message),
  })

  const orderDiscountMutation = useMutation({
    mutationFn: async ({ amount, reason }: { amount: number; reason: string }) => {
      // Distribute discount proportionally across all line items
      let remaining = amount
      for (let i = 0; i < lineItems.length; i++) {
        const item = lineItems[i]
        const itemTotal = parseFloat(item.unitPrice) * item.qty
        const isLast = i === lineItems.length - 1
        const share = isLast ? remaining : Math.round((itemTotal / subtotal) * amount * 100) / 100
        remaining -= share
        if (share > 0) {
          await posMutations.applyDiscount(currentTransactionId!, { lineItemId: item.id, amount: share, reason })
        }
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: posKeys.transaction(currentTransactionId!) })
      toast.success('Order discount applied')
    },
    onError: (err) => toast.error(err.message),
  })

  const voidMutation = useMutation({
    mutationFn: () => posMutations.void(currentTransactionId!),
    onSuccess: () => {
      setTransaction(null)
      toast.success('Transaction voided')
    },
    onError: (err) => toast.error(err.message),
  })

  const subtotal = parseFloat(transaction?.subtotal ?? '0')
  const discountTotal = parseFloat(transaction?.discountTotal ?? '0')
  const taxTotal = parseFloat(transaction?.taxTotal ?? '0')
  const total = parseFloat(transaction?.total ?? '0')
  const hasItems = lineItems.length > 0
  const isPending = transaction?.status === 'pending'

  function handlePaymentComplete() {
    setPaymentMethod(null)
    setTransaction(null)
  }

  return (
    <div className="flex flex-col h-full bg-card">
      {/* Header */}
      <div className="p-3 border-b border-border">
        <div className="flex items-center justify-between">
          <h2 className="font-semibold text-base">Current Sale</h2>
          {transaction && (
            <span className="text-xs text-muted-foreground font-mono">
              {transaction.transactionNumber}
            </span>
          )}
        </div>
        <button
          onClick={() => setCustomerOpen(true)}
          className="flex items-start gap-1.5 mt-1 text-xs text-muted-foreground hover:text-foreground text-left"
        >
          <UserRound className="h-3 w-3 mt-0.5 shrink-0" />
          {accountName ? (
            <span>
              <span className="font-medium text-foreground">{accountName}</span>
              {(accountPhone || accountEmail) && (
                <span className="block text-[11px]">
                  {[accountPhone, accountEmail].filter(Boolean).join(' · ')}
                </span>
              )}
            </span>
          ) : (
            <span>Walk-in — tap to add customer</span>
          )}
        </button>
      </div>

      {/* Line items */}
      <div className="flex-1 overflow-y-auto">
        {lineItems.length === 0 ? (
          <div className="flex items-center justify-center h-full text-muted-foreground text-sm">
            No items yet
          </div>
        ) : (
          <div className="divide-y divide-border">
            {lineItems.map((item) => {
              const unitPrice = parseFloat(item.unitPrice)
              const discount = parseFloat(item.discountAmount)
              const hasDiscount = discount > 0
              const listTotal = unitPrice * item.qty
              const discountPct = listTotal > 0 ? Math.round((discount / listTotal) * 100) : 0

              return (
                <div key={item.id} className="flex items-center gap-2 px-3 py-2.5 group">
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium truncate">{item.description}</p>
                    <div className="text-xs text-muted-foreground flex items-center gap-2">
                      <span>{item.qty} x ${unitPrice.toFixed(2)}</span>
                      {hasDiscount && (
                        <span className="text-green-600">-${discount.toFixed(2)} ({discountPct}%)</span>
                      )}
                      {parseFloat(item.taxAmount) > 0 && (
                        <span>tax ${parseFloat(item.taxAmount).toFixed(2)}</span>
                      )}
                    </div>
                  </div>
                  <span className="text-sm font-medium tabular-nums">
                    ${parseFloat(item.lineTotal).toFixed(2)}
                  </span>
                  {isPending && (
                    <div className="flex items-center gap-0.5 opacity-0 group-hover:opacity-100 shrink-0">
                      <PriceAdjuster
                        item={item}
                        open={priceItemId === item.id}
                        onOpenChange={(o) => setPriceItemId(o ? item.id : null)}
                        onApply={(amount, reason) => {
                          const pct = listTotal > 0 ? (amount / listTotal) * 100 : 0
                          if (requiresDiscountOverride(pct)) {
                            setPendingDiscount({ lineItemId: item.id, amount, reason })
                            setDiscountOverrideOpen(true)
                          } else {
                            discountMutation.mutate({ lineItemId: item.id, amount, reason })
                          }
                        }}
                        isPending={discountMutation.isPending}
                      />
                      <Button
                        variant="ghost"
                        size="icon"
                        className="h-8 w-8"
                        onClick={() => removeItemMutation.mutate(item.id)}
                        disabled={removeItemMutation.isPending}
                      >
                        <X className="h-4 w-4 text-destructive" />
                      </Button>
                    </div>
                  )}
                </div>
              )
            })}
          </div>
        )}
      </div>

      {/* Totals + payment */}
      <div className="shrink-0 border-t border-border">
        <div className="px-3 py-2 space-y-1 text-sm">
          <div className="flex justify-between">
            <span className="text-muted-foreground">Subtotal</span>
            <span className="tabular-nums">${subtotal.toFixed(2)}</span>
          </div>
          {discountTotal > 0 && (
            <div className="flex justify-between text-green-600">
              <span>Discount</span>
              <span className="tabular-nums">-${discountTotal.toFixed(2)}</span>
            </div>
          )}
          <div className="flex justify-between">
            <span className="text-muted-foreground">Tax</span>
            <span className="tabular-nums">${taxTotal.toFixed(2)}</span>
          </div>
          <Separator />
          <div className="flex justify-between text-lg font-bold pt-1">
            <span>Total</span>
            <span className="tabular-nums">${total.toFixed(2)}</span>
          </div>
        </div>

        {/* Order discount button */}
        {hasItems && isPending && (
          <div className="px-3 pb-1">
            <OrderDiscountButton
              subtotal={subtotal}
              onApply={(amount, reason) => {
                const pct = subtotal > 0 ? (amount / subtotal) * 100 : 0
                if (requiresDiscountOverride(pct)) {
                  setPendingOrderDiscount({ amount, reason })
                  setDiscountOverrideOpen(true)
                } else {
                  orderDiscountMutation.mutate({ amount, reason })
                }
              }}
              isPending={orderDiscountMutation.isPending}
            />
          </div>
        )}

        {/* Payment buttons */}
        <div className="p-3 space-y-2">
          {!drawerOpen && hasItems && (
            <p className="text-xs text-destructive text-center">Open the drawer before accepting payment</p>
          )}
          <div className="grid grid-cols-2 gap-2">
            <Button
              className="h-12 text-sm gap-2"
              disabled={!hasItems || !isPending || !drawerOpen}
              onClick={() => setPaymentMethod('cash')}
            >
              <Banknote className="h-4 w-4" />
              Cash
            </Button>
            <Button
              className="h-12 text-sm gap-2"
              disabled={!hasItems || !isPending || !drawerOpen}
              onClick={() => setPaymentMethod('card_present')}
            >
              <CreditCard className="h-4 w-4" />
              Card
            </Button>
            <Button
              variant="outline"
              className="h-12 text-sm gap-2"
              disabled={!hasItems || !isPending || !drawerOpen}
              onClick={() => setPaymentMethod('check')}
            >
              <FileText className="h-4 w-4" />
              Check
            </Button>
            <Button
              variant="destructive"
              className="h-12 text-sm gap-2"
              disabled={!hasItems || !isPending}
              onClick={() => {
                if (requiresOverride('void_transaction')) {
                  setOverrideOpen(true)
                } else {
                  voidMutation.mutate()
                }
              }}
            >
              <Ban className="h-4 w-4" />
              Void
            </Button>
          </div>
        </div>
      </div>

      {/* Payment dialog */}
      {paymentMethod && transaction && (
        <POSPaymentDialog
          open={!!paymentMethod}
          onOpenChange={(open) => { if (!open) setPaymentMethod(null) }}
          paymentMethod={paymentMethod}
          transaction={transaction}
          onComplete={handlePaymentComplete}
        />
      )}

      {/* Customer dialog */}
      <POSCustomerDialog open={customerOpen} onOpenChange={setCustomerOpen} />

      {/* Manager override for void */}
      <ManagerOverrideDialog
        open={overrideOpen}
        onOpenChange={setOverrideOpen}
        action="Void transaction"
        onAuthorized={() => voidMutation.mutate()}
      />

      {/* Manager override for discount */}
      <ManagerOverrideDialog
        open={discountOverrideOpen}
        onOpenChange={setDiscountOverrideOpen}
        action="Price adjustment"
        onAuthorized={() => {
          if (pendingDiscount) {
            discountMutation.mutate(pendingDiscount)
            setPendingDiscount(null)
          } else if (pendingOrderDiscount) {
            orderDiscountMutation.mutate(pendingOrderDiscount)
            setPendingOrderDiscount(null)
          }
        }}
      />
    </div>
  )
}

// --- Order Discount Button ---

function OrderDiscountButton({ subtotal, onApply, isPending }: {
  subtotal: number
  onApply: (amount: number, reason: string) => void
  isPending: boolean
}) {
  const [open, setOpen] = useState(false)
  const [mode, setMode] = useState<AdjustMode>('percent')
  const [value, setValue] = useState('')

  function calculate() {
    const v = parseFloat(value) || 0
    if (mode === 'amount_off') return Math.min(v, subtotal)
    if (mode === 'set_price') return Math.max(0, subtotal - v)
    return Math.round(subtotal * (v / 100) * 100) / 100
  }

  const discountAmount = calculate()

  function handleApply() {
    if (discountAmount <= 0) return
    const reason = mode === 'percent' ? `${parseFloat(value)}% order discount` : mode === 'set_price' ? `Order total set to $${parseFloat(value).toFixed(2)}` : `$${parseFloat(value).toFixed(2)} order discount`
    onApply(discountAmount, reason)
    setValue('')
    setOpen(false)
  }

  return (
    <Popover open={open} onOpenChange={(o) => { setOpen(o); if (!o) setValue('') }}>
      <PopoverTrigger asChild>
        <Button variant="outline" size="sm" className="w-full gap-2 text-xs h-8">
          <Tag className="h-3 w-3" />Order Discount
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-64 p-3" side="top" align="center">
        <div className="space-y-3">
          <div className="text-xs text-muted-foreground">
            Subtotal: <span className="font-medium text-foreground">${subtotal.toFixed(2)}</span>
          </div>
          <div className="flex rounded-md border overflow-hidden text-xs">
            {([
              { key: 'percent' as const, label: '% Off' },
              { key: 'amount_off' as const, label: '$ Off' },
              { key: 'set_price' as const, label: 'Set Total' },
            ]).map((m) => (
              <button
                key={m.key}
                type="button"
                className={`flex-1 py-1.5 transition-colors ${mode === m.key ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}
                onClick={() => { setMode(m.key); setValue('') }}
              >
                {m.label}
              </button>
            ))}
          </div>
          <Input
            type="number"
            step="0.01"
            min="0"
            placeholder={mode === 'percent' ? 'e.g. 10' : '0.00'}
            value={value}
            onChange={(e) => setValue(e.target.value)}
            className="h-9"
            autoFocus
            onKeyDown={(e) => { if (e.key === 'Enter') handleApply() }}
          />
          {value && discountAmount > 0 && (
            <div className="text-xs flex justify-between font-medium">
              <span className="text-green-600">-${discountAmount.toFixed(2)}</span>
              <span>New total: ${(subtotal - discountAmount).toFixed(2)}</span>
            </div>
          )}
          <Button size="sm" className="w-full" onClick={handleApply} disabled={isPending || discountAmount <= 0}>
            {isPending ? 'Applying...' : 'Apply Discount'}
          </Button>
        </div>
      </PopoverContent>
    </Popover>
  )
}

// --- Price Adjuster Popover ---

type AdjustMode = 'amount_off' | 'set_price' | 'percent'

function PriceAdjuster({ item, open, onOpenChange, onApply, isPending }: {
  item: TransactionLineItem
  open: boolean
  onOpenChange: (open: boolean) => void
  onApply: (amount: number, reason: string) => void
  isPending: boolean
}) {
  const [mode, setMode] = useState<AdjustMode>('percent')
  const [value, setValue] = useState('')

  const unitPrice = parseFloat(item.unitPrice)
  const listTotal = unitPrice * item.qty

  function calculate(): { discountAmount: number; salePrice: number; pct: number } {
    const v = parseFloat(value) || 0
    if (mode === 'amount_off') {
      const d = Math.min(v, listTotal)
      return { discountAmount: d, salePrice: listTotal - d, pct: listTotal > 0 ? (d / listTotal) * 100 : 0 }
    }
    if (mode === 'set_price') {
      const d = Math.max(0, listTotal - v)
      return { discountAmount: d, salePrice: v, pct: listTotal > 0 ? (d / listTotal) * 100 : 0 }
    }
    // percent
    const d = Math.round(listTotal * (v / 100) * 100) / 100
    return { discountAmount: d, salePrice: listTotal - d, pct: v }
  }

  const calc = calculate()

  function handleApply() {
    if (calc.discountAmount <= 0) return
    const reason = mode === 'percent' ? `${parseFloat(value)}% off` : mode === 'set_price' ? `Price set to $${parseFloat(value).toFixed(2)}` : `$${parseFloat(value).toFixed(2)} off`
    onApply(calc.discountAmount, reason)
    setValue('')
  }

  return (
    <Popover open={open} onOpenChange={(o) => { onOpenChange(o); if (!o) setValue('') }}>
      <PopoverTrigger asChild>
        <Button variant="ghost" size="icon" className="h-8 w-8">
          <Tag className="h-4 w-4" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-64 p-3" side="left" align="start">
        <div className="space-y-3">
          <div className="text-xs text-muted-foreground">
            List: <span className="font-medium text-foreground">${listTotal.toFixed(2)}</span>
          </div>

          {/* Mode tabs */}
          <div className="flex rounded-md border overflow-hidden text-xs">
            {([
              { key: 'percent' as const, label: '% Off' },
              { key: 'amount_off' as const, label: '$ Off' },
              { key: 'set_price' as const, label: 'Set Price' },
            ]).map((m) => (
              <button
                key={m.key}
                type="button"
                className={`flex-1 py-1.5 transition-colors ${mode === m.key ? 'bg-primary text-primary-foreground' : 'hover:bg-muted'}`}
                onClick={() => { setMode(m.key); setValue('') }}
              >
                {m.label}
              </button>
            ))}
          </div>

          <Input
            type="number"
            step="0.01"
            min="0"
            placeholder={mode === 'percent' ? 'e.g. 10' : '0.00'}
            value={value}
            onChange={(e) => setValue(e.target.value)}
            className="h-9"
            autoFocus
            onKeyDown={(e) => { if (e.key === 'Enter') handleApply() }}
          />

          {value && parseFloat(value) > 0 && (
            <div className="text-xs space-y-0.5">
              <div className="flex justify-between">
                <span className="text-muted-foreground">Discount</span>
                <span className="text-green-600">-${calc.discountAmount.toFixed(2)} ({calc.pct.toFixed(0)}%)</span>
              </div>
              <div className="flex justify-between font-medium">
                <span>Sale Price</span>
                <span>${calc.salePrice.toFixed(2)}</span>
              </div>
            </div>
          )}

          <Button
            size="sm"
            className="w-full"
            onClick={handleApply}
            disabled={isPending || !value || calc.discountAmount <= 0}
          >
            {isPending ? 'Applying...' : 'Apply'}
          </Button>
        </div>
      </PopoverContent>
    </Popover>
  )
}
