<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { accountingService, type AccountTransaction, type FinancialAccount } from '@/modules/accounting/services/accountingService'
import { reportService, type CrmReport, type InventoryReport, type OverviewReport, type SalesReport } from '@/modules/reports/services/reportService'
import { notificationService, type NotificationPayload } from '@/modules/notification/services/notificationService'
import { companyService, type Company } from '@/modules/settings/services/companyService'
import { getApiErrorMessage } from '@/services/api'

const today = new Date()
const startDate = new Date(today.getFullYear(), today.getMonth(), 1).toISOString().slice(0, 10)
const endDate = new Date(today.getFullYear(), today.getMonth() + 1, 0).toISOString().slice(0, 10)

const overview = ref<OverviewReport | null>(null)
const sales = ref<SalesReport | null>(null)
const inventory = ref<InventoryReport | null>(null)
const crm = ref<CrmReport | null>(null)
const accounts = ref<FinancialAccount[]>([])
const ledgerTransactions = ref<AccountTransaction[]>([])
const notifications = ref<NotificationPayload | null>(null)
const company = ref<Company | null>(null)
const loading = ref(false)
const error = ref('')
const lastUpdatedAt = ref('')
const currentCompanyId = ref(localStorage.getItem('current_company_id') || '')

const maxDailySale = computed(() => {
  return Math.max(...(sales.value?.by_day.map((day) => Number(day.total)) || [0]), 1)
})

const topSalesDays = computed(() => {
  return [...(sales.value?.by_day || [])].sort((a, b) => Number(b.total) - Number(a.total)).slice(0, 5)
})

const enabledFeatures = computed(() => {
  return new Set(company.value?.subscription?.plan.features?.map((feature) => feature.slug) || [])
})

const hasReports = computed(() => enabledFeatures.value.has('reports'))
const hasNotifications = computed(() => enabledFeatures.value.has('notification'))
const hasAccounting = computed(() => enabledFeatures.value.has('accounting'))
const hasInvoice = computed(() => enabledFeatures.value.has('invoice'))
const hasPos = computed(() => enabledFeatures.value.has('pos'))
const hasInventory = computed(() => enabledFeatures.value.has('inventory'))
const hasCrm = computed(() => enabledFeatures.value.has('crm'))
const activePlanName = computed(() => company.value?.subscription?.plan.name || 'No active plan')
const subscriptionStatus = computed(() => company.value?.subscription?.status || 'none')
const moduleLinks = computed(() => [
  { label: 'POS Sale', to: '/pos', enabled: hasPos.value },
  { label: 'Inventory', to: '/inventory', enabled: hasInventory.value },
  { label: 'Invoices', to: '/invoices', enabled: hasInvoice.value },
  { label: 'CRM', to: '/crm', enabled: hasCrm.value },
  { label: 'Finance', to: '/finance', enabled: hasAccounting.value },
  { label: 'Reports', to: '/reports', enabled: hasReports.value },
])

const totalAccountBalance = computed(() => {
  return accounts.value.reduce((total, account) => total + Number(account.current_balance || 0), 0)
})

const monthlyCashIn = computed(() => {
  return ledgerTransactions.value
    .filter((transaction) => transaction.direction === 'inflow')
    .reduce((total, transaction) => total + Number(transaction.amount || 0), 0)
})

const monthlyCashOut = computed(() => {
  return ledgerTransactions.value
    .filter((transaction) => transaction.direction === 'outflow')
    .reduce((total, transaction) => total + Number(transaction.amount || 0), 0)
})

const netCashflow = computed(() => monthlyCashIn.value - monthlyCashOut.value)
const cashflowClass = computed(() => netCashflow.value >= 0 ? 'text-[#087443]' : 'text-danger')
const unreadNotifications = computed(() => notifications.value?.summary.unread_notifications || 0)
const activeAlerts = computed(() => notifications.value?.summary.active_alerts || 0)

function money(value: string | number | undefined) {
  return Number(value || 0).toFixed(2)
}

function barWidth(value: string | number) {
  return `${Math.max((Number(value || 0) / maxDailySale.value) * 100, 3)}%`
}

function statusClass(status: string) {
  if (status === 'active' || status === 'trialing') {
    return 'status-pill'
  }

  if (status === 'past_due' || status === 'cancelled' || status === 'expired') {
    return 'status-pill danger'
  }

  return 'status-pill off'
}

function alertClass(type: string) {
  return type === 'danger' || type === 'error' ? 'status-pill danger' : type === 'warning' ? 'status-pill warn' : 'status-pill off'
}

function safeRoute(url: string | null | undefined) {
  return url?.startsWith('/') ? url : '/notifications'
}

function updateLastUpdated() {
  lastUpdatedAt.value = new Date().toLocaleTimeString([], {
    hour: '2-digit',
    minute: '2-digit',
  })
}

async function load() {
  if (!currentCompanyId.value) {
    error.value = 'Select a company workspace first.'
    return
  }

  loading.value = true
  error.value = ''

  try {
    company.value = await companyService.current()

    if (hasReports.value) {
      const [overviewData, salesData, inventoryData, crmData] = await Promise.all([
        reportService.overview(startDate, endDate),
        reportService.sales(startDate, endDate),
        reportService.inventory(),
        reportService.crm(),
      ])
      overview.value = overviewData
      sales.value = salesData
      inventory.value = inventoryData
      crm.value = crmData
    } else {
      overview.value = null
      sales.value = null
      inventory.value = null
      crm.value = null
    }

    if (hasAccounting.value) {
      const [accountData, transactionPage] = await Promise.all([
        accountingService.accounts(),
        accountingService.transactions({
          date_from: startDate,
          date_to: endDate,
          page: 1,
          per_page: 100,
        }),
      ])
      accounts.value = accountData
      ledgerTransactions.value = transactionPage.data
    } else {
      accounts.value = []
      ledgerTransactions.value = []
    }

    notifications.value = hasNotifications.value ? await notificationService.all() : null
    updateLastUpdated()
  } catch (apiError) {
    error.value = getApiErrorMessage(apiError, 'Unable to load dashboard data.')
  } finally {
    loading.value = false
  }
}

onMounted(load)
</script>

<template>
  <section class="stack">
    <article class="panel">
      <div class="topbar" style="margin-bottom: 0">
        <div>
          <h2>Dashboard</h2>
          <p v-if="company">{{ company.name }} - {{ activePlanName }}</p>
          <div v-if="company" class="inline-actions">
            <span :class="statusClass(subscriptionStatus)">{{ subscriptionStatus }}</span>
            <span v-if="lastUpdatedAt">Updated {{ lastUpdatedAt }}</span>
          </div>
          <p v-if="overview">{{ overview.period.start_date }} to {{ overview.period.end_date }}</p>
          <p v-if="loading">Loading dashboard...</p>
          <p v-if="error" class="error">{{ error }}</p>
        </div>
        <button class="button ghost" type="button" :disabled="loading || !currentCompanyId" @click="load">Refresh</button>
      </div>
    </article>

    <section class="grid compact-grid">
      <article class="metric">
        <span>POS Sales</span>
        <strong>{{ hasReports ? 'BDT ' + money(overview?.sales.total) : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Invoice Due</span>
        <strong>{{ hasReports ? 'BDT ' + money(overview?.invoices.due) : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Open Leads</span>
        <strong>{{ hasReports ? overview?.crm.open_leads || 0 : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Unread Notifications</span>
        <strong>{{ hasNotifications ? unreadNotifications : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Active Alerts</span>
        <strong>{{ hasNotifications ? activeAlerts : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Account Balance</span>
        <strong>{{ hasAccounting ? 'BDT ' + money(totalAccountBalance) : 'Locked' }}</strong>
      </article>
      <article class="metric">
        <span>Net Cashflow</span>
        <strong :class="cashflowClass">{{ hasAccounting ? 'BDT ' + money(netCashflow) : 'Locked' }}</strong>
      </article>
    </section>

    <section class="grid wide-grid">
      <article class="panel stack">
        <h2>Finance Snapshot</h2>
        <p v-if="!hasAccounting">Accounting is not enabled on the current plan.</p>
        <div class="list-item">
          <div>
            <strong>Cash In</strong>
            <span>Ledger inflow this month</span>
          </div>
          <span>BDT {{ money(monthlyCashIn) }}</span>
        </div>
        <div class="list-item">
          <div>
            <strong>Cash Out</strong>
            <span>Ledger outflow this month</span>
          </div>
          <span>BDT {{ money(monthlyCashOut) }}</span>
        </div>
        <div class="list-item">
          <div>
            <strong>Accounts</strong>
            <span>{{ accounts.length }} active accounts</span>
          </div>
          <span>BDT {{ money(totalAccountBalance) }}</span>
        </div>
        <RouterLink v-if="hasAccounting" class="button ghost" to="/finance">Open Finance</RouterLink>
      </article>

      <article class="panel stack">
        <h2>Business Snapshot</h2>
        <p v-if="!hasReports">Reports are not enabled on the current plan.</p>
        <div class="list-item">
          <div>
            <strong>Payments Received</strong>
            <span>Invoice collections this month</span>
          </div>
          <span>BDT {{ money(overview?.payments.received) }}</span>
        </div>
        <div class="list-item">
          <div>
            <strong>Purchase Cost</strong>
            <span>Inventory purchase spend</span>
          </div>
          <span>BDT {{ money(overview?.purchases.total) }}</span>
        </div>
        <div class="list-item">
          <div>
            <strong>Stock Value</strong>
            <span>{{ overview?.inventory.products || 0 }} products</span>
          </div>
          <span>BDT {{ money(overview?.inventory.stock_value) }}</span>
        </div>
        <div class="list-item">
          <div>
            <strong>Pipeline Value</strong>
            <span>{{ overview?.crm.total_leads || 0 }} total leads</span>
          </div>
          <span>BDT {{ money(overview?.crm.pipeline_value) }}</span>
        </div>
      </article>

      <article class="panel stack">
        <h2>Sales Trend</h2>
        <p v-if="!hasReports">Enable Reports to view sales trend.</p>
        <div v-for="day in topSalesDays" :key="day.date" class="stack">
          <div class="list-item">
            <div>
              <strong>{{ day.date }}</strong>
              <span>{{ day.count }} sales</span>
            </div>
            <span>BDT {{ day.total }}</span>
          </div>
          <div class="h-2 rounded-lg bg-[#d9e2ef]">
            <div class="h-2 rounded-lg bg-brand" :style="{ width: barWidth(day.total) }"></div>
          </div>
        </div>
        <p v-if="topSalesDays.length === 0 && !loading">No sales recorded this month.</p>
        <RouterLink v-if="hasReports" class="button ghost" to="/reports">Open Reports</RouterLink>
      </article>

      <article class="panel stack">
        <h2>Needs Attention</h2>
        <p v-if="!hasNotifications">Notifications are not enabled on the current plan.</p>
        <div v-for="alert in notifications?.alerts.slice(0, 5)" :key="alert.id" class="list-item">
          <div>
            <strong>{{ alert.title }}</strong>
            <span>{{ alert.message }}</span>
            <span :class="alertClass(alert.type)">{{ alert.category }}</span>
          </div>
          <RouterLink class="button ghost" :to="safeRoute(alert.action_url)">Open</RouterLink>
        </div>
        <p v-if="!notifications?.alerts.length && !loading">No live alerts.</p>
        <RouterLink v-if="hasNotifications" class="button ghost" to="/notifications">Open Notifications</RouterLink>
      </article>

      <article class="panel stack">
        <h2>Operations</h2>
        <div class="grid compact-grid">
          <template v-for="module in moduleLinks" :key="module.to">
            <RouterLink v-if="module.enabled" class="button ghost" :to="module.to">{{ module.label }}</RouterLink>
            <span v-else class="button ghost" aria-disabled="true">{{ module.label }} Locked</span>
          </template>
        </div>
        <div class="list-item">
          <div>
            <strong>Low Stock</strong>
            <span>{{ hasReports ? inventory?.summary.low_stock || 0 : 'Locked' }} products need restock</span>
          </div>
          <RouterLink v-if="hasInventory" class="button ghost" to="/inventory">Review</RouterLink>
        </div>
        <div class="list-item">
          <div>
            <strong>Follow Ups</strong>
            <span>{{ hasReports ? crm?.upcoming_follow_ups.length || 0 : 'Locked' }} scheduled CRM follow-ups</span>
          </div>
          <RouterLink v-if="hasCrm" class="button ghost" to="/crm">Review</RouterLink>
        </div>
      </article>
    </section>
  </section>
</template>
