import { eq, desc, gt, count } from 'drizzle-orm'
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'
import { accountBalances } from '../db/schema/accounting.js'
import { accounts } from '../db/schema/accounts.js'
import type { PaginationInput } from '@lunarfront/shared/schemas'

export const AccountBalanceService = {
  async getBalance(db: PostgresJsDatabase<any>, accountId: string) {
    const [existing] = await db.select().from(accountBalances).where(eq(accountBalances.accountId, accountId)).limit(1)
    if (existing) return existing

    // Create balance record if it doesn't exist
    const [created] = await db.insert(accountBalances).values({ accountId }).returning()
    return created
  },

  async adjustBalance(
    db: PostgresJsDatabase<any>,
    accountId: string,
    adjustment: number,
    reason: 'invoice' | 'payment' | 'void' | 'write_off',
  ) {
    const balance = await this.getBalance(db, accountId)
    const newBalance = parseFloat(balance.currentBalance) + adjustment

    const updates: Record<string, unknown> = {
      currentBalance: newBalance.toFixed(2),
      updatedAt: new Date(),
    }

    if (reason === 'invoice' && adjustment > 0) {
      updates.lastInvoiceDate = new Date().toISOString().slice(0, 10)
    }
    if (reason === 'payment' && adjustment < 0) {
      updates.lastPaymentDate = new Date().toISOString().slice(0, 10)
    }

    await db.update(accountBalances).set(updates).where(eq(accountBalances.accountId, accountId))
  },

  async getOutstandingAccounts(db: PostgresJsDatabase<any>, params: PaginationInput) {
    const where = gt(accountBalances.currentBalance, '0')
    const offset = ((params.page ?? 1) - 1) * (params.limit ?? 25)

    const [data, [{ total }]] = await Promise.all([
      db.select({
        accountId: accountBalances.accountId,
        currentBalance: accountBalances.currentBalance,
        lastInvoiceDate: accountBalances.lastInvoiceDate,
        lastPaymentDate: accountBalances.lastPaymentDate,
        accountName: accounts.name,
        accountEmail: accounts.email,
      })
        .from(accountBalances)
        .innerJoin(accounts, eq(accountBalances.accountId, accounts.id))
        .where(where)
        .orderBy(desc(accountBalances.currentBalance))
        .limit(params.limit ?? 25)
        .offset(offset),
      db.select({ total: count() })
        .from(accountBalances)
        .where(where),
    ])

    return {
      data,
      pagination: {
        page: params.page ?? 1,
        limit: params.limit ?? 25,
        total,
        totalPages: Math.ceil(total / (params.limit ?? 25)),
      },
    }
  },

  async recalculateFromInvoices(db: PostgresJsDatabase<any>, accountId: string) {
    // Safety valve: recalculate balance from all invoices
    const { invoices } = await import('../db/schema/accounting.js')
    const rows = await db
      .select({ balance: invoices.balance, status: invoices.status })
      .from(invoices)
      .where(eq(invoices.accountId, accountId))

    const totalOutstanding = rows
      .filter(r => ['sent', 'partial', 'overdue'].includes(r.status))
      .reduce((sum, r) => sum + parseFloat(r.balance), 0)

    await db.update(accountBalances).set({
      currentBalance: totalOutstanding.toFixed(2),
      updatedAt: new Date(),
    }).where(eq(accountBalances.accountId, accountId))
  },
}
