import { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery } from '@tanstack/react-query'
import { Check, ChevronsUpDown, Loader2, ShoppingCart } from 'lucide-react'
import { toast } from 'sonner'
import { cn } from '@/lib/utils'
import { getApiErrorMessage } from '@/lib/api'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@/components/ui/command'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { PasswordInput } from '@/components/password-input'
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import { Textarea } from '@/components/ui/textarea'
import { AdminPage } from '@/features/admin/components/admin-page'
import {
  listCatalogCategories,
  listCatalogProducts,
  type CatalogCategory,
  type CatalogProduct,
  type OrderFormField,
} from '@/features/catalog/api'
import { createOrder, type OrderDetail } from './api'

const CATEGORY_NONE = 'none'
const PRODUCT_NONE = 'none'

type SelfOwnedOrderForm = {
  categoryId: string
  productId: string
  quantity: number
  remark: string
  orderPayload: Record<string, unknown>
}

const defaultForm: SelfOwnedOrderForm = {
  categoryId: CATEGORY_NONE,
  productId: PRODUCT_NONE,
  quantity: 1,
  remark: '',
  orderPayload: {},
}

function formatPrice(value?: string) {
  const numberValue = Number(value || 0)
  return Number.isFinite(numberValue) ? `¥${numberValue.toFixed(2)}` : value
}

async function listAllSelfOwnedCategories() {
  const pageSize = 100
  let page = 1
  let total: number
  const list: CatalogCategory[] = []

  do {
    const result = await listCatalogCategories({
      page,
      pageSize,
      sourceType: 'self_owned',
      enabled: 'true',
    })
    list.push(...result.list)
    total = result.total
    page += 1
  } while (list.length < total)

  return { list, total, page: 1, pageSize: list.length || pageSize }
}

async function listAllSelfOwnedProductsByCategory(categoryId: string) {
  const pageSize = 100
  let page = 1
  let total: number
  const list: CatalogProduct[] = []

  do {
    const result = await listCatalogProducts({
      page,
      pageSize,
      sourceType: 'self_owned',
      enabled: 'true',
      categoryId,
    })
    list.push(...result.list)
    total = result.total
    page += 1
  } while (list.length < total)

  return { list, total, page: 1, pageSize: list.length || pageSize }
}

export function SelfOwnedOrderPage() {
  const [form, setForm] = useState<SelfOwnedOrderForm>(defaultForm)
  const [categoryPopoverOpen, setCategoryPopoverOpen] = useState(false)
  const [productPopoverOpen, setProductPopoverOpen] = useState(false)
  const [createdOrder, setCreatedOrder] = useState<OrderDetail | null>(null)

  const categoriesQuery = useQuery({
    queryKey: ['self-owned-order-categories'],
    queryFn: listAllSelfOwnedCategories,
  })

  const productsQuery = useQuery({
    queryKey: ['self-owned-order-products', form.categoryId],
    enabled: form.categoryId !== CATEGORY_NONE,
    queryFn: () => listAllSelfOwnedProductsByCategory(form.categoryId),
  })

  useEffect(() => {
    const params = new URLSearchParams(window.location.search)
    const categoryId = params.get('categoryId')
    if (!categoryId || form.categoryId !== CATEGORY_NONE) return
    const categoryExists = (categoriesQuery.data?.list ?? []).some(
      (category) => category.id === categoryId
    )
    if (categoryExists) {
      setForm((current) => ({ ...current, categoryId }))
    }
  }, [categoriesQuery.data?.list, form.categoryId])

  useEffect(() => {
    const params = new URLSearchParams(window.location.search)
    const productId = params.get('productId')
    if (
      !productId ||
      form.categoryId === CATEGORY_NONE ||
      form.productId !== PRODUCT_NONE
    ) {
      return
    }
    const productExists = (productsQuery.data?.list ?? []).some(
      (product) => product.id === productId
    )
    if (productExists) {
      setForm((current) => ({ ...current, productId }))
    }
  }, [form.categoryId, form.productId, productsQuery.data?.list])

  const selectedCategory = useMemo(
    () =>
      (categoriesQuery.data?.list ?? []).find(
        (category) => category.id === form.categoryId
      ) ?? null,
    [categoriesQuery.data?.list, form.categoryId]
  )

  const selectedProduct = useMemo(
    () =>
      (productsQuery.data?.list ?? []).find(
        (product) => product.id === form.productId
      ) ?? null,
    [form.productId, productsQuery.data?.list]
  )

  useEffect(() => {
    setForm((current) => ({
      ...current,
      orderPayload: getInitialPayload(selectedProduct?.orderFormSchema ?? []),
    }))
    setCreatedOrder(null)
  }, [selectedProduct?.id, selectedProduct?.orderFormSchema])

  const createOrderMutation = useMutation({
    mutationFn: () => {
      if (!selectedProduct) {
        throw new Error('请选择自营商品')
      }
      validatePayload(selectedProduct.orderFormSchema ?? [], form.orderPayload)
      return createOrder({
        productId: selectedProduct.id,
        quantity: form.quantity,
        orderPayload: form.orderPayload,
        selectedCourse: null,
        expand: null,
        remark: form.remark.trim() || null,
      })
    },
    onSuccess: (order) => {
      setCreatedOrder(order)
      toast.success(`订单已创建：${order.orderNo}`)
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '创建订单失败')),
  })

  const payableAmount = selectedProduct
    ? (Number(selectedProduct.price || 0) * form.quantity).toFixed(2)
    : '0.00'

  return (
    <AdminPage
      title='自营下单'
      description='选择平台自营商品，填写商品配置的下单信息，创建本地待支付订单。'
    >
      <div className='grid min-w-0 gap-4 lg:grid-cols-[minmax(0,420px)_minmax(0,1fr)]'>
        <div className='min-w-0 space-y-4 rounded-md border p-4'>
          <div className='grid gap-2'>
            <Label>自营分类</Label>
            <CategoryCombobox
              categories={categoriesQuery.data?.list ?? []}
              selectedCategory={selectedCategory}
              open={categoryPopoverOpen}
              loading={categoriesQuery.isLoading}
              onOpenChange={setCategoryPopoverOpen}
              onSelect={(categoryId) => {
                setForm({
                  ...form,
                  categoryId,
                  productId: PRODUCT_NONE,
                  orderPayload: {},
                })
                setCreatedOrder(null)
              }}
            />
          </div>

          <div className='grid gap-2'>
            <Label>自营商品</Label>
            <ProductCombobox
              products={productsQuery.data?.list ?? []}
              selectedProduct={selectedProduct}
              open={productPopoverOpen}
              loading={productsQuery.isLoading || productsQuery.isFetching}
              disabled={!selectedCategory}
              onOpenChange={setProductPopoverOpen}
              onSelect={(productId) => {
                setForm({ ...form, productId })
                setCreatedOrder(null)
              }}
            />
          </div>

          {selectedProduct && <ProductSummary product={selectedProduct} />}

          <div className='grid gap-2'>
            <Label htmlFor='quantity'>数量</Label>
            <Input
              id='quantity'
              type='number'
              min='1'
              max='999'
              value={form.quantity}
              onChange={(event) =>
                setForm({
                  ...form,
                  quantity: Math.max(Number(event.target.value || 1), 1),
                })
              }
            />
          </div>

          <OrderPayloadForm
            fields={selectedProduct?.orderFormSchema ?? []}
            payload={form.orderPayload}
            onPayloadChange={(orderPayload) =>
              setForm({ ...form, orderPayload })
            }
          />

          <div className='grid gap-2'>
            <Label htmlFor='remark'>备注</Label>
            <Textarea
              id='remark'
              value={form.remark}
              onChange={(event) =>
                setForm({ ...form, remark: event.target.value })
              }
            />
          </div>
        </div>

        <div className='min-w-0 space-y-4'>
          <div className='rounded-md border p-4'>
            <div className='mb-4 flex flex-wrap items-center justify-between gap-3'>
              <div>
                <div className='font-medium'>订单确认</div>
                <div className='text-sm text-muted-foreground'>
                  自营商品创建订单后不会调用第三方接口。
                </div>
              </div>
              <Badge variant='outline'>自营</Badge>
            </div>
            <div className='grid gap-3 text-sm'>
              <InfoRow label='商品' value={selectedProduct?.name} />
              <InfoRow label='分类' value={selectedCategory?.name} />
              <InfoRow label='单价' value={formatPrice(selectedProduct?.price)} />
              <InfoRow label='数量' value={String(form.quantity)} />
              <InfoRow label='应付金额' value={formatPrice(payableAmount)} />
              <InfoRow
                label='交付方式'
                value={
                  selectedProduct?.fulfillmentType === 'manual'
                    ? '人工处理'
                    : selectedProduct?.fulfillmentType === 'local_only'
                      ? '本地交付'
                      : '-'
                }
              />
            </div>
            <Button
              className='mt-4 w-full'
              disabled={!selectedProduct || createOrderMutation.isPending}
              onClick={() => createOrderMutation.mutate()}
            >
              {createOrderMutation.isPending ? (
                <Loader2 className='animate-spin' />
              ) : (
                <ShoppingCart />
              )}
              创建订单
            </Button>
          </div>

          {createdOrder && (
            <div className='grid gap-2 rounded-md border bg-muted/20 p-4 text-sm'>
              <div className='flex flex-wrap items-center gap-2'>
                <span className='font-medium'>订单号：{createdOrder.orderNo}</span>
                <Badge variant='secondary'>待支付</Badge>
              </div>
              <div className='text-muted-foreground'>
                应付金额 {formatPrice(createdOrder.payableAmount)}，履约状态：
                {createdOrder.fulfillmentStatus}
              </div>
            </div>
          )}
        </div>
      </div>
    </AdminPage>
  )
}

function CategoryCombobox({
  categories,
  selectedCategory,
  open,
  loading,
  onOpenChange,
  onSelect,
}: {
  categories: CatalogCategory[]
  selectedCategory: CatalogCategory | null
  open: boolean
  loading: boolean
  onOpenChange: (open: boolean) => void
  onSelect: (categoryId: string) => void
}) {
  return (
    <Popover open={open} onOpenChange={onOpenChange}>
      <PopoverTrigger asChild>
        <Button
          type='button'
          variant='outline'
          role='combobox'
          aria-expanded={open}
          title={selectedCategory?.name}
          className='h-auto min-h-10 w-full min-w-0 max-w-full justify-between gap-2 overflow-hidden px-3 py-2 text-left font-normal'
        >
          <span className='block min-w-0 flex-1 truncate'>
            {selectedCategory ? selectedCategory.name : '请选择或搜索自营分类'}
          </span>
          <ChevronsUpDown className='size-4 shrink-0 opacity-50' />
        </Button>
      </PopoverTrigger>
      <PopoverContent className='w-[var(--radix-popover-trigger-width)] p-0' align='start'>
        <Command filter={textFilter}>
          <CommandInput placeholder='输入分类名' />
          <CommandList>
            <CommandEmpty>
              {loading ? '分类加载中...' : '未找到匹配分类'}
            </CommandEmpty>
            <CommandGroup>
              {categories.map((category) => (
                <CommandItem
                  key={category.id}
                  value={[category.name, category.id].filter(Boolean).join(' ')}
                  onSelect={() => {
                    onSelect(category.id)
                    onOpenChange(false)
                  }}
                >
                  <Check
                    className={cn(
                      'size-4',
                      selectedCategory?.id === category.id
                        ? 'opacity-100'
                        : 'opacity-0'
                    )}
                  />
                  <span className='min-w-0 flex-1 truncate'>{category.name}</span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}

function ProductCombobox({
  products,
  selectedProduct,
  open,
  loading,
  disabled,
  onOpenChange,
  onSelect,
}: {
  products: CatalogProduct[]
  selectedProduct: CatalogProduct | null
  open: boolean
  loading: boolean
  disabled: boolean
  onOpenChange: (open: boolean) => void
  onSelect: (productId: string) => void
}) {
  return (
    <Popover open={open} onOpenChange={onOpenChange}>
      <PopoverTrigger asChild>
        <Button
          type='button'
          variant='outline'
          role='combobox'
          aria-expanded={open}
          disabled={disabled}
          title={selectedProduct?.name}
          className='h-auto min-h-10 w-full min-w-0 max-w-full justify-between gap-2 overflow-hidden px-3 py-2 text-left font-normal'
        >
          <span className='block min-w-0 flex-1 truncate'>
            {selectedProduct
              ? selectedProduct.name
              : disabled
                ? '请先选择自营分类'
                : '请选择或搜索自营商品'}
          </span>
          <ChevronsUpDown className='size-4 shrink-0 opacity-50' />
        </Button>
      </PopoverTrigger>
      <PopoverContent className='w-[var(--radix-popover-trigger-width)] p-0' align='start'>
        <Command filter={textFilter}>
          <CommandInput placeholder='输入商品名或商品 ID' />
          <CommandList>
            <CommandEmpty>
              {loading ? '商品加载中...' : '该分类下未找到匹配商品'}
            </CommandEmpty>
            <CommandGroup>
              {products.length > 0 && (
                <div className='px-2 py-1.5 text-xs text-muted-foreground'>
                  已加载 {products.length} 个商品
                </div>
              )}
              {products.map((product) => (
                <CommandItem
                  key={product.id}
                  value={[product.name, product.id].filter(Boolean).join(' ')}
                  onSelect={() => {
                    onSelect(product.id)
                    onOpenChange(false)
                  }}
                >
                  <Check
                    className={cn(
                      'size-4',
                      selectedProduct?.id === product.id
                        ? 'opacity-100'
                        : 'opacity-0'
                    )}
                  />
                  <div className='min-w-0 flex-1'>
                    <div className='truncate'>{product.name}</div>
                    <div className='truncate text-xs text-muted-foreground'>
                      库存：{product.stock === null ? '不限' : product.stock}
                    </div>
                  </div>
                  <span className='shrink-0 text-xs text-muted-foreground'>
                    {formatPrice(product.price)}
                  </span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}

function OrderPayloadForm({
  fields,
  payload,
  onPayloadChange,
}: {
  fields: OrderFormField[]
  payload: Record<string, unknown>
  onPayloadChange: (payload: Record<string, unknown>) => void
}) {
  if (!fields.length) {
    return (
      <div className='rounded-md border border-dashed py-6 text-center text-sm text-muted-foreground'>
        该商品没有配置下单字段。
      </div>
    )
  }

  function updateValue(key: string, value: unknown) {
    onPayloadChange({ ...payload, [key]: value })
  }

  return (
    <div className='space-y-3 rounded-md border p-3'>
      <div className='text-sm font-medium'>下单信息</div>
      {fields.map((field) => (
        <div key={field.key} className='grid gap-2'>
          <Label htmlFor={`field-${field.key}`}>
            {field.label}
            {field.required && <span className='ml-1 text-destructive'>*</span>}
          </Label>
          {field.type === 'textarea' ? (
            <Textarea
              id={`field-${field.key}`}
              value={String(payload[field.key] ?? '')}
              placeholder={field.placeholder ?? undefined}
              onChange={(event) => updateValue(field.key, event.target.value)}
            />
          ) : field.type === 'select' ? (
            <Select
              value={String(payload[field.key] ?? '')}
              onValueChange={(value) => updateValue(field.key, value)}
            >
              <SelectTrigger id={`field-${field.key}`}>
                <SelectValue placeholder={field.placeholder || '请选择'} />
              </SelectTrigger>
              <SelectContent>
                {(field.options ?? []).map((option) => (
                  <SelectItem key={option.value} value={option.value}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          ) : field.type === 'checkbox' ? (
            <label className='flex items-center gap-2 rounded-md border px-3 py-2 text-sm'>
              <Checkbox
                checked={Boolean(payload[field.key])}
                onCheckedChange={(checked) =>
                  updateValue(field.key, checked === true)
                }
              />
              {field.placeholder || '确认'}
            </label>
          ) : field.type === 'password' ? (
            <PasswordInput
              id={`field-${field.key}`}
              value={String(payload[field.key] ?? '')}
              placeholder={field.placeholder ?? undefined}
              onChange={(event) => updateValue(field.key, event.target.value)}
            />
          ) : (
            <Input
              id={`field-${field.key}`}
              type={field.type === 'number' ? 'number' : 'text'}
              value={String(payload[field.key] ?? '')}
              placeholder={field.placeholder ?? undefined}
              onChange={(event) => updateValue(field.key, event.target.value)}
            />
          )}
        </div>
      ))}
    </div>
  )
}

function ProductSummary({ product }: { product: CatalogProduct }) {
  return (
    <div className='grid gap-2 rounded-md border bg-muted/20 p-3 text-sm'>
      <div className='flex flex-wrap items-center gap-2'>
        <span className='font-medium'>{product.name}</span>
        <Badge variant='default'>自营</Badge>
      </div>
      <div className='text-muted-foreground'>
        价格：{formatPrice(product.price)}，库存：
        {product.stock === null ? '不限' : product.stock}
      </div>
    </div>
  )
}

function InfoRow({ label, value }: { label: string; value?: string | null }) {
  return (
    <div className='flex items-center justify-between gap-4 border-b pb-2 last:border-b-0 last:pb-0'>
      <span className='text-muted-foreground'>{label}</span>
      <span className='min-w-0 truncate text-right font-medium'>{value || '-'}</span>
    </div>
  )
}

function getInitialPayload(fields: OrderFormField[]) {
  return Object.fromEntries(
    fields.map((field) => [
      field.key,
      field.type === 'checkbox' ? false : '',
    ])
  )
}

function validatePayload(fields: OrderFormField[], payload: Record<string, unknown>) {
  for (const field of fields) {
    if (!field.required) continue
    const value = payload[field.key]
    if (field.type === 'checkbox') {
      if (value !== true) {
        throw new Error(`${field.label}必须勾选`)
      }
      continue
    }
    if (value === undefined || value === null || String(value).trim() === '') {
      throw new Error(`${field.label}不能为空`)
    }
  }
}

function textFilter(value: string, search: string) {
  if (!search.trim()) return 1
  return value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0
}
