<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { getApiErrorMessage } from '@/services/api'
import { reportService, type CrmReport, type InventoryReport, type OverviewReport, type SalesReport } from '@/modules/reports/services/reportService'

const today = new Date()
const startDate = ref(new Date(today.getFullYear(), today.getMonth(), 1).toISOString().slice(0, 10))
const endDate = ref(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 loading = ref(false)
const error = 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 maxPaymentMethod = computed(() => {
  return Math.max(...(sales.value?.payment_methods.map((method) => Number(method.total)) || [0]), 1)
})
const maxPipelineStage = computed(() => {
  return Math.max(...(crm.value?.stages.map((stage) => Number(stage.value)) || [0]), 1)
})
const grossCashFlow = computed(() => {
  return Number(overview.value?.payments.received || 0) + Number(overview.value?.sales.paid || 0) - Number(overview.value?.purchases.total || 0)
})
const collectionRate = computed(() => {
  const invoiceTotal = Number(overview.value?.invoices.total || 0)

  if (!invoiceTotal) {
    return 0
  }

  return Math.min((Number(overview.value?.invoices.paid || 0) / invoiceTotal) * 100, 100)
})
const rangeDays = computed(() => {
  const start = new Date(startDate.value)
  const end = new Date(endDate.value)
  const diff = end.getTime() - start.getTime()

  return Number.isFinite(diff) ? Math.max(Math.round(diff / 86_400_000) + 1, 0) : 0
})

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

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

function paymentLabel(value: string) {
  return value
    .split('_')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ')
}

function setPreset(preset: 'month' | 'last_30' | 'quarter') {
  const base = new Date()
  let start = new Date(base.getFullYear(), base.getMonth(), 1)
  let end = new Date(base.getFullYear(), base.getMonth() + 1, 0)

  if (preset === 'last_30') {
    start = new Date(base)
    start.setDate(base.getDate() - 29)
    end = base
  }

  if (preset === 'quarter') {
    const quarterStartMonth = Math.floor(base.getMonth() / 3) * 3
    start = new Date(base.getFullYear(), quarterStartMonth, 1)
    end = new Date(base.getFullYear(), quarterStartMonth + 3, 0)
  }

  startDate.value = start.toISOString().slice(0, 10)
  endDate.value = end.toISOString().slice(0, 10)
  void load()
}

function printReport() {
  window.print()
}

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

  if (startDate.value > endDate.value) {
    error.value = 'Start date must be before end date.'
    return
  }

  loading.value = true
  error.value = ''

  try {
    const [overviewData, salesData, inventoryData, crmData] = await Promise.all([
      reportService.overview(startDate.value, endDate.value),
      reportService.sales(startDate.value, endDate.value),
      reportService.inventory(),
      reportService.crm(),
    ])
    overview.value = overviewData
    sales.value = salesData
    inventory.value = inventoryData
    crm.value = crmData
  } catch (reportError) {
    error.value = getApiErrorMessage(reportError, 'Unable to load reports.')
  } finally {
    loading.value = false
  }
}

onMounted(load)
</script>

<template>
  <section class="stack">
    <article class="panel">
      <div class="report-toolbar">
        <div>
          <h2>Reports</h2>
          <p v-if="overview" class="muted">{{ overview.period.start_date }} to {{ overview.period.end_date }} - {{ rangeDays }} days</p>
          <p v-if="loading" class="muted">Loading reports...</p>
          <p v-if="error" class="error">{{ error }}</p>
        </div>
        <form class="inline-actions" @submit.prevent="load">
          <div class="field">
            <label for="report_start">Start</label>
            <input id="report_start" v-model="startDate" type="date" />
          </div>
          <div class="field">
            <label for="report_end">End</label>
            <input id="report_end" v-model="endDate" type="date" />
          </div>
          <button class="button primary" type="submit" :disabled="loading || !currentCompanyId">Apply</button>
          <button class="button ghost" type="button" :disabled="loading" @click="setPreset('month')">This Month</button>
          <button class="button ghost" type="button" :disabled="loading" @click="setPreset('last_30')">30 Days</button>
          <button class="button ghost" type="button" :disabled="loading" @click="setPreset('quarter')">Quarter</button>
          <button class="button ghost no-print" type="button" :disabled="loading || !overview" @click="printReport">Print</button>
        </form>
      </div>
    </article>

    <section class="grid compact-grid">
      <article class="metric">
        <span>POS Sales</span>
        <strong>BDT {{ money(overview?.sales.total) }}</strong>
        <small>{{ overview?.sales.count || 0 }} completed sales</small>
      </article>
      <article class="metric">
        <span>Invoice Due</span>
        <strong>BDT {{ money(overview?.invoices.due) }}</strong>
        <small>{{ collectionRate.toFixed(0) }}% collected</small>
      </article>
      <article class="metric">
        <span>Payments</span>
        <strong>BDT {{ money(overview?.payments.received) }}</strong>
        <small>Invoice payment inflow</small>
      </article>
      <article class="metric">
        <span>Purchases</span>
        <strong>BDT {{ money(overview?.purchases.total) }}</strong>
        <small>{{ overview?.purchases.count || 0 }} received purchases</small>
      </article>
      <article class="metric">
        <span>Cash Flow</span>
        <strong>BDT {{ money(grossCashFlow) }}</strong>
        <small>POS paid + payments - purchases</small>
      </article>
    </section>

    <section class="grid wide-grid">
      <article class="panel stack">
        <h2>Daily Sales</h2>
        <div v-for="day in sales?.by_day" :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="chart-track">
            <div class="chart-bar" :style="{ width: barWidth(day.total) }"></div>
          </div>
        </div>
        <p v-if="sales?.by_day.length === 0">No POS sales in this period.</p>
      </article>

      <article class="panel stack">
        <h2>Payment Methods</h2>
        <div v-for="method in sales?.payment_methods" :key="method.payment_method" class="stack">
          <div class="list-item">
            <div>
              <strong>{{ paymentLabel(method.payment_method) }}</strong>
              <span>{{ method.count }} sales</span>
            </div>
            <span>BDT {{ method.total }}</span>
          </div>
          <div class="chart-track">
            <div class="chart-bar alt" :style="{ width: barWidth(method.total, maxPaymentMethod) }"></div>
          </div>
        </div>
        <p v-if="sales?.payment_methods.length === 0">No payment data.</p>
      </article>

      <article class="panel stack">
        <h2>Inventory</h2>
        <div class="grid compact-grid">
          <div class="metric">
            <span>Products</span>
            <strong>{{ inventory?.summary.products || 0 }}</strong>
          </div>
          <div class="metric">
            <span>Low Stock</span>
            <strong>{{ inventory?.summary.low_stock || 0 }}</strong>
          </div>
          <div class="metric">
            <span>Stock Value</span>
            <strong>BDT {{ money(inventory?.summary.stock_value) }}</strong>
          </div>
        </div>
        <div v-for="product in inventory?.low_stock_products" :key="product.id" class="list-item">
          <div>
            <strong>{{ product.name }}</strong>
            <span>{{ product.sku || 'No SKU' }}</span>
          </div>
          <span>{{ product.current_stock }} / {{ product.low_stock_threshold }} {{ product.unit }}</span>
        </div>
        <p v-if="inventory?.low_stock_products.length === 0">No low stock products.</p>
      </article>

      <article class="panel stack">
        <h2>CRM Pipeline</h2>
        <div class="grid compact-grid">
          <div class="metric">
            <span>Open Leads</span>
            <strong>{{ overview?.crm.open_leads || 0 }}</strong>
          </div>
          <div class="metric">
            <span>Pipeline Value</span>
            <strong>BDT {{ money(overview?.crm.pipeline_value) }}</strong>
          </div>
        </div>
        <div v-for="stage in crm?.stages" :key="stage.stage" class="stack">
          <div class="list-item">
            <div>
              <strong>{{ stage.stage }}</strong>
              <span>{{ stage.count }} leads</span>
            </div>
            <span>BDT {{ stage.value }}</span>
          </div>
          <div class="chart-track">
            <div class="chart-bar warn" :style="{ width: barWidth(stage.value, maxPipelineStage) }"></div>
          </div>
        </div>
        <h3>Upcoming Follow Ups</h3>
        <div v-for="lead in crm?.upcoming_follow_ups" :key="lead.id" class="list-item">
          <div>
            <strong>{{ lead.name }}</strong>
            <span>{{ lead.stage }}</span>
          </div>
          <span>{{ lead.next_follow_up_at }}</span>
        </div>
        <p v-if="crm?.upcoming_follow_ups.length === 0">No scheduled follow ups.</p>
      </article>
    </section>
  </section>
</template>
