import { useState, useMemo, useCallback, useEffect, type ReactNode } from 'react'
import { useQuery } from '@tanstack/react-query'
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell, Treemap } from 'recharts'
import api from '@/lib/api'
import { MetricCard } from '@/components/MetricCard'
import { LoadingSpinner } from '@/components/LoadingSpinner'
import { CollapsibleSection } from '@/components/CollapsibleSection'
import { FilterableTable } from '@/components/FilterableTable'
import { formatNumber, formatCurrency, cn } from '@/lib/utils'
import { Network, ChevronRight, ChevronDown, Layers, GitBranch, Box, Package, Loader2, X } from 'lucide-react'
import { MonthPicker } from '@/components/MonthPicker'

function varianceColorClass(pct: number): string {
  if (Math.abs(pct) <= 3) return 'text-green-600'
  if (Math.abs(pct) <= 10) return 'text-yellow-600'
  return 'text-red-600'
}

function varianceText(pct: number): string {
  if (pct > 0) return `+${pct.toFixed(2)}%`
  return `${pct.toFixed(2)}%`
}

interface BomTreeNode {
  level: number
  material_code: string
  material_name: string
  unit: string
  theoretical_qty: number
  issue_qty: number
  theoretical_amt: number
  issue_amt: number
  avg_unit_price: number
  is_finished_product: boolean
  parent_material_code: string
  root_product_code: string
  root_product_name: string
  root_recipe: string
  path: string
  children: BomTreeNode[]
}

function buildTree(flatTree: any[]): BomTreeNode[] {
  const nodeMap = new Map<string, BomTreeNode>()
  const roots: BomTreeNode[] = []
  flatTree.forEach((n: any) => {
    const node: BomTreeNode = { ...n, children: [] }
    nodeMap.set(node.material_code + '_' + node.level, node)
  })
  flatTree.forEach((n: any) => {
    const key = n.material_code + '_' + n.level
    const node = nodeMap.get(key)!
    if (n.level === 1) {
      roots.push(node)
    } else {
      const parentKey = n.parent_material_code + '_' + (n.level - 1)
      const parent = nodeMap.get(parentKey)
      if (parent) parent.children.push(node)
      else roots.push(node)
    }
  })
  return roots
}

export function BomPenetrationPage() {
  const [month, setMonth] = useState('2026-04')
  const [selectedProduct, setSelectedProduct] = useState<string | null>(null)
  const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set())
  const [lazyChildren, setLazyChildren] = useState<Map<string, BomTreeNode[]>>(new Map())
  const [loadingNodes, setLoadingNodes] = useState<Set<string>>(new Set())

  const { data: overviewData, isLoading: overviewLoading } = useQuery({
    queryKey: ['bom-penetration-overview', month],
    queryFn: async () => {
      const res = await api.get(`/central-kitchen/bom-penetration?month=${month}`)
      return res.data
    },
  })

  const { data: productData, isLoading: productLoading } = useQuery({
    queryKey: ['bom-penetration', month, selectedProduct],
    queryFn: async () => {
      const res = await api.get(`/central-kitchen/bom-penetration?month=${month}&productCode=${selectedProduct}`)
      return res.data
    },
    enabled: !!selectedProduct,
  })

  const bomTree = productData?.bomTree || []

  // BOM树构建
  const bomTreeData = useMemo(() => buildTree(bomTree), [bomTree])

  const maxLevel = useMemo(() => Math.max(0, ...bomTree.map((n: any) => n.level)), [bomTree])

  const toggleNode = useCallback(async (code: string, isFinishedProduct: boolean) => {
    if (expandedNodes.has(code)) {
      setExpandedNodes(prev => { const n = new Set(prev); n.delete(code); return n })
      return
    }
    setExpandedNodes(prev => new Set(prev).add(code))
    if (isFinishedProduct && !lazyChildren.has(code)) {
      setLoadingNodes(prev => new Set(prev).add(code))
      try {
        const res = await api.get(`/central-kitchen/bom-penetration?month=${month}&productCode=${code}`)
        const children = buildTree(res.data.bomTree || [])
        setLazyChildren(prev => new Map(prev).set(code, children))
      } catch (e) {
        setLazyChildren(prev => new Map(prev).set(code, []))
      } finally {
        setLoadingNodes(prev => { const n = new Set(prev); n.delete(code); return n })
      }
    }
  }, [expandedNodes, lazyChildren, month])

  const openProductModal = (code: string) => {
    setSelectedProduct(code)
    setExpandedNodes(new Set())
    setLazyChildren(new Map())
    setLoadingNodes(new Set())
  }

  // 数据加载后自动展开所有有子级的节点
  useEffect(() => {
    if (!bomTreeData.length) return
    const toExpand = new Set<string>()
    const collect = (nodes: BomTreeNode[]) => {
      nodes.forEach(n => {
        if (n.children.length > 0) {
          toExpand.add(n.material_code)
          collect(n.children)
        }
      })
    }
    collect(bomTreeData)
    if (toExpand.size > 0) {
      setExpandedNodes(prev => new Set([...prev, ...toExpand]))
    }
  }, [bomTreeData])

  const closeModal = () => {
    setSelectedProduct(null)
    setExpandedNodes(new Set())
    setLazyChildren(new Map())
    setLoadingNodes(new Set())
  }

  if (overviewLoading) return <LoadingSpinner />
  if (!overviewData) return <div className="p-4 text-muted-foreground">暂无数据</div>

  const { productList, bomSummary, multiLevelChains } = overviewData

  // 汇总指标
  const totalProducts = productList.length
  const multiLevelProducts = productList.filter((p: any) => p.has_multi_level_bom).length
  const totalBomTheoretical = bomSummary.reduce((s: number, b: any) => s + b.bom_theoretical_amt, 0)
  const totalBomIssue = bomSummary.reduce((s: number, b: any) => s + b.bom_issue_amt, 0)
  const totalVariance = bomSummary.reduce((s: number, b: any) => s + b.variance_amt, 0)

  // BOM汇总Top10
  const bomSummaryTop10 = bomSummary.slice(0, 15)
  const bomChartData = bomSummaryTop10.map((b: any) => ({
    name: b.product_name,
    理论成本: b.bom_theoretical_amt,
    领用成本: b.bom_issue_amt,
  }))

  const renderTreeRows = (nodes: BomTreeNode[], depth: number): ReactNode[] => {
    const rows: ReactNode[] = []
    nodes.forEach((node) => {
      const isExpanded = expandedNodes.has(node.material_code)
      const hasChildren = node.children.length > 0
      const lazyLoaded = lazyChildren.get(node.material_code)
      const isLoading = loadingNodes.has(node.material_code)
      const showChevron = hasChildren || node.is_finished_product
      const childrenToRender = hasChildren ? node.children : (lazyLoaded || [])
      const isZero = node.theoretical_qty === 0 && node.issue_qty === 0 && node.theoretical_amt === 0 && node.issue_amt === 0
      rows.push(
        <tr key={node.material_code + '_' + node.level} className={cn('border-b hover:bg-muted/50', node.is_finished_product && 'bg-purple-50/30', isZero && 'bg-yellow-50/40')}>
          <td className="py-1.5 pr-3" style={{ paddingLeft: `${depth * 20 + 8}px` }}>
            <div className="flex items-center gap-1.5">
              {showChevron ? (
                <button onClick={() => toggleNode(node.material_code, node.is_finished_product)} className="flex-shrink-0">
                  {isLoading ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> :
                   isExpanded ? <ChevronDown className="h-3.5 w-3.5" /> : <ChevronRight className="h-3.5 w-3.5" />}
                </button>
              ) : (
                <span className="inline-block w-3.5" />
              )}
              {node.is_finished_product && <Box className="h-3.5 w-3.5 text-purple-600 flex-shrink-0" />}
              <span className={cn('text-xs', node.is_finished_product && 'font-medium text-purple-700')}>{node.material_name}</span>
              {isZero && <span className="rounded bg-yellow-100 px-1 py-0.5 text-[10px] text-yellow-700">用量为0</span>}
            </div>
          </td>
          <td className="py-1.5 pr-3 text-xs text-muted-foreground">{node.material_code}</td>
          <td className="py-1.5 pr-3 text-xs text-muted-foreground">{node.unit}</td>
          <td className="py-1.5 pr-3 text-right text-xs">{formatNumber(node.theoretical_qty)}</td>
          <td className="py-1.5 pr-3 text-right text-xs">{formatNumber(node.issue_qty)}</td>
          <td className="py-1.5 pr-3 text-right text-xs">{formatCurrency(node.theoretical_amt)}</td>
          <td className="py-1.5 pr-3 text-right text-xs">{formatCurrency(node.issue_amt)}</td>
          <td className="py-1.5 pr-3 text-right text-xs">
            <span className={cn('font-medium', node.issue_amt - node.theoretical_amt >= 0 ? 'text-yellow-600' : 'text-red-600')}>
              {formatCurrency(node.issue_amt - node.theoretical_amt)}
            </span>
          </td>
          <td className="py-1.5 pr-3" />
        </tr>
      )
      if (isExpanded && childrenToRender.length > 0) {
        rows.push(...renderTreeRows(childrenToRender, depth + 1))
      }
      if (isExpanded && !hasChildren && lazyLoaded && lazyLoaded.length === 0 && !isLoading) {
        rows.push(
          <tr key={node.material_code + '_empty'} className="border-b">
            <td className="py-1 pr-3 text-xs text-muted-foreground" style={{ paddingLeft: `${(depth + 1) * 20 + 8}px` }}>
              无子配方数据
            </td>
            <td colSpan={8} />
          </tr>
        )
      }
    })
    return rows
  }

  // Treemap数据
  const treemapData = bomSummary.slice(0, 30).map((b: any) => ({
    name: b.product_name,
    size: b.bom_theoretical_amt,
    variance: b.variance_pct,
  }))

  return (
    <div className="space-y-4 p-4">
      {/* 页面标题 */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Network className="h-6 w-6 text-purple-600" />
          <h1 className="text-xl font-bold">多级BOM成本穿透</h1>
        </div>
        <MonthPicker month={month} onChange={setMonth} />
      </div>

      {/* 核心指标 */}
      <div className="grid grid-cols-2 gap-3 md:grid-cols-4 lg:grid-cols-6">
        <MetricCard title="完工产品数" value={totalProducts} unit="个" />
        <MetricCard title="含多级BOM" value={multiLevelProducts} unit="个" status="warn" description="配方中包含半成品的产成品数" />
        <MetricCard title="BOM理论成本" value={totalBomTheoretical} format="currency" />
        <MetricCard title="BOM领用成本" value={totalBomIssue} format="currency" />
        <MetricCard title="差异金额" value={totalVariance} format="currency" status={totalVariance >= 0 ? 'warn' : 'bad'} />
        <MetricCard title="半成品依赖链" value={multiLevelChains.length} unit="条" description="成品→半成品的依赖关系数" />
      </div>

      {/* BOM成本结构Top15 */}
      <CollapsibleSection title="BOM成本结构Top15" subtitle="按理论成本排序的产成品BOM汇总">
        <ResponsiveContainer width="100%" height={350}>
          <BarChart data={bomChartData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis dataKey="name" tick={{ fontSize: 10 }} angle={-20} textAnchor="end" height={60} />
            <YAxis tickFormatter={(v) => `${(v / 10000).toFixed(0)}万`} tick={{ fontSize: 11 }} />
            <Tooltip formatter={(v: any) => formatCurrency(v)} />
            <Bar dataKey="理论成本" fill="#1677ff" />
            <Bar dataKey="领用成本" fill="#722ed1" />
          </BarChart>
        </ResponsiveContainer>
        <div className="mt-3">
          <FilterableTable
            data={bomSummary}
            searchKeys={['product_code', 'product_name']}
            searchPlaceholder="搜索产品..."
            sortOptions={[
              { key: 'bom_theoretical_amt', label: '理论成本' },
              { key: 'bom_issue_amt', label: '领用成本' },
              { key: 'variance_amt', label: '差异金额' },
              { key: 'variance_pct', label: '差异率' },
              { key: 'material_count', label: '材料数' },
            ]}
            columns={[
              { key: 'product_code', label: '产品编码' },
              { key: 'product_name', label: '产品名称', render: (b) => <span className="font-medium text-blue-600">{b.product_name}</span> },
              { key: 'material_count', label: '材料数', align: 'right' },
              { key: 'sub_product_count', label: '半成品数', align: 'right', render: (b) => b.sub_product_count > 0 ? <span className="text-purple-600 font-medium">{b.sub_product_count}</span> : '-' },
              { key: 'bom_theoretical_amt', label: '理论成本', align: 'right', render: (b) => formatCurrency(b.bom_theoretical_amt) },
              { key: 'bom_issue_amt', label: '领用成本', align: 'right', render: (b) => formatCurrency(b.bom_issue_amt) },
              { key: 'bom_unit_theoretical_cost', label: '单位理论成本', align: 'right', render: (b) => formatNumber(b.bom_unit_theoretical_cost) },
              { key: 'bom_unit_issue_cost', label: '单位领用成本', align: 'right', render: (b) => formatNumber(b.bom_unit_issue_cost) },
              { key: 'variance_amt', label: '差异金额', align: 'right', render: (b) => <span className={b.variance_amt >= 0 ? 'text-yellow-600' : 'text-red-600'}>{formatCurrency(b.variance_amt)}</span> },
              { key: 'variance_pct', label: '差异率', align: 'right', render: (b) => <span className={`font-medium ${varianceColorClass(b.variance_pct)}`}>{varianceText(b.variance_pct)}</span> },
            ]}
            onRowClick={(b) => setSelectedProduct(b.product_code)}
          />
        </div>
      </CollapsibleSection>

      {/* BOM成本Treemap */}
      <CollapsibleSection title="BOM成本分布Treemap" subtitle="按理论成本大小展示产成品BOM分布" defaultOpen={false}>
        <ResponsiveContainer width="100%" height={400}>
          <Treemap
            data={treemapData}
            dataKey="size"
            stroke="#fff"
            fill="#722ed1"
            content={<CustomTreemapContent />}
          />
        </ResponsiveContainer>
      </CollapsibleSection>

      {/* 产品选择器 */}
      <CollapsibleSection title="产品列表" subtitle={`${productList.length}个产品`}>
        <FilterableTable
          data={productList}
          searchKeys={['product_code', 'product_name']}
          searchPlaceholder="搜索产品..."
          sortOptions={[
            { key: 'theoretical_cost', label: '理论成本' },
            { key: 'actual_cost', label: '实际成本' },
            { key: 'inbound_quantity', label: '入库量' },
            { key: 'material_count', label: '材料数' },
          ]}
          columns={[
            { key: 'product_code', label: '产品编码' },
            { key: 'product_name', label: '产品名称', render: (p) => <span className="font-medium">{p.product_name}</span> },
            { key: 'category_minor', label: '品类' },
            { key: 'inbound_quantity', label: '入库量', align: 'right', render: (p) => formatNumber(p.inbound_quantity) },
            { key: 'theoretical_cost', label: '理论成本', align: 'right', render: (p) => formatCurrency(p.theoretical_cost) },
            { key: 'actual_cost', label: '实际成本', align: 'right', render: (p) => formatCurrency(p.actual_cost) },
            { key: 'material_count', label: '材料数', align: 'right' },
            { key: 'has_multi_level_bom', label: '多级BOM', align: 'center', render: (p) => p.has_multi_level_bom ? <span className="text-purple-600">✓</span> : '-' },
            { key: 'action', label: '', render: (p) => <button className="text-xs text-blue-600 hover:underline" onClick={(e) => { e.stopPropagation(); openProductModal(p.product_code) }}>查看BOM</button> },
          ]}
          onRowClick={(p) => openProductModal(p.product_code)}
        />
      </CollapsibleSection>

      {/* 半成品依赖链 */}
      <CollapsibleSection title="半成品依赖链" subtitle={`${multiLevelChains.length}条成品→半成品依赖关系`} defaultOpen={false}>
        <div className="mb-3 flex items-center gap-2">
          <Network className="h-4 w-4 text-purple-600" />
          <span className="text-sm text-muted-foreground">展示成品与半成品之间的多级BOM依赖关系，可快速定位半成品成本波动影响的成品范围</span>
        </div>
        <FilterableTable
          data={multiLevelChains}
          searchKeys={['finished_code', 'finished_name', 'sub_product_code', 'sub_product_name']}
          searchPlaceholder="搜索成品/半成品..."
          sortOptions={[
            { key: 'finished_name', label: '成品名称' },
            { key: 'sub_product_name', label: '半成品名称' },
          ]}
          columns={[
            { key: 'finished_code', label: '成品编码' },
            { key: 'finished_name', label: '成品名称', render: (c) => <span className="font-medium">{c.finished_name}</span> },
            { key: 'finished_recipe', label: '成品配方' },
            { key: 'arrow', label: '', render: () => <ChevronRight className="h-4 w-4 text-purple-600" /> },
            { key: 'sub_product_code', label: '半成品编码' },
            { key: 'sub_product_finished_name', label: '半成品名称', render: (c) => <span className="font-medium text-purple-600">{c.sub_product_finished_name || c.sub_product_name}</span> },
            { key: 'sub_product_recipe', label: '半成品配方', render: (c) => c.sub_product_recipe || '-' },
          ]}
        />
      </CollapsibleSection>

      {/* BOM树弹窗 */}
      {selectedProduct && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40" onClick={closeModal}>
          <div className="max-h-[85vh] w-[90vw] max-w-5xl overflow-hidden rounded-lg bg-white shadow-xl" onClick={e => e.stopPropagation()}>
            <div className="flex items-center justify-between border-b px-4 py-3">
              <div className="flex items-center gap-2">
                <GitBranch className="h-5 w-5 text-purple-600" />
                <h2 className="text-base font-semibold">
                  BOM树穿透 - {productData?.productList?.find((p: any) => p.product_code === selectedProduct)?.product_name || selectedProduct}
                </h2>
                <span className="text-xs text-muted-foreground">共{bomTree.length}个节点，最大{maxLevel}层</span>
              </div>
              <button onClick={closeModal} className="rounded p-1 hover:bg-muted">
                <X className="h-5 w-5" />
              </button>
            </div>
            <div className="max-h-[calc(85vh-60px)] overflow-auto p-4">
              {productLoading ? (
                <LoadingSpinner />
              ) : bomTree.length === 0 ? (
                <div className="py-8 text-center text-muted-foreground">该产品无配方数据</div>
              ) : (
                <div className="overflow-x-auto">
                  <table className="w-full text-sm">
                    <thead>
                      <tr className="border-b text-left text-muted-foreground">
                        <th className="pb-2 pr-3">物料名称</th>
                        <th className="pb-2 pr-3">编码</th>
                        <th className="pb-2 pr-3">单位</th>
                        <th className="pb-2 pr-3 text-right">理论量</th>
                        <th className="pb-2 pr-3 text-right">领用量</th>
                        <th className="pb-2 pr-3 text-right">理论金额</th>
                        <th className="pb-2 pr-3 text-right">领用金额</th>
                        <th className="pb-2 pr-3 text-right">差异金额</th>
                      </tr>
                    </thead>
                    <tbody>
                      {renderTreeRows(bomTreeData, 0)}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

function CustomTreemapContent(props: any) {
  const { x, y, width, height, name, size, variance } = props
  if (width < 50 || height < 30) return null
  const fill = Math.abs(variance || 0) <= 3 ? '#52c41a' : Math.abs(variance || 0) <= 10 ? '#faad14' : '#f5222d'
  return (
    <g>
      <rect x={x} y={y} width={width} height={height} stroke="#fff" fill={fill} fillOpacity={0.7} />
      <text x={x + 4} y={y + 16} fontSize={11} fill="#333">
        {name?.length > 10 ? name.slice(0, 10) + '...' : name}
      </text>
      <text x={x + 4} y={y + 30} fontSize={10} fill="#666">
        ¥{(size / 10000).toFixed(1)}万
      </text>
    </g>
  )
}
