import { expect, type Page } from "@playwright/test"

export const E2E_INVITE_TOKEN = "e2e-onboard-invite-token"
export const E2E_MIGRATEE_EMAIL = "alice@acme.com"
export const E2E_PROJECT_ID = "11111111-1111-4111-8111-111111111111"

export type MigrationMockState = {
  projectStatus?: "draft" | "active" | "cutover"
  authMode?: "oauth" | "google_dwd" | "microsoft_app"
  sourceProvider?: "google" | "microsoft"
  inviteStatus?: "invited" | "claimed"
  hasMigrationCredentials?: boolean
  waitingForAdmin?: boolean
  jobs?: Array<{
    service: string
    status: string
    stats_json?: Record<string, number>
    error?: string
  }>
}

const DEFAULT_JOBS = [
  { service: "mail", status: "pending", stats_json: { imported: 0 } },
  { service: "contacts", status: "pending", stats_json: { imported: 0 } },
  { service: "calendar", status: "pending", stats_json: { imported: 0 } },
  { service: "drive", status: "pending", stats_json: { imported: 0 } },
]

function buildProject(state: MigrationMockState) {
  return {
    id: E2E_PROJECT_ID,
    name: "Migration E2E ACME",
    source_provider: state.sourceProvider ?? "google",
    auth_mode: state.authMode ?? "oauth",
    status: state.projectStatus ?? "draft",
    delta_mode: state.projectStatus === "cutover",
    created_at: "2026-01-15T10:00:00Z",
  }
}

function buildInvite(state: MigrationMockState) {
  return {
    id: "22222222-2222-4222-8222-222222222222",
    project_id: E2E_PROJECT_ID,
    email: E2E_MIGRATEE_EMAIL,
    status: state.inviteStatus ?? "invited",
  }
}

export function buildOnboardingHints(state: MigrationMockState) {
  const projectStatus = state.projectStatus ?? "draft"
  const waiting =
    state.waitingForAdmin ??
    (projectStatus !== "active" && projectStatus !== "cutover")
  const authMode = state.authMode ?? "oauth"
  const sourceProvider = state.sourceProvider ?? "google"
  return {
    needs_user_oauth: authMode !== "google_dwd" && authMode !== "microsoft_app",
    oauth_provider: sourceProvider,
    waiting_for_admin: waiting,
    waiting_reason: waiting ? "project_not_activated" : undefined,
    has_migration_credentials: state.hasMigrationCredentials ?? false,
    needs_microsoft_admin_consent: sourceProvider === "microsoft",
  }
}

export async function mockAuthSession(
  page: Page,
  opts: { authenticated: boolean; email?: string; name?: string } = {
    authenticated: true,
  }
) {
  await page.route("**/api/auth/session", async (route) => {
    if (!opts.authenticated) {
      await route.fulfill({
        status: 200,
        contentType: "application/json",
        body: JSON.stringify({ authenticated: false }),
      })
      return
    }
    const email = opts.email ?? E2E_MIGRATEE_EMAIL
    const name = opts.name ?? "Alice Test"
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        authenticated: true,
        accessToken: "e2e-access-token",
        refreshToken: "e2e-refresh-token",
        expiresAt: Date.now() + 3_600_000,
        user: {
          sub: "e2e-user-sub",
          email,
          name,
          firstName: name.split(/\s+/)[0] ?? name,
        },
      }),
    })
  })
}

export async function installMigrationApiMocks(
  page: Page,
  state: MigrationMockState = {}
) {
  let inviteClaimed = (state.inviteStatus ?? "invited") === "claimed"

  const snapshot = () => {
    const inviteStatus = inviteClaimed ? "claimed" : "invited"
    const merged = { ...state, inviteStatus: inviteStatus as "invited" | "claimed" }
    return {
      project: buildProject(merged),
      invite: buildInvite(merged),
      onboarding: buildOnboardingHints(merged),
      jobs: state.jobs ?? DEFAULT_JOBS,
    }
  }

  await page.route("**/api/v1/migration/invite**", async (route) => {
    const body = snapshot()
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        invite: body.invite,
        project: body.project,
        onboarding: body.onboarding,
      }),
    })
  })

  await page.route("**/api/v1/migration/status**", async (route) => {
    const body = snapshot()
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify(body),
    })
  })

  await page.route("**/api/v1/migration/claim**", async (route) => {
    if (route.request().method() !== "POST") {
      await route.continue()
      return
    }
    inviteClaimed = true
    const body = snapshot()
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify(body),
    })
  })

  await page.route("**/api/v1/migration/oauth/start**", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify({
        auth_url: `/onboard/migration?token=${E2E_INVITE_TOKEN}&oauth=success`,
      }),
    })
  })
}

export async function gotoClaimPage(page: Page, token = E2E_INVITE_TOKEN) {
  await page.goto(`/onboard/claim?token=${encodeURIComponent(token)}`)
  await page.waitForResponse((res) => res.url().includes("/migration/invite"))
}

export async function gotoMigrationPage(page: Page, token = E2E_INVITE_TOKEN) {
  await page.goto(`/onboard/migration?token=${encodeURIComponent(token)}`)
}

export async function expectClaimAuthenticatedStep(page: Page) {
  await expect(page.getByRole("heading", { name: "Revendiquer votre compte" })).toBeVisible()
  await expect(page.getByRole("button", { name: "Revendiquer mon compte" })).toBeVisible()
  await expect(
    page.getByText(/L'email de connexion doit correspondre exactement/)
  ).toBeVisible()
}

export async function submitClaim(page: Page) {
  const claimResponse = page.waitForResponse(
    (res) => res.url().includes("/migration/claim") && res.request().method() === "POST"
  )
  await page.getByRole("button", { name: "Revendiquer mon compte" }).click()
  await claimResponse
  await page.waitForURL(new RegExp(`/onboard/migration\\?token=${E2E_INVITE_TOKEN}`))
}
