import { useDB, eq, and, sql } from '../../utils/database'
import { subscriptions } from '../schema'

export interface InsertSubscription {
  id: string
  customerId: string
  priceId: string
  userId: string
  status: string
  metadata?: Record<string, unknown> | null
  quantity: number
  cancelAtPeriodEnd: boolean
  currentPeriodEnd: Date
  currentPeriodStart: Date
  endedAt?: Date | null
  cancelAt?: Date | null
  trialStart?: Date | null
  trialEnd?: Date | null
}

export interface Subscription {
  id: string
  customerId: string | null
  priceId: string | null
  userId: string | null
  status: string
  metadata: unknown
  quantity: number
  cancelAtPeriodEnd: boolean
  currentPeriodEnd: Date | null
  currentPeriodStart: Date | null
  endedAt: Date | null
  cancelAt: Date | null
  trialStart: Date | null
  trialEnd: Date | null
  createdAt: Date | null
  updatedAt: Date | null
}

export const upsertSubscription = async (
  subscription: InsertSubscription
): Promise<Subscription> => {
  try {
    const db = useDB()
    const [upsertedSubscription] = await db
      .insert(subscriptions)
      .values(subscription)
      .onConflictDoUpdate({
        target: [subscriptions.id],
        set: subscription
      })
      .returning()

    return upsertedSubscription as unknown as Subscription
  } catch (error) {
    console.error('[upsertSubscription]', error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to upsert subscription'
    })
  }
}

/**
 * Get subscription by user ID (supports both org-enabled and org-disabled modes)
 * When organizations are disabled, userId represents the actual user
 * When organizations are enabled, userId should be the organization ID
 */
export const getSubscriptionByUserId = async (
  userId: string
): Promise<Subscription | null> => {
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const db = useDB() as any
    const subscription = await db.query.subscriptions.findFirst({
      where: eq(subscriptions.userId, userId),
      with: {
        price: true
      }
    })
    return subscription ?? null
  } catch (error) {
    console.error('[getSubscriptionByUserId]', userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to get subscription by user ID'
    })
  }
}

/**
 * Get active subscriptions by user ID
 * Returns all active or trialing subscriptions for the user/organization
 */
export const getSubscriptionsByUserId = async (
  userId: string
): Promise<Subscription[]> => {
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const db = useDB() as any
    const activeSubscriptions = await db.query.subscriptions.findMany({
      where: and(
        eq(subscriptions.userId, userId),
        sql`${subscriptions.status} IN ('active', 'trialing')`
      ),
      with: {
        price: {
          with: {
            product: true
          }
        }
      }
    })
    return activeSubscriptions
  } catch (error) {
    console.error('[getSubscriptionsByUserId]', userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to get subscriptions by user ID'
    })
  }
}
