import { computed, onMounted, ref, watch } from 'vue'
import { ElButton, ElInput, ElPagination, ElTable, ElTableColumn } from 'element-plus'

import BudgetTrendChart from '../../components/charts/BudgetTrendChart.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import { fetchBudgetSummary } from '../../services/budgets.js'
import { fetchEmployeeMeta } from '../../services/employees.js'
import {
  canEditBudgetCenter,
  canSwitchBudgetDepartments,
  isBudgetMonitorUser,
  isExecutiveUser
} from '../../utils/accessControl.js'
import {
  BUDGET_QUARTER_OPTIONS,
  BUDGET_VISIBLE_EXPENSE_TYPE_OPTIONS,
  BUDGET_YEAR_OPTIONS,
  resolveBudgetExpenseTypeLabel
} from '../../utils/budgetOntology.js'

const FALLBACK_DEPARTMENTS = [
  { code: 'MARKET-DEPT', name: '市场部', costCenter: 'CC-4100' },
  { code: 'FINANCE-DEPT', name: '财务部', costCenter: 'CC-2100' },
  { code: 'TECH-DEPT', name: '技术部', costCenter: 'CC-6100' },
  { code: 'HR-DEPT', name: '人力资源部', costCenter: 'CC-3200' },
  { code: 'PRODUCTION-DEPT', name: '生产部', costCenter: 'CC-7200' },
  { code: 'PRESIDENT-OFFICE', name: '总裁办', costCenter: 'CC-1000' }
]

const EXPENSE_BUDGET_SEED = {
  travel: { total: 600000, used: 242300, occupied: 150000, warning: 80, action: '提醒' },
  communication: { total: 120000, used: 38600, occupied: 18000, warning: 70, action: '正常' },
  meal: { total: 420000, used: 168200, occupied: 118000, warning: 80, action: '管控' },
  office: { total: 180000, used: 68500, occupied: 32000, warning: 70, action: '正常' }
}

const DEFAULT_EXPENSE_BUDGET = {
  total: 100000,
  used: 0,
  occupied: 0,
  warning: 70,
  action: '正常'
}

const EXPENSE_BLUEPRINTS = BUDGET_VISIBLE_EXPENSE_TYPE_OPTIONS.map((option) => ({
  ...DEFAULT_EXPENSE_BUDGET,
  ...EXPENSE_BUDGET_SEED[option.value],
  budgetSubjectCode: option.value,
  expenseType: option.label
}))

const currency = (value) =>
  Number(value || 0).toLocaleString('zh-CN', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  })

const comparison = (value, direction) => ({
  value,
  tone: direction === 'down' ? 'down' : 'up',
  icon: direction === 'down' ? 'mdi mdi-arrow-down' : 'mdi mdi-arrow-up'
})

const BUDGET_PAGE_SIZE_OPTIONS = [5, 10]
const ALERT_DATE_FORMATTER = new Intl.DateTimeFormat('zh-CN', {
  month: '2-digit',
  day: '2-digit'
})
const BUDGET_COMPILED_TIME_FORMATTER = new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  hour12: false
})

const normalizePeriodKey = (year, quarter) => {
  const normalizedYear = String(year || '').replace(/[^\d]/g, '') || '2026'
  const normalizedQuarter = BUDGET_QUARTER_OPTIONS.includes(String(quarter || '').trim())
    ? String(quarter || '').trim()
    : BUDGET_QUARTER_OPTIONS[0]
  return `${normalizedYear}${normalizedQuarter}`
}

const parsePercent = (value, fallback = 80) => {
  const parsed = Number(String(value || '').replace(/[^\d.-]/g, ''))
  return Number.isFinite(parsed) ? parsed : fallback
}

const clampPercent = (value) => Math.min(100, Math.max(0, Number(value) || 0))

function buildThresholds(warning) {
  const alert = clampPercent(warning)
  return {
    reminder: clampPercent(alert - 10),
    alert,
    risk: clampPercent(alert + 10)
  }
}

function formatBudgetCompiledAt(value) {
  if (!value) return '—'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return '—'
  return BUDGET_COMPILED_TIME_FORMATTER.format(date).replace(/\//g, '-')
}

function resolveBudgetCompiler(item) {
  return String(
    item?.compiler
      || item?.compiled_by
      || item?.compiledBy
      || item?.created_by
      || item?.createdBy
      || item?.owner_name
      || item?.ownerName
      || '预算编制助手'
  ).trim()
}

function resolveBudgetReviewer(item) {
  return String(
    item?.reviewer
      || item?.reviewed_by
      || item?.reviewedBy
      || item?.approved_by
      || item?.approvedBy
      || item?.auditor
      || item?.updated_by
      || item?.updatedBy
      || '高级财务人员'
  ).trim()
}

function normalizeBudgetAllocationRow(item) {
  const balance = item?.balance || {}
  const totalAmount = Number(balance.total_amount ?? item?.original_amount ?? 0)
  const usedAmount = Number(balance.consumed_amount ?? 0)
  const occupiedAmount = Number(balance.reserved_amount ?? 0)
  const leftAmount = Number(balance.available_amount ?? 0)
  const rate = Number(balance.usage_rate ?? 0)
  const warning = parsePercent(item?.warning_threshold, 80)
  const thresholds = buildThresholds(warning)
  const budgetSubjectCode = String(item?.subject_code || '').trim()
  const expenseType = item?.subject_name || resolveBudgetExpenseTypeLabel(budgetSubjectCode, budgetSubjectCode)

  return {
    allocationId: item?.id || '',
    budgetNo: item?.budget_no || '',
    budgetSubjectCode,
    compiledAt: formatBudgetCompiledAt(item?.created_at || item?.createdAt || item?.updated_at || item?.updatedAt),
    compiler: resolveBudgetCompiler(item),
    reviewer: resolveBudgetReviewer(item),
    expenseType,
    totalAmount,
    usedAmount,
    occupiedAmount,
    leftAmount,
    rate,
    rateTone: rate >= thresholds.risk ? 'danger' : rate >= thresholds.alert ? 'warn' : 'ok',
    reminderThreshold: thresholds.reminder,
    alertThreshold: thresholds.alert,
    riskThreshold: thresholds.risk,
    reminderLine: `${thresholds.reminder}%`,
    alertLine: `${thresholds.alert}%`,
    riskLine: `${thresholds.risk}%`,
    total: currency(totalAmount),
    used: currency(usedAmount),
    occupied: currency(occupiedAmount),
    left: currency(leftAmount)
  }
}

function normalizeBudgetUsageData(rows) {
  const source = Array.isArray(rows) ? rows : []
  return {
    labels: source.map((item) => item.expenseType || '未分类'),
    budget: source.map((item) => Number(item.totalAmount || 0)),
    used: source.map((item) => Number(item.usedAmount || 0)),
    occupied: source.map((item) => Number(item.occupiedAmount || 0)),
    available: source.map((item) => Math.max(Number(item.leftAmount || 0), 0))
  }
}

function formatAlertDate(value) {
  if (!value) return ''
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return ''
  return ALERT_DATE_FORMATTER.format(date)
}

function normalizeBudgetWarning(item) {
  const subjectName = item?.subject_name || resolveBudgetExpenseTypeLabel(item?.subject_code, item?.subject_code)
  const departmentName = item?.department_name || ''
  const usageRate = Number(item?.usage_rate || 0)
  const warningThreshold = Number(item?.warning_threshold || 0)
  const tone = item?.severity === 'danger' ? 'danger' : 'warn'
  return {
    id: item?.allocation_id || `${departmentName}-${subjectName}-${item?.period_key || ''}`,
    title: departmentName ? `${departmentName} · ${subjectName}` : subjectName,
    desc: item?.message || `使用率已达 ${usageRate}%，达到预警线 ${warningThreshold}%。`,
    date: formatAlertDate(item?.occurred_at),
    tone
  }
}

export default {
  name: 'BudgetCenterView',
  props: {
    currentUser: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['openAssistant'],
  components: {
    BudgetTrendChart,
    EnterpriseSelect,
    ElButton,
    ElInput,
    ElPagination,
    ElTable,
    ElTableColumn
  },
  setup(props, { emit }) {
    const departments = ref(FALLBACK_DEPARTMENTS)
    const activeDepartmentCode = ref(FALLBACK_DEPARTMENTS[0].code)
    const departmentKeyword = ref('')
    const filters = ref({
      year: '2026',
      quarter: 'Q1',
      expenseType: '全部',
      status: '全部'
    })
    const budgetPage = ref(1)
    const budgetPageSize = ref(5)
    const budgetTableKeyword = ref('')
    const budgetRows = ref([])
    const budgetSummary = ref(null)
    const budgetLoading = ref(false)
    const budgetError = ref('')
    const canEditBudget = computed(() => canEditBudgetCenter(props.currentUser))
    const canSwitchDepartments = computed(() => canSwitchBudgetDepartments(props.currentUser))
    const isDepartmentBudgetMonitor = computed(
      () => isBudgetMonitorUser(props.currentUser) && !canSwitchDepartments.value && !isExecutiveUser(props.currentUser)
    )
    const yearOptions = BUDGET_YEAR_OPTIONS.map((year) => ({ label: `${year}年度`, value: year }))
    const budgetPageSizeOptions = BUDGET_PAGE_SIZE_OPTIONS.map((size) => ({ label: `${size} 条/页`, value: size }))
    const departmentOptions = computed(() =>
      departments.value.map((department) => ({
        label: department.name,
        value: department.code
      }))
    )

    const activeDepartment = computed(() =>
      departments.value.find((item) => item.code === activeDepartmentCode.value) || departments.value[0]
    )

    const activeDepartmentName = computed(() => activeDepartment.value?.name || '市场部')
    const currentUserDepartmentName = computed(() =>
      String(props.currentUser?.departmentName || props.currentUser?.department || '').trim()
    )
    const currentUserCostCenter = computed(() =>
      String(props.currentUser?.costCenter || props.currentUser?.cost_center || '').trim()
    )
    const departmentRows = computed(() => budgetRows.value)
    const filteredBudgetRows = computed(() => {
      const keyword = budgetTableKeyword.value.trim().toLowerCase()
      return departmentRows.value
        .filter((row) => {
          if (!keyword) return true
          return [
            row.compiledAt,
            row.compiler,
            row.reviewer,
            row.expenseType,
            row.total,
            row.used,
            row.occupied,
            row.left,
            `${row.rate}%`,
            row.reminderLine,
            row.alertLine,
            row.riskLine
          ].some((value) => String(value || '').toLowerCase().includes(keyword))
        })
        .filter((row) => filters.value.expenseType === '全部' || row.expenseType === filters.value.expenseType)
        .filter((row) => {
          if (filters.value.status === '全部') return true
          if (filters.value.status === '预警') return row.rateTone === 'warn'
          if (filters.value.status === '管控') return row.rateTone === 'danger'
          return row.rateTone === 'ok'
        })
    })
    const totalBudgetRows = computed(() => filteredBudgetRows.value.length)
    const totalBudgetPages = computed(() =>
      Math.max(1, Math.ceil(totalBudgetRows.value / Number(budgetPageSize.value || 5)))
    )
    const currentBudgetPage = computed(() =>
      Math.min(Math.max(1, budgetPage.value), totalBudgetPages.value)
    )
    const budgetPageNumbers = computed(() =>
      Array.from({ length: totalBudgetPages.value }, (_, index) => index + 1)
    )
    const visibleBudgetRows = computed(() => {
      const pageSize = Number(budgetPageSize.value || 5)
      const start = (currentBudgetPage.value - 1) * pageSize
      return filteredBudgetRows.value.slice(start, start + pageSize)
    })

    const totals = computed(() => {
      const rows = departmentRows.value
      const total = rows.reduce((sum, item) => sum + item.totalAmount, 0)
      const used = rows.reduce((sum, item) => sum + item.usedAmount, 0)
      const occupied = rows.reduce((sum, item) => sum + item.occupiedAmount, 0)
      return {
        total,
        used,
        occupied,
        left: Math.max(total - used - occupied, 0)
      }
    })

    const budgetMetrics = computed(() => [
      {
        label: '预算总额',
        value: `¥${currency(totals.value.total)}`,
        yoy: comparison('+8.42%', 'up'),
        mom: comparison('+2.16%', 'up'),
        tone: 'primary',
        icon: 'mdi mdi-wallet-outline'
      },
      {
        label: '已发生',
        value: `¥${currency(totals.value.used)}`,
        yoy: comparison('+12.68%', 'up'),
        mom: comparison('+4.35%', 'up'),
        tone: 'info',
        icon: 'mdi mdi-chart-line'
      },
      {
        label: '已占用',
        value: `¥${currency(totals.value.occupied)}`,
        yoy: comparison('+6.37%', 'up'),
        mom: comparison('-1.84%', 'down'),
        tone: 'warning',
        icon: 'mdi mdi-briefcase-check-outline'
      },
      {
        label: '剩余可用',
        value: `¥${currency(totals.value.left)}`,
        yoy: comparison('-3.26%', 'down'),
        mom: comparison('-2.08%', 'down'),
        tone: 'primary',
        icon: 'mdi mdi-cash'
      }
    ])

    const visibleDepartments = computed(() => {
      const keyword = departmentKeyword.value.trim()
      return departments.value
        .filter((item) => !keyword || item.name.includes(keyword) || item.code.includes(keyword))
        .map((item) => ({
          ...item,
          icon: item.code === activeDepartmentCode.value ? 'mdi mdi-account-group-outline' : 'mdi mdi-domain'
        }))
    })

    const warnings = computed(() =>
      (Array.isArray(budgetSummary.value?.warnings) ? budgetSummary.value.warnings : [])
        .map(normalizeBudgetWarning)
    )

    const budgetUsageData = computed(() =>
      normalizeBudgetUsageData(departmentRows.value)
    )

    function openBudgetAssistant() {
      if (!canEditBudget.value) return
      emit('openAssistant', {
        source: 'budget',
        sessionType: 'budget',
        prompt: '',
        files: [],
        conversation: null
      })
    }


    function goToBudgetPage(page) {
      budgetPage.value = Math.min(Math.max(Number(page) || 1, 1), totalBudgetPages.value)
    }

    function changeBudgetPage(direction) {
      goToBudgetPage(currentBudgetPage.value + direction)
    }

    function resolveScopedDepartments(options) {
      if (!isDepartmentBudgetMonitor.value) {
        return options
      }

      const userDepartment = currentUserDepartmentName.value
      const userCostCenter = currentUserCostCenter.value
      const scoped = options.filter((item) => {
        if (userCostCenter && item.costCenter === userCostCenter) return true
        return userDepartment && item.name === userDepartment
      })

      if (scoped.length) {
        return scoped
      }

      return [
        {
          id: '',
          code: userCostCenter || userDepartment || 'CURRENT-DEPARTMENT',
          name: userDepartment || '当前部门',
          costCenter: userCostCenter
        }
      ]
    }

    async function loadDepartments() {
      try {
        const payload = await fetchEmployeeMeta()
        const options = Array.isArray(payload?.organizationOptions) ? payload.organizationOptions : []
        const nextDepartments = options
          .filter((item) => item?.code && item?.name)
          .map((item) => ({
            id: String(item.id || ''),
            code: String(item.code),
            name: String(item.name),
            costCenter: String(item.costCenter || '')
          }))
        const scopedDepartments = resolveScopedDepartments(nextDepartments)

        if (scopedDepartments.length) {
          departments.value = scopedDepartments
          if (!scopedDepartments.some((item) => item.code === activeDepartmentCode.value)) {
            activeDepartmentCode.value = scopedDepartments[0].code
          }
        }
        await loadBudgetData()
      } catch (error) {
        console.warn('Failed to load budget departments from employee meta:', error)
        await loadBudgetData()
      }
    }

    async function loadBudgetData() {
      const department = activeDepartment.value || {}
      budgetLoading.value = true
      budgetError.value = ''
      try {
        const payload = await fetchBudgetSummary({
          year: filters.value.year,
          period: normalizePeriodKey(filters.value.year, filters.value.quarter),
          department_id: department.id || '',
          cost_center: department.costCenter || ''
        })
        const allocations = Array.isArray(payload?.allocations) ? payload.allocations : []
        budgetSummary.value = payload || null
        budgetRows.value = allocations.map(normalizeBudgetAllocationRow)
      } catch (error) {
        budgetError.value = error?.message || 'Failed to load budget data'
        budgetSummary.value = null
        budgetRows.value = []
        console.warn('Failed to load budget data:', error)
      } finally {
        budgetLoading.value = false
      }
    }

    onMounted(() => {
      void loadDepartments()
    })

    watch(
      [
        activeDepartmentCode,
        budgetPageSize,
        () => filters.value.year,
        () => filters.value.quarter,
        () => filters.value.expenseType,
        () => filters.value.status,
        budgetTableKeyword
      ],
      () => {
        budgetPage.value = 1
      }
    )

    watch(
      [activeDepartmentCode, () => filters.value.year, () => filters.value.quarter],
      () => {
        void loadBudgetData()
      }
    )

    watch(totalBudgetPages, (pages) => {
      if (budgetPage.value > pages) {
        budgetPage.value = pages
      }
    })

    return {
      activeDepartmentCode,
      activeDepartmentName,
      budgetError,
      budgetLoading,
      budgetMetrics,
      budgetPage: currentBudgetPage,
      budgetPageNumbers,
      budgetPageSize,
      budgetPageSizeOptions,
      budgetTableKeyword,
      canEditBudget,
      canSwitchDepartments,
      changeBudgetPage,
      departmentKeyword,
      departments,
      expenseTypes: ['全部', ...EXPENSE_BLUEPRINTS.map((item) => item.expenseType)],
      filters,
      openBudgetAssistant,
      quarters: BUDGET_QUARTER_OPTIONS,
      departmentOptions,
      statuses: ['全部', '正常', '预警', '管控'],
      goToBudgetPage,
      totalBudgetPages,
      totalBudgetRows,
      budgetUsageData,
      visibleBudgetRows,
      visibleDepartments,
      warnings,
      yearOptions,
      years: BUDGET_YEAR_OPTIONS
    }
  }
}
