import { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery } from '@tanstack/react-query'
import { Check, ChevronsUpDown, Loader2, SearchIcon, 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 {
  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 { Textarea } from '@/components/ui/textarea'
import { AdminPage } from '@/features/admin/components/admin-page'
import {
  listCatalogCategories,
  listCatalogProducts,
  type CatalogCategory,
  type CatalogProduct,
} from '@/features/catalog/api'
import {
  createOrder,
  queryThirdPartyCourses,
  type CourseQueryResultItem,
  type OrderDetail,
} from './api'

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

type QueryForm = {
  categoryId: string
  productId: string
  school: string
  account: string
  password: string
  expandText: string
}

const defaultQueryForm: QueryForm = {
  categoryId: CATEGORY_NONE,
  productId: PRODUCT_NONE,
  school: '',
  account: '',
  password: '',
  expandText: '',
}

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

function parseJsonObject(value: string, label: string) {
  const trimmed = value.trim()
  if (!trimmed) {
    return null
  }

  try {
    const parsed = JSON.parse(trimmed) as unknown
    if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
      return parsed as Record<string, unknown>
    }
  } catch {
    throw new Error(`${label} 必须是合法 JSON`)
  }

  throw new Error(`${label} 必须是 JSON 对象`)
}

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

  do {
    const result = await listCatalogCategories({
      page,
      pageSize,
      sourceType: 'third_party',
      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 listAllThirdPartyProductsByCategory(categoryId: string) {
  const pageSize = 100
  let page = 1
  let total: number
  const list: CatalogProduct[] = []

  do {
    const result = await listCatalogProducts({
      page,
      pageSize,
      sourceType: 'third_party',
      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 CourseQueryPage() {
  const [form, setForm] = useState<QueryForm>(defaultQueryForm)
  const [selectedCourse, setSelectedCourse] =
    useState<CourseQueryResultItem | null>(null)
  const [createdOrder, setCreatedOrder] = useState<OrderDetail | null>(null)
  const [categoryPopoverOpen, setCategoryPopoverOpen] = useState(false)
  const [productPopoverOpen, setProductPopoverOpen] = useState(false)

  const categoriesQuery = useQuery({
    queryKey: ['course-query-categories'],
    queryFn: listAllThirdPartyCategories,
  })

  const productsQuery = useQuery({
    queryKey: ['course-query-products', form.categoryId],
    enabled: form.categoryId !== CATEGORY_NONE,
    queryFn: () => listAllThirdPartyProductsByCategory(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]
  )

  const queryMutation = useMutation({
    mutationFn: () => {
      if (!selectedProduct) {
        throw new Error('请选择第三方商品')
      }
      return queryThirdPartyCourses({
        productId: selectedProduct.id,
        school: form.school,
        account: form.account,
        password: form.password,
        expand: parseJsonObject(form.expandText, 'expand 参数'),
      })
    },
    onSuccess: (result) => {
      setSelectedCourse(null)
      setCreatedOrder(null)
      toast.success(`查课完成，共 ${result.courses.length} 门课程`)
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '查课失败')),
  })

  const createOrderMutation = useMutation({
    mutationFn: () => {
      if (!selectedProduct) {
        throw new Error('请选择第三方商品')
      }
      if (!selectedCourse) {
        throw new Error('请选择课程')
      }
      return createOrder({
        productId: selectedProduct.id,
        quantity: 1,
        orderPayload: {
          school: form.school,
          account: form.account,
          password: form.password,
        },
        selectedCourse,
        expand: parseJsonObject(form.expandText, 'expand 参数'),
      })
    },
    onSuccess: (order) => {
      setCreatedOrder(order)
      toast.success(`订单已创建：${order.orderNo}`)
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '创建订单失败')),
  })

  const courses = queryMutation.data?.courses ?? []

  return (
    <AdminPage
      title='查课下单'
      description='通过服务端调用第三方查课接口，选择课程后创建本地待支付订单。'
    >
      <div className='grid min-w-0 gap-4 lg:grid-cols-[minmax(0,360px)_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 })
                setSelectedCourse(null)
                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 })
                setSelectedCourse(null)
                setCreatedOrder(null)
              }}
            />
          </div>

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

          <div className='grid gap-2'>
            <Label htmlFor='school'>学校</Label>
            <Input
              id='school'
              value={form.school}
              onChange={(event) =>
                setForm({ ...form, school: event.target.value })
              }
            />
          </div>
          <div className='grid gap-2'>
            <Label htmlFor='account'>账号</Label>
            <Input
              id='account'
              value={form.account}
              onChange={(event) =>
                setForm({ ...form, account: event.target.value })
              }
            />
          </div>
          <div className='grid gap-2'>
            <Label htmlFor='password'>密码</Label>
            <PasswordInput
              id='password'
              value={form.password}
              onChange={(event) =>
                setForm({ ...form, password: event.target.value })
              }
            />
          </div>
          <div className='grid gap-2'>
            <Label htmlFor='expand'>expand 参数</Label>
            <Textarea
              id='expand'
              value={form.expandText}
              placeholder='例如 {"score":95,"duration":35}'
              onChange={(event) =>
                setForm({ ...form, expandText: event.target.value })
              }
            />
          </div>
          <Button
            className='w-full'
            disabled={
              queryMutation.isPending ||
              !selectedCategory ||
              !selectedProduct ||
              !form.school ||
              !form.account ||
              !form.password
            }
            onClick={() => queryMutation.mutate()}
          >
            {queryMutation.isPending ? (
              <Loader2 className='animate-spin' />
            ) : (
              <SearchIcon />
            )}
            查课
          </Button>
        </div>

        <div className='min-w-0 space-y-4'>
          <div className='overflow-auto rounded-md border'>
            <table className='w-full text-sm'>
              <thead className='border-b bg-muted/40'>
                <tr>
                  <th className='px-3 py-2 text-left font-medium'>课程名称</th>
                  <th className='w-40 px-3 py-2 text-left font-medium'>
                    课程 ID
                  </th>
                  <th className='w-24 px-3 py-2 text-right font-medium'>
                    操作
                  </th>
                </tr>
              </thead>
              <tbody>
                {queryMutation.isPending ? (
                  <tr>
                    <td colSpan={3} className='h-28 text-center'>
                      <Loader2 className='mx-auto animate-spin' />
                    </td>
                  </tr>
                ) : courses.length ? (
                  courses.map((course, index) => {
                    const selected =
                      selectedCourse?.courseId === course.courseId &&
                      selectedCourse?.courseName === course.courseName
                    return (
                      <tr key={`${course.courseId || index}-${course.courseName}`} className='border-b'>
                        <td className='px-3 py-2'>{course.courseName}</td>
                        <td className='px-3 py-2 text-muted-foreground'>
                          {course.courseId || '-'}
                        </td>
                        <td className='px-3 py-2 text-right'>
                          <Button
                            size='sm'
                            variant={selected ? 'default' : 'outline'}
                            onClick={() => setSelectedCourse(course)}
                          >
                            {selected && <Check />}
                            选择
                          </Button>
                        </td>
                      </tr>
                    )
                  })
                ) : (
                  <tr>
                    <td colSpan={3} className='h-28 text-center text-muted-foreground'>
                      填写信息后点击查课
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <div className='flex flex-wrap items-center justify-between gap-3 rounded-md border p-4'>
            <div>
              <div className='text-sm font-medium'>
                {selectedCourse ? selectedCourse.courseName : '未选择课程'}
              </div>
              <div className='text-xs text-muted-foreground'>
                订单创建后进入待支付状态，支付成功后再提交第三方下单。
              </div>
            </div>
            <Button
              disabled={!selectedCourse || 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={productFilter}>
          <CommandInput placeholder='输入分类名或项目 ID' />
          <CommandList>
            <CommandEmpty>
              {loading ? '分类加载中...' : '未找到匹配分类'}
            </CommandEmpty>
            <CommandGroup>
              {categories.map((category) => (
                <CommandItem
                  key={category.id}
                  value={[
                    category.name,
                    category.remoteCategoryId,
                    category.externalId,
                    category.id,
                  ]
                    .filter(Boolean)
                    .join(' ')}
                  onSelect={() => {
                    onSelect(category.id)
                    onOpenChange(false)
                  }}
                >
                  <Check
                    className={cn(
                      'size-4',
                      selectedCategory?.id === category.id
                        ? 'opacity-100'
                        : 'opacity-0'
                    )}
                  />
                  <div className='min-w-0 flex-1'>
                    <div className='truncate'>{category.name}</div>
                    <div className='truncate text-xs text-muted-foreground'>
                      项目 ID：{category.remoteCategoryId || category.externalId || '-'}
                    </div>
                  </div>
                </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={productFilter}>
          <CommandInput placeholder='输入商品名、项目 ID 或商品 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.remoteCategoryId,
                    product.remoteCourseId,
                    product.externalId,
                    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'>
                      项目 ID：{product.remoteCategoryId || '-'} / 商品 ID：
                      {product.remoteCourseId || product.externalId || '-'}
                    </div>
                  </div>
                  <span className='shrink-0 text-xs text-muted-foreground'>
                    {formatPrice(product.price)}
                  </span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  )
}

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

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='outline'>第三方</Badge>
      </div>
      <div className='text-muted-foreground'>
        项目 ID：{product.remoteCategoryId || '-'}，价格：
        {formatPrice(product.price)}
      </div>
    </div>
  )
}
