"use server"

import { z } from "zod"
import { revalidatePath } from "next/cache"

import type { ActionState } from "@/shared/types/action-state"
import { requirePermission } from "@/shared/lib/auth-guard"
import { Permissions } from "@/shared/types/permissions"

import {
  getAllSystemSettings,
  upsertSystemSettings,
} from "./data-access-system-settings"
import { toSettingItem } from "./lib/system-settings-utils"

// --- Schemas ---

const SchoolInfoSchema = z.object({
  schoolName: z.string().min(1).max(255),
  schoolCode: z.string().max(50).default(""),
  schoolPhone: z.string().max(50).default(""),
  schoolEmail: z.string().email().or(z.literal("")).default(""),
  schoolAddress: z.string().max(500).default(""),
  schoolDescription: z.string().max(2000).default(""),
})

const SecurityPolicySchema = z.object({
  passwordMinLength: z.coerce.number().int().min(6).max(32),
  sessionTimeout: z.coerce.number().int().min(5).max(1440),
  requireSpecialChar: z.coerce.boolean(),
  requireUppercase: z.coerce.boolean(),
  forcePasswordChange: z.coerce.boolean(),
})

const FileUploadSchema = z.object({
  maxFileSize: z.coerce.number().int().min(1).max(100),
  allowedTypes: z.string().min(1).max(500),
})

const NotificationConfigSchema = z.object({
  notifyNewUser: z.coerce.boolean(),
  notifyScheduleChange: z.coerce.boolean(),
  notifyAnnouncement: z.coerce.boolean(),
})

const AdminSettingsFormSchema = z.object({
  schoolInfo: SchoolInfoSchema,
  securityPolicy: SecurityPolicySchema,
  fileUpload: FileUploadSchema,
  notificationConfig: NotificationConfigSchema,
})

type AdminSettingsFormValues = z.infer<typeof AdminSettingsFormSchema>

// --- Actions ---

/**
 * 获取管理员系统设置
 */
export async function getAdminSystemSettingsAction(): Promise<
  ActionState<AdminSettingsFormValues>
> {
  try {
    const ctx = await requirePermission(Permissions.SETTINGS_ADMIN)
    void ctx

    const records = await getAllSystemSettings()

    const map = new Map<string, string>()
    for (const r of records) {
      map.set(`${r.category}.${r.key}`, r.value)
    }

    const get = (category: string, key: string, fallback: string): string =>
      map.get(`${category}.${key}`) ?? fallback

    const getBool = (category: string, key: string, fallback: boolean): boolean => {
      const v = map.get(`${category}.${key}`)
      if (v === undefined) return fallback
      return v === "true"
    }

    const getNum = (category: string, key: string, fallback: number): number => {
      const v = map.get(`${category}.${key}`)
      if (v === undefined) return fallback
      const n = Number(v)
      return Number.isNaN(n) ? fallback : n
    }

    const data: AdminSettingsFormValues = {
      schoolInfo: {
        schoolName: get("school_info", "schoolName", ""),
        schoolCode: get("school_info", "schoolCode", ""),
        schoolPhone: get("school_info", "schoolPhone", ""),
        schoolEmail: get("school_info", "schoolEmail", ""),
        schoolAddress: get("school_info", "schoolAddress", ""),
        schoolDescription: get("school_info", "schoolDescription", ""),
      },
      securityPolicy: {
        passwordMinLength: getNum("security_policy", "passwordMinLength", 8),
        sessionTimeout: getNum("security_policy", "sessionTimeout", 60),
        requireSpecialChar: getBool("security_policy", "requireSpecialChar", true),
        requireUppercase: getBool("security_policy", "requireUppercase", false),
        forcePasswordChange: getBool("security_policy", "forcePasswordChange", true),
      },
      fileUpload: {
        maxFileSize: getNum("file_upload", "maxFileSize", 10),
        allowedTypes: get("file_upload", "allowedTypes", "jpg,png,pdf,docx,xlsx,pptx"),
      },
      notificationConfig: {
        notifyNewUser: getBool("notification_config", "notifyNewUser", true),
        notifyScheduleChange: getBool("notification_config", "notifyScheduleChange", true),
        notifyAnnouncement: getBool("notification_config", "notifyAnnouncement", false),
      },
    }

    return { success: true, data }
  } catch (error) {
    const message = error instanceof Error ? error.message : "Failed to load settings"
    return { success: false, message }
  }
}

/**
 * 保存管理员系统设置
 */
export async function saveAdminSystemSettingsAction(
  values: AdminSettingsFormValues
): Promise<ActionState<null>> {
  try {
    const ctx = await requirePermission(Permissions.SETTINGS_ADMIN)

    const parsed = AdminSettingsFormSchema.parse(values)

    const items = [
      // school_info
      toSettingItem("school_info", "schoolName", parsed.schoolInfo.schoolName, "string"),
      toSettingItem("school_info", "schoolCode", parsed.schoolInfo.schoolCode, "string"),
      toSettingItem("school_info", "schoolPhone", parsed.schoolInfo.schoolPhone, "string"),
      toSettingItem("school_info", "schoolEmail", parsed.schoolInfo.schoolEmail, "string"),
      toSettingItem("school_info", "schoolAddress", parsed.schoolInfo.schoolAddress, "string"),
      toSettingItem("school_info", "schoolDescription", parsed.schoolInfo.schoolDescription, "string"),
      // security_policy
      toSettingItem("security_policy", "passwordMinLength", parsed.securityPolicy.passwordMinLength, "number"),
      toSettingItem("security_policy", "sessionTimeout", parsed.securityPolicy.sessionTimeout, "number"),
      toSettingItem("security_policy", "requireSpecialChar", parsed.securityPolicy.requireSpecialChar, "boolean"),
      toSettingItem("security_policy", "requireUppercase", parsed.securityPolicy.requireUppercase, "boolean"),
      toSettingItem("security_policy", "forcePasswordChange", parsed.securityPolicy.forcePasswordChange, "boolean"),
      // file_upload
      toSettingItem("file_upload", "maxFileSize", parsed.fileUpload.maxFileSize, "number"),
      toSettingItem("file_upload", "allowedTypes", parsed.fileUpload.allowedTypes, "string"),
      // notification_config
      toSettingItem("notification_config", "notifyNewUser", parsed.notificationConfig.notifyNewUser, "boolean"),
      toSettingItem("notification_config", "notifyScheduleChange", parsed.notificationConfig.notifyScheduleChange, "boolean"),
      toSettingItem("notification_config", "notifyAnnouncement", parsed.notificationConfig.notifyAnnouncement, "boolean"),
    ]

    await upsertSystemSettings(items, ctx.userId)

    revalidatePath("/admin/settings")

    return { success: true, data: null }
  } catch (error) {
    const message = error instanceof Error ? error.message : "Failed to save settings"
    return { success: false, message }
  }
}
