import "server-only"

import { and, count, desc, eq, inArray, like, or, sql, type SQL } from "drizzle-orm"
import { cache } from "react"

import { db } from "@/shared/db"
import { fileAttachments } from "@/shared/db/schema"
import type {
  BatchDeleteResult,
  CreateFileAttachmentInput,
  FileAttachment,
  FileAttachmentQueryParams,
  FileStats,
} from "./types"

const toIso = (d: Date): string => d.toISOString()

const mapRow = (row: typeof fileAttachments.$inferSelect): FileAttachment => ({
  id: row.id,
  filename: row.filename,
  originalName: row.originalName,
  mimeType: row.mimeType,
  size: row.size,
  storagePath: row.storagePath,
  url: row.url,
  uploaderId: row.uploaderId,
  targetType: row.targetType,
  targetId: row.targetId,
  createdAt: toIso(row.createdAt),
})

/**
 * 插入文件附件记录
 */
export async function createFileAttachment(
  data: CreateFileAttachmentInput
): Promise<FileAttachment | null> {
  try {
    await db.insert(fileAttachments).values({
      id: data.id,
      filename: data.filename,
      originalName: data.originalName,
      mimeType: data.mimeType,
      size: data.size,
      storagePath: data.storagePath,
      url: data.url,
      uploaderId: data.uploaderId,
      targetType: data.targetType ?? null,
      targetId: data.targetId ?? null,
    })

    const created = await getFileAttachment(data.id)
    return created
  } catch (error) {
    console.error("createFileAttachment failed:", error)
    return null
  }
}

/**
 * 按 ID 查询文件附件
 */
export const getFileAttachment = cache(
  async (id: string): Promise<FileAttachment | null> => {
    try {
      const [row] = await db
        .select()
        .from(fileAttachments)
        .where(eq(fileAttachments.id, id))
        .limit(1)

      return row ? mapRow(row) : null
    } catch (error) {
      console.error("getFileAttachment failed:", error)
      return null
    }
  },
)

/**
 * 按关联资源查询文件列表
 */
export const getFileAttachmentsByTarget = cache(
  async (targetType: string, targetId: string): Promise<FileAttachment[]> => {
    try {
      const rows = await db
        .select()
        .from(fileAttachments)
        .where(
          and(
            eq(fileAttachments.targetType, targetType),
            eq(fileAttachments.targetId, targetId)
          )
        )
        .orderBy(desc(fileAttachments.createdAt))

      return rows.map(mapRow)
    } catch (error) {
      console.error("getFileAttachmentsByTarget failed:", error)
      return []
    }
  },
)

/**
 * 按上传者查询文件列表
 */
export const getFileAttachmentsByUploader = cache(
  async (uploaderId: string): Promise<FileAttachment[]> => {
    try {
      const rows = await db
        .select()
        .from(fileAttachments)
        .where(eq(fileAttachments.uploaderId, uploaderId))
        .orderBy(desc(fileAttachments.createdAt))

      return rows.map(mapRow)
    } catch (error) {
      console.error("getFileAttachmentsByUploader failed:", error)
      return []
    }
  },
)

/**
 * 查询所有文件（用于管理员文件管理页面）
 */
export const getAllFileAttachments = cache(
  async (limit = 100): Promise<FileAttachment[]> => {
    try {
      const rows = await db
        .select()
        .from(fileAttachments)
        .orderBy(desc(fileAttachments.createdAt))
        .limit(limit)

      return rows.map(mapRow)
    } catch (error) {
      console.error("getAllFileAttachments failed:", error)
      return []
    }
  },
)

/**
 * 删除文件附件记录
 */
export async function deleteFileAttachment(id: string): Promise<boolean> {
  try {
    await db.delete(fileAttachments).where(eq(fileAttachments.id, id))
    return true
  } catch (error) {
    console.error("deleteFileAttachment failed:", error)
    return false
  }
}

/**
 * 批量删除文件附件记录
 * 仅删除数据库记录，磁盘文件由调用方处理
 */
export async function deleteFileAttachments(ids: string[]): Promise<BatchDeleteResult> {
  if (ids.length === 0) {
    return { success: true, deletedCount: 0, failedIds: [] }
  }
  try {
    await db.delete(fileAttachments).where(inArray(fileAttachments.id, ids))
    return { success: true, deletedCount: ids.length, failedIds: [] }
  } catch (error) {
    console.error("deleteFileAttachments batch failed:", error)
    // 失败时回退到逐条删除，尽量多删
    const failedIds: string[] = []
    let deletedCount = 0
    for (const id of ids) {
      try {
        await db.delete(fileAttachments).where(eq(fileAttachments.id, id))
        deletedCount += 1
      } catch (err) {
        console.error("deleteFileAttachments single failed:", err)
        failedIds.push(id)
      }
    }
    return {
      success: failedIds.length === 0,
      deletedCount,
      failedIds,
    }
  }
}

/**
 * 按条件筛选文件列表（管理员页面）
 * - mimeType: 精确匹配或前缀匹配（如 "image/"）
 * - search: 在 originalName / filename 中模糊匹配
 */
export const getFileAttachmentsWithFilters = cache(
  async (params: FileAttachmentQueryParams): Promise<FileAttachment[]> => {
    try {
      const { mimeType, search, limit = 100, offset = 0 } = params

      const conditions: SQL[] = []
      if (mimeType) {
        if (mimeType.endsWith("/")) {
          conditions.push(like(fileAttachments.mimeType, `${mimeType}%`))
        } else {
          conditions.push(eq(fileAttachments.mimeType, mimeType))
        }
      }
      if (search) {
        const kw = `%${search}%`
        const nameCondition = or(
          like(fileAttachments.originalName, kw),
          like(fileAttachments.filename, kw)
        )
        if (nameCondition) conditions.push(nameCondition)
      }

      const where = conditions.length > 0 ? and(...conditions) : undefined

      const rows = await db
        .select()
        .from(fileAttachments)
        .where(where)
        .orderBy(desc(fileAttachments.createdAt))
        .limit(limit)
        .offset(offset)

      return rows.map(mapRow)
    } catch (error) {
      console.error("getFileAttachmentsWithFilters failed:", error)
      return []
    }
  },
)

/**
 * 获取文件统计信息（总数、总大小、按类型分组）
 */
export const getFileStats = cache(
  async (): Promise<FileStats> => {
    try {
      const rows = await db
        .select({
          mimeType: fileAttachments.mimeType,
          count: count(),
          size: sql<number>`COALESCE(SUM(${fileAttachments.size}), 0)`,
        })
        .from(fileAttachments)
        .groupBy(fileAttachments.mimeType)

      const byType = rows.map((r) => ({
        mimeType: r.mimeType,
        count: Number(r.count),
        size: Number(r.size),
      }))

      const totalCount = byType.reduce((sum, r) => sum + r.count, 0)
      const totalSize = byType.reduce((sum, r) => sum + r.size, 0)

      return { totalCount, totalSize, byType }
    } catch (error) {
      console.error("getFileStats failed:", error)
      return { totalCount: 0, totalSize: 0, byType: [] }
    }
  },
)

/**
 * 按 URL 查询文件附件（用于头像等场景的旧文件清理）
 */
export const getFileByUrl = cache(
  async (url: string): Promise<FileAttachment | null> => {
    try {
      const [row] = await db
        .select()
        .from(fileAttachments)
        .where(eq(fileAttachments.url, url))
        .limit(1)

      return row ? mapRow(row) : null
    } catch (error) {
      console.error("getFileByUrl failed:", error)
      return null
    }
  },
)

/**
 * 按 ID 列表批量查询文件（用于批量删除前获取磁盘路径）
 */
export const getFileAttachmentsByIds = cache(
  async (ids: string[]): Promise<FileAttachment[]> => {
    if (ids.length === 0) return []
    try {
      const rows = await db
        .select()
        .from(fileAttachments)
        .where(inArray(fileAttachments.id, ids))
      return rows.map(mapRow)
    } catch (error) {
      console.error("getFileAttachmentsByIds failed:", error)
      return []
    }
  },
)
