'use server';

import { getDb } from '@/db';
import { creditTransaction } from '@/db/schema';
import type { User } from '@/lib/auth-types';
import { userActionClient } from '@/lib/safe-action';
import { and, asc, desc, eq, ilike, or, sql } from 'drizzle-orm';
import { z } from 'zod';

// Define the schema for getCreditTransactions parameters
const getCreditTransactionsSchema = z.object({
  pageIndex: z.number().min(0).default(0),
  pageSize: z.number().min(1).max(100).default(10),
  search: z.string().optional().default(''),
  sorting: z
    .array(
      z.object({
        id: z.string(),
        desc: z.boolean(),
      })
    )
    .optional()
    .default([]),
});

// Define sort field mapping
const sortFieldMap = {
  type: creditTransaction.type,
  amount: creditTransaction.amount,
  remainingAmount: creditTransaction.remainingAmount,
  description: creditTransaction.description,
  createdAt: creditTransaction.createdAt,
  updatedAt: creditTransaction.updatedAt,
  expirationDate: creditTransaction.expirationDate,
  expirationDateProcessedAt: creditTransaction.expirationDateProcessedAt,
  paymentId: creditTransaction.paymentId,
} as const;

// Create a safe action for getting credit transactions
export const getCreditTransactionsAction = userActionClient
  .schema(getCreditTransactionsSchema)
  .action(async ({ parsedInput, ctx }) => {
    try {
      const { pageIndex, pageSize, search, sorting } = parsedInput;
      const currentUser = (ctx as { user: User }).user;

      // search by type, amount, paymentId, description, and restrict to current user
      const where = search
        ? and(
            eq(creditTransaction.userId, currentUser.id),
            or(
              ilike(creditTransaction.type, `%${search}%`),
              ilike(creditTransaction.amount, `%${search}%`),
              ilike(creditTransaction.remainingAmount, `%${search}%`),
              ilike(creditTransaction.paymentId, `%${search}%`),
              ilike(creditTransaction.description, `%${search}%`)
            )
          )
        : eq(creditTransaction.userId, currentUser.id);

      const offset = pageIndex * pageSize;

      // Get the sort configuration
      const sortConfig = sorting[0];
      const sortField = sortConfig?.id
        ? sortFieldMap[sortConfig.id as keyof typeof sortFieldMap]
        : creditTransaction.createdAt;
      const sortDirection = sortConfig?.desc ? desc : asc;

      const db = await getDb();
      const [items, [{ count }]] = await Promise.all([
        db
          .select({
            id: creditTransaction.id,
            userId: creditTransaction.userId,
            type: creditTransaction.type,
            description: creditTransaction.description,
            amount: creditTransaction.amount,
            remainingAmount: creditTransaction.remainingAmount,
            paymentId: creditTransaction.paymentId,
            expirationDate: creditTransaction.expirationDate,
            expirationDateProcessedAt:
              creditTransaction.expirationDateProcessedAt,
            createdAt: creditTransaction.createdAt,
            updatedAt: creditTransaction.updatedAt,
          })
          .from(creditTransaction)
          .where(where)
          .orderBy(sortDirection(sortField))
          .limit(pageSize)
          .offset(offset),
        db
          .select({ count: sql`count(*)` })
          .from(creditTransaction)
          .where(where),
      ]);

      return {
        success: true,
        data: {
          items,
          total: Number(count),
        },
      };
    } catch (error) {
      console.error('get credit transactions error:', error);
      return {
        success: false,
        error:
          error instanceof Error
            ? error.message
            : 'Failed to fetch credit transactions',
      };
    }
  });
