/**
 * Calendar settings query helpers for the per-user integration settings page.
 */
import { and, eq } from 'drizzle-orm'
import type { Db } from '../client'
import { calendarConnections } from '../schema/calendar'

export type CalendarProvider = 'google' | 'outlook'
export type CalendarSyncDirection = 'two_way' | 'read_only' | 'push_only'
export type CalendarConnectionStatus = 'active' | 'error' | 'disconnected'

export interface CalendarConnectionPublic {
  provider: CalendarProvider
  status: CalendarConnectionStatus
  connected_email: string | null
  connected_account_label: string
  selected_calendar_id: string | null
  selected_calendar_name: string | null
  sync_direction: CalendarSyncDirection
  sync_task_due_dates: boolean
  sync_manual_events: boolean
  sync_customer_meetings: boolean
  last_synced_at: string | null
  last_sync_error: string | null
}

export interface CalendarListItemPublic {
  id: string
  name: string
  primary: boolean
}

export interface CalendarConnectionPrefsPatch {
  selected_calendar_id?: string | null
  selected_calendar_name?: string | null
  sync_direction?: CalendarSyncDirection
  sync_task_due_dates?: boolean
  sync_manual_events?: boolean
  sync_customer_meetings?: boolean
}

export type CalendarSettingsObject = CalendarConnectionPublic
export type CalendarSettingsPatch = CalendarConnectionPrefsPatch
export type CalendarConnection = CalendarConnectionPublic

function serializeConnection(
  row: typeof calendarConnections.$inferSelect,
): CalendarConnectionPublic {
  return {
    provider: row.provider as CalendarProvider,
    status: row.status as CalendarConnectionStatus,
    connected_email: row.connectedEmail ?? null,
    connected_account_label: row.connectedEmail ?? row.externalUserId,
    selected_calendar_id: row.selectedCalendarId ?? null,
    selected_calendar_name: row.selectedCalendarName ?? null,
    sync_direction: row.syncDirection as CalendarSyncDirection,
    sync_task_due_dates: row.syncTaskDueDates,
    sync_manual_events: row.syncManualEvents,
    sync_customer_meetings: row.syncCustomerMeetings,
    last_synced_at: row.lastSyncedAt ? row.lastSyncedAt.toISOString() : null,
    last_sync_error: row.lastSyncError ?? null,
  }
}

export async function listCalendarSettingsConnections(
  db: Db,
  tenantId: string,
  userId: string,
): Promise<CalendarConnectionPublic[]> {
  const rows = await db
    .select()
    .from(calendarConnections)
    .where(and(eq(calendarConnections.tenantId, tenantId), eq(calendarConnections.userId, userId)))

  return rows.map(serializeConnection)
}

export async function getCalendarSettingsConnection(
  db: Db,
  tenantId: string,
  userId: string,
  provider: CalendarProvider,
): Promise<CalendarConnectionPublic | null> {
  const [row] = await db
    .select()
    .from(calendarConnections)
    .where(
      and(
        eq(calendarConnections.tenantId, tenantId),
        eq(calendarConnections.userId, userId),
        eq(calendarConnections.provider, provider),
      ),
    )
    .limit(1)

  return row ? serializeConnection(row) : null
}

export async function updateCalendarConnectionPrefs(
  db: Db,
  tenantId: string,
  userId: string,
  provider: CalendarProvider,
  patch: CalendarConnectionPrefsPatch,
): Promise<CalendarConnectionPublic | null> {
  const [row] = await db
    .update(calendarConnections)
    .set({
      selectedCalendarId: patch.selected_calendar_id,
      selectedCalendarName: patch.selected_calendar_name,
      syncDirection: patch.sync_direction,
      syncTaskDueDates: patch.sync_task_due_dates,
      syncManualEvents: patch.sync_manual_events,
      syncCustomerMeetings: patch.sync_customer_meetings,
    })
    .where(
      and(
        eq(calendarConnections.tenantId, tenantId),
        eq(calendarConnections.userId, userId),
        eq(calendarConnections.provider, provider),
      ),
    )
    .returning()

  return row ? serializeConnection(row) : null
}

export async function setCalendarConnectionStatus(
  db: Db,
  tenantId: string,
  userId: string,
  provider: CalendarProvider,
  status: CalendarConnectionStatus,
  lastSyncError?: string | null,
): Promise<void> {
  await db
    .update(calendarConnections)
    .set({
      status,
      lastSyncError: lastSyncError ?? null,
    })
    .where(
      and(
        eq(calendarConnections.tenantId, tenantId),
        eq(calendarConnections.userId, userId),
        eq(calendarConnections.provider, provider),
      ),
    )
}
