import "server-only"

import { count, desc, eq, or } from "drizzle-orm"

import { db } from "@/shared/db"
import { aiProviders, passwordSecurity, users } from "@/shared/db/schema"

import type {
  AiProviderExisting,
  AiProviderName,
  AiProviderSummary,
  AiProviderVisibility,
} from "./types"

// --- AI Provider operations ---

/**
 * 获取所有 AI Provider（管理员视图）
 *
 * 返回所有 public 与 private 记录，供管理员在 /admin/ai-settings 中管理。
 */
export async function getAiProviderSummaries(): Promise<AiProviderSummary[]> {
  const rows = await db
    .select({
      id: aiProviders.id,
      provider: aiProviders.provider,
      baseUrl: aiProviders.baseUrl,
      model: aiProviders.model,
      apiKeyLast4: aiProviders.apiKeyLast4,
      isDefault: aiProviders.isDefault,
      visibility: aiProviders.visibility,
      createdBy: aiProviders.createdBy,
      updatedAt: aiProviders.updatedAt,
    })
    .from(aiProviders)
    .orderBy(desc(aiProviders.updatedAt))
  return rows
}

/**
 * 获取当前用户可见的 AI Provider（用户视图）
 *
 * 规则：
 *   - public Provider：全员可见
 *   - private Provider：仅创建者可见
 *
 * @param userId 当前用户 ID
 */
export async function getAiProviderSummariesForUser(
  userId: string
): Promise<AiProviderSummary[]> {
  const rows = await db
    .select({
      id: aiProviders.id,
      provider: aiProviders.provider,
      baseUrl: aiProviders.baseUrl,
      model: aiProviders.model,
      apiKeyLast4: aiProviders.apiKeyLast4,
      isDefault: aiProviders.isDefault,
      visibility: aiProviders.visibility,
      createdBy: aiProviders.createdBy,
      updatedAt: aiProviders.updatedAt,
    })
    .from(aiProviders)
    .where(
      or(
        eq(aiProviders.visibility, "public"),
        eq(aiProviders.createdBy, userId)
      )
    )
    .orderBy(desc(aiProviders.updatedAt))
  return rows
}

export async function countDefaultAiProviders(): Promise<number> {
  const [row] = await db
    .select({ value: count() })
    .from(aiProviders)
    .where(eq(aiProviders.isDefault, true))
  return Number(row?.value ?? 0)
}

/**
 * 获取 Provider 用于更新（管理员或创建者视图）
 *
 * 管理员可访问任意 Provider；非管理员仅能访问自己创建的 private Provider。
 */
export async function getAiProviderForUpdate(
  id: string,
  userId?: string
): Promise<AiProviderExisting | null> {
  const [row] = await db
    .select({
      id: aiProviders.id,
      apiKeyEncrypted: aiProviders.apiKeyEncrypted,
      apiKeyLast4: aiProviders.apiKeyLast4,
      isDefault: aiProviders.isDefault,
      visibility: aiProviders.visibility,
      createdBy: aiProviders.createdBy,
    })
    .from(aiProviders)
    .where(eq(aiProviders.id, id))
    .limit(1)
  if (!row) return null

  // 未传 userId 视为管理员视图（向后兼容）
  if (userId === undefined) return row

  // 非管理员只能更新自己创建的 Provider
  if (row.createdBy !== userId) return null
  return row
}

export async function updateAiProvider(
  id: string,
  data: {
    provider: AiProviderName
    baseUrl: string | null
    model: string
    apiKeyEncrypted: string
    apiKeyLast4: string | null
    isDefault: boolean
    visibility: AiProviderVisibility
    updatedBy: string
  },
  resetOtherDefaults: boolean
): Promise<void> {
  await db.transaction(async (tx) => {
    if (resetOtherDefaults) {
      await tx.update(aiProviders).set({ isDefault: false }).where(eq(aiProviders.isDefault, true))
    }
    await tx
      .update(aiProviders)
      .set({
        provider: data.provider,
        baseUrl: data.baseUrl,
        model: data.model,
        apiKeyEncrypted: data.apiKeyEncrypted,
        apiKeyLast4: data.apiKeyLast4,
        isDefault: data.isDefault,
        visibility: data.visibility,
        updatedBy: data.updatedBy,
      })
      .where(eq(aiProviders.id, id))
  })
}

export async function createAiProvider(
  data: {
    id: string
    provider: AiProviderName
    baseUrl: string | null
    model: string
    apiKeyEncrypted: string
    apiKeyLast4: string | null
    isDefault: boolean
    visibility: AiProviderVisibility
    createdBy: string
    updatedBy: string
  },
  resetOtherDefaults: boolean
): Promise<void> {
  await db.transaction(async (tx) => {
    if (resetOtherDefaults) {
      await tx.update(aiProviders).set({ isDefault: false }).where(eq(aiProviders.isDefault, true))
    }
    await tx.insert(aiProviders).values({
      id: data.id,
      provider: data.provider,
      baseUrl: data.baseUrl,
      model: data.model,
      apiKeyEncrypted: data.apiKeyEncrypted,
      apiKeyLast4: data.apiKeyLast4,
      isDefault: data.isDefault,
      visibility: data.visibility,
      createdBy: data.createdBy,
      updatedBy: data.updatedBy,
    })
  })
}

/**
 * 删除 AI Provider
 *
 * 如果删除的是默认 Provider，自动将最新的一条记录设为默认（若存在）。
 *
 * @param id Provider ID
 * @param userId 当前用户 ID（用于所有权校验；未传则不校验，仅管理员路径使用）
 */
export async function deleteAiProvider(
  id: string,
  userId?: string
): Promise<{ wasDefault: boolean }> {
  return await db.transaction(async (tx) => {
    const [existing] = await tx
      .select({
        isDefault: aiProviders.isDefault,
        createdBy: aiProviders.createdBy,
      })
      .from(aiProviders)
      .where(eq(aiProviders.id, id))
      .limit(1)

    if (!existing) {
      return { wasDefault: false }
    }

    // 所有权校验：非创建者不能删除（管理员路径不传 userId）
    if (userId !== undefined && existing.createdBy !== userId) {
      return { wasDefault: false }
    }

    await tx.delete(aiProviders).where(eq(aiProviders.id, id))

    // 如果删除的是默认 Provider，自动选一条最新的设为默认
    if (existing.isDefault) {
      const [next] = await tx
        .select({ id: aiProviders.id })
        .from(aiProviders)
        .orderBy(desc(aiProviders.updatedAt))
        .limit(1)

      if (next) {
        await tx.update(aiProviders).set({ isDefault: true }).where(eq(aiProviders.id, next.id))
      }
    }

    return { wasDefault: existing.isDefault }
  })
}

// --- Password change operations ---

export async function getUserPasswordHash(
  userId: string
): Promise<{ password: string | null } | null> {
  const [row] = await db
    .select({ password: users.password })
    .from(users)
    .where(eq(users.id, userId))
    .limit(1)
  return row ?? null
}

export async function getPasswordSecurityByUserId(
  userId: string
): Promise<{ id: string } | null> {
  const [row] = await db
    .select({ id: passwordSecurity.id })
    .from(passwordSecurity)
    .where(eq(passwordSecurity.userId, userId))
    .limit(1)
  return row ?? null
}

export async function updateUserPassword(
  userId: string,
  newHash: string,
  now: Date
): Promise<void> {
  await db
    .update(users)
    .set({ password: newHash, updatedAt: now })
    .where(eq(users.id, userId))
}

export async function upsertPasswordSecurityOnPasswordChange(
  userId: string,
  now: Date,
  existing: { id: string } | null
): Promise<void> {
  if (existing) {
    await db
      .update(passwordSecurity)
      .set({
        lastPasswordChange: now,
        passwordChangedAt: now,
        mustChangePassword: false,
        updatedAt: now,
      })
      .where(eq(passwordSecurity.userId, userId))
  } else {
    await db.insert(passwordSecurity).values({
      userId,
      lastPasswordChange: now,
      passwordChangedAt: now,
      mustChangePassword: false,
    })
  }
}
