/**
 * Seed Zapier and Make OAuth clients — zapier-make-integration (wave-13).
 *
 * Third-party clients (`is_first_party = false`) — consent screen is shown.
 * Secrets come from env at seed time; never committed.
 *
 * Idempotent: upserts on client_id; preserves client_secret_hash on conflict
 * (to avoid accidental secret rotation). Pass `forceRotateSecret: true` to
 * update the hash as well.
 */
import { sql } from 'drizzle-orm'
import type { Db } from '../client'
import { oauthClients } from '../schema/oauth'

const ZAPIER_REDIRECT_URI = 'https://zapier.com/dashboard/auth/oauth/return/App1234CLIAPI/'
const MAKE_REDIRECT_URI = 'https://www.make.com/oauth/cb/app'

const ZAPIER_MAKE_SCOPES = [
  'read:invoices',
  'write:invoices',
  'read:customers',
  'write:customers',
  'read:leads',
  'write:leads',
  'read:time',
  'write:time',
  'read:events',
  'read:projects',
  'write:tasks',
]

async function sha256Hex(plaintext: string): Promise<string> {
  const encoder = new TextEncoder()
  const data = encoder.encode(plaintext)
  const hashBuffer = await crypto.subtle.digest('SHA-256', data)
  const hashArray = Array.from(new Uint8Array(hashBuffer))
  return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
}

export interface SeedZapierMakeOptions {
  zapierSecret: string
  makeSecret: string
  /** If true, update client_secret_hash on conflict (secret rotation). Default: false. */
  forceRotateSecret?: boolean
}

/**
 * Seed Zapier and Make third-party OAuth clients.
 * Idempotent — upserts on client_id.
 */
export async function seedZapierMakeOAuthClients(
  db: Db,
  opts: SeedZapierMakeOptions,
): Promise<void> {
  const zapierHash = await sha256Hex(opts.zapierSecret)
  const makeHash = await sha256Hex(opts.makeSecret)

  const clients = [
    {
      clientId: 'zapier_zync',
      clientSecretHash: zapierHash,
      name: 'Zapier',
      redirectUris: [ZAPIER_REDIRECT_URI],
      scopes: ZAPIER_MAKE_SCOPES,
      isFirstParty: false as const,
      logoUrl: null,
    },
    {
      clientId: 'make_zync',
      clientSecretHash: makeHash,
      name: 'Make',
      redirectUris: [MAKE_REDIRECT_URI],
      scopes: ZAPIER_MAKE_SCOPES,
      isFirstParty: false as const,
      logoUrl: null,
    },
  ]

  for (const client of clients) {
    const conflictSet = opts.forceRotateSecret
      ? {
          name: sql`excluded.name`,
          redirectUris: sql`excluded.redirect_uris`,
          scopes: sql`excluded.scopes`,
          isFirstParty: sql`excluded.is_first_party`,
          logoUrl: sql`excluded.logo_url`,
          clientSecretHash: sql`excluded.client_secret_hash`,
        }
      : {
          name: sql`excluded.name`,
          redirectUris: sql`excluded.redirect_uris`,
          scopes: sql`excluded.scopes`,
          isFirstParty: sql`excluded.is_first_party`,
          logoUrl: sql`excluded.logo_url`,
        }

    await db
      .insert(oauthClients)
      .values(client)
      .onConflictDoUpdate({
        target: oauthClients.clientId,
        set: conflictSet,
      })
  }
}
