"use server"

import { PermissionDeniedError, requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { exportToExcel, type ExcelColumn } from "@/shared/lib/excel"
import { formatDateForFile } from "@/shared/lib/utils"

import {
  getAuditLogsForExport,
  getDataChangeLogs,
  getDataChangeLogsForExport,
  getDataChangeStats,
  getDataChangeTableOptions,
  getLoginLogsForExport,
} from "./data-access"
import type {
  AuditLogQueryParams,
  DataChangeLog,
  DataChangeLogQueryParams,
  DataChangeStat,
  LoginLogQueryParams,
} from "./types"

export async function getDataChangeLogsAction(
  params?: DataChangeLogQueryParams
): Promise<
  ActionState<{
    items: DataChangeLog[]
    total: number
    page: number
    pageSize: number
    totalPages: number
    tableOptions: string[]
    stats: DataChangeStat[]
  }>
> {
  try {
    await requirePermission(Permissions.AUDIT_LOG_READ)
    const [result, tableOptions, stats] = await Promise.all([
      getDataChangeLogs(params),
      getDataChangeTableOptions(),
      getDataChangeStats(),
    ])
    return {
      success: true,
      data: {
        items: result.items,
        total: result.total,
        page: result.page,
        pageSize: result.pageSize,
        totalPages: result.totalPages,
        tableOptions,
        stats,
      },
    }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

/**
 * 通用 Excel 导出辅助函数。
 * 将 sheet 配置 + 行数据生成 Excel buffer，并按 filenamePrefix 拼接日期文件名。
 * 抽取自三个 export*Action，消除重复的 exportToExcel + filename 构造逻辑。
 */
async function buildExcelExport<TRow extends Record<string, unknown>>(params: {
  sheetName: string
  columns: ExcelColumn[]
  rows: TRow[]
  filenamePrefix: string
}): Promise<{ buffer: Buffer; filename: string }> {
  const buffer = await exportToExcel({
    sheets: [
      {
        name: params.sheetName,
        columns: params.columns,
        rows: params.rows,
      },
    ],
  })
  return {
    buffer,
    filename: `${params.filenamePrefix}_${formatDateForFile()}.xlsx`,
  }
}

export async function exportAuditLogsAction(
  params?: AuditLogQueryParams
): Promise<ActionState<{ buffer: Buffer; filename: string }>> {
  try {
    await requirePermission(Permissions.AUDIT_LOG_READ)
    const items = await getAuditLogsForExport(params)

    const { buffer, filename } = await buildExcelExport({
      sheetName: "Audit Logs",
      columns: [
        { header: "User ID", key: "userId", width: 22 },
        { header: "User Name", key: "userName", width: 18 },
        { header: "Module", key: "module", width: 16 },
        { header: "Action", key: "action", width: 22 },
        { header: "Target ID", key: "targetId", width: 22 },
        { header: "Target Type", key: "targetType", width: 16 },
        { header: "Detail", key: "detail", width: 40 },
        { header: "IP Address", key: "ipAddress", width: 16 },
        { header: "Status", key: "status", width: 10 },
        { header: "Created At", key: "createdAt", width: 22 },
      ],
      rows: items.map((r) => ({
        userId: r.userId,
        userName: r.userName,
        module: r.module,
        action: r.action,
        targetId: r.targetId ?? "",
        targetType: r.targetType ?? "",
        detail: r.detail ?? "",
        ipAddress: r.ipAddress ?? "",
        status: r.status,
        createdAt: r.createdAt,
      })),
      filenamePrefix: "audit_logs",
    })

    return { success: true, data: { buffer, filename } }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function exportLoginLogsAction(
  params?: LoginLogQueryParams
): Promise<ActionState<{ buffer: Buffer; filename: string }>> {
  try {
    await requirePermission(Permissions.AUDIT_LOG_READ)
    const items = await getLoginLogsForExport(params)

    const { buffer, filename } = await buildExcelExport({
      sheetName: "Login Logs",
      columns: [
        { header: "User ID", key: "userId", width: 22 },
        { header: "User Email", key: "userEmail", width: 26 },
        { header: "Action", key: "action", width: 12 },
        { header: "Status", key: "status", width: 10 },
        { header: "IP Address", key: "ipAddress", width: 16 },
        { header: "User Agent", key: "userAgent", width: 40 },
        { header: "Error Message", key: "errorMessage", width: 30 },
        { header: "Created At", key: "createdAt", width: 22 },
      ],
      rows: items.map((r) => ({
        userId: r.userId ?? "",
        userEmail: r.userEmail,
        action: r.action,
        status: r.status,
        ipAddress: r.ipAddress ?? "",
        userAgent: r.userAgent ?? "",
        errorMessage: r.errorMessage ?? "",
        createdAt: r.createdAt,
      })),
      filenamePrefix: "login_logs",
    })

    return { success: true, data: { buffer, filename } }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}

export async function exportDataChangeLogsAction(
  params?: DataChangeLogQueryParams
): Promise<ActionState<{ buffer: Buffer; filename: string }>> {
  try {
    await requirePermission(Permissions.AUDIT_LOG_READ)
    const items = await getDataChangeLogsForExport(params)

    const { buffer, filename } = await buildExcelExport({
      sheetName: "Data Change Logs",
      columns: [
        { header: "Table Name", key: "tableName", width: 22 },
        { header: "Record ID", key: "recordId", width: 22 },
        { header: "Action", key: "action", width: 10 },
        { header: "Old Value", key: "oldValue", width: 50 },
        { header: "New Value", key: "newValue", width: 50 },
        { header: "Changed By", key: "changedBy", width: 22 },
        { header: "Changed By Name", key: "changedByName", width: 18 },
        { header: "IP Address", key: "ipAddress", width: 16 },
        { header: "Created At", key: "createdAt", width: 22 },
      ],
      rows: items.map((r) => ({
        tableName: r.tableName,
        recordId: r.recordId,
        action: r.action,
        oldValue: r.oldValue ?? "",
        newValue: r.newValue ?? "",
        changedBy: r.changedBy,
        changedByName: r.changedByName,
        ipAddress: r.ipAddress ?? "",
        createdAt: r.createdAt,
      })),
      filenamePrefix: "data_change_logs",
    })

    return { success: true, data: { buffer, filename } }
  } catch (e) {
    if (e instanceof PermissionDeniedError) return { success: false, message: e.message }
    if (e instanceof Error) return { success: false, message: e.message }
    return { success: false, message: "Unexpected error" }
  }
}
