"use server"

import { revalidatePath } from "next/cache"
import { getTranslations } from "next-intl/server"
import { PermissionDeniedError, requirePermission } from "@/shared/lib/auth-guard"
import { trackEvent } from "@/shared/lib/track-event"
import { Permissions } from "@/shared/types/permissions"
import type { ActionState } from "@/shared/types/action-state"
import { sendNotification } from "@/modules/notifications/dispatcher"

import {
  SendMessageSchema,
  MessageIdSchema,
  UpdateNotificationPreferencesSchema,
} from "./schema"
import {
  getMessages,
  getMessageById,
  createMessage,
  markMessageAsRead,
  deleteMessage,
  getRecipients,
  getUnreadMessageCount,
  toggleMessageStar,
  getMessageDrafts,
  createMessageDraft,
  updateMessageDraft,
  deleteMessageDraft,
} from "./data-access"
import {
  getNotificationPreferences,
  upsertNotificationPreferences,
} from "@/modules/notifications/preferences"
import type { Message, MessageType, RecipientOption } from "./types"
import type {
  NotificationPreferences,
  UpdateNotificationPreferencesInput,
} from "@/modules/notifications/types"

export async function sendMessageAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_SEND)

    const parsed = SendMessageSchema.safeParse({
      receiverId: formData.get("receiverId"),
      subject: formData.get("subject") || undefined,
      content: formData.get("content"),
      parentMessageId: formData.get("parentMessageId") || undefined,
    })

    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    const input = parsed.data
    if (input.receiverId === ctx.userId) {
      return { success: false, message: "Cannot send a message to yourself" }
    }

    const id = await createMessage({
      senderId: ctx.userId,
      receiverId: input.receiverId,
      subject: input.subject,
      content: input.content,
      parentMessageId: input.parentMessageId,
    })

    // Notify the receiver about the new message via the notifications dispatcher.
    // This respects user notification preferences (SMS/WeChat/Email/In-App).
    const t = await getTranslations("messages")
    const notifyTitle = input.subject
      ? t("notification.messageTitle", { subject: input.subject })
      : t("notification.messageTitleNoSubject")
    await sendNotification({
      userId: input.receiverId,
      type: "info",
      title: notifyTitle,
      content: input.content.slice(0, 200),
      actionUrl: `/messages/${id}`,
      metadata: { messageType: "message", messageId: id },
    })

    revalidatePath("/messages")
    revalidatePath(`/messages/${id}`)

    void trackEvent({
      event: "message.sent",
      userId: ctx.userId,
      targetId: id,
      targetType: "message",
      properties: { receiverId: input.receiverId, hasSubject: !!input.subject },
    })

    return { success: true, message: "Message sent", data: id }
  } 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 markMessageAsReadAction(messageId: string): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)

    const parsed = MessageIdSchema.safeParse({ messageId })
    if (!parsed.success) {
      return { success: false, message: "Invalid message id", errors: parsed.error.flatten().fieldErrors }
    }

    await markMessageAsRead(parsed.data.messageId, ctx.userId)
    revalidatePath("/messages")
    revalidatePath(`/messages/${parsed.data.messageId}`)

    void trackEvent({
      event: "message.marked_read",
      userId: ctx.userId,
      targetId: parsed.data.messageId,
      targetType: "message",
    })

    return { success: true, message: "Marked as read" }
  } 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 deleteMessageAction(messageId: string): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_DELETE)

    const parsed = MessageIdSchema.safeParse({ messageId })
    if (!parsed.success) {
      return { success: false, message: "Invalid message id", errors: parsed.error.flatten().fieldErrors }
    }

    await deleteMessage(parsed.data.messageId, ctx.userId)
    revalidatePath("/messages")
    revalidatePath(`/messages/${parsed.data.messageId}`)

    void trackEvent({
      event: "message.deleted",
      userId: ctx.userId,
      targetId: parsed.data.messageId,
      targetType: "message",
    })

    return { success: true, message: "Message deleted" }
  } 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 getMessagesAction(
  params: { type: MessageType; page?: number; pageSize?: number; keyword?: string }
): Promise<ActionState<{ items: Message[]; total: number; page: number; pageSize: number; totalPages: number }>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)
    const result = await getMessages({ userId: ctx.userId, ...params })
    return { success: true, data: result }
  } 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 getMessageDetailAction(messageId: string): Promise<ActionState<Message>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)

    const parsed = MessageIdSchema.safeParse({ messageId })
    if (!parsed.success) {
      return { success: false, message: "Invalid message id", errors: parsed.error.flatten().fieldErrors }
    }

    const validMessageId = parsed.data.messageId
    const message = await getMessageById(validMessageId, ctx.userId)
    if (!message) return { success: false, message: "Message not found" }
    // Auto-mark as read when viewed by receiver
    if (!message.isRead && message.receiverId === ctx.userId) {
      await markMessageAsRead(validMessageId, ctx.userId)
      revalidatePath("/messages")
    }
    return { success: true, data: message }
  } 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 getRecipientsAction(): Promise<ActionState<RecipientOption[]>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_SEND)
    const recipients = await getRecipients(ctx.userId, ctx.dataScope)
    return { success: true, data: recipients }
  } 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 getUnreadMessageCountAction(): Promise<ActionState<number>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)
    const count = await getUnreadMessageCount(ctx.userId)
    return { success: true, data: count }
  } 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" }
  }
}

// ---------------------------------------------------------------------------
// V2-P2-13c: 消息星标 Server Actions
// ---------------------------------------------------------------------------

export async function toggleMessageStarAction(messageId: string): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)

    const parsed = MessageIdSchema.safeParse({ messageId })
    if (!parsed.success) {
      return { success: false, message: "Invalid message id", errors: parsed.error.flatten().fieldErrors }
    }

    await toggleMessageStar(parsed.data.messageId, ctx.userId)
    revalidatePath("/messages")
    revalidatePath(`/messages/${parsed.data.messageId}`)

    void trackEvent({
      event: "message.star_toggled",
      userId: ctx.userId,
      targetId: parsed.data.messageId,
      targetType: "message",
    })

    return { success: true, message: "Star toggled" }
  } 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" }
  }
}

// ---------------------------------------------------------------------------
// V2-P2-13c: 消息草稿 Server Actions
// ---------------------------------------------------------------------------

export async function getMessageDraftsAction(): Promise<ActionState<import("./types").MessageDraft[]>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_SEND)
    const drafts = await getMessageDrafts(ctx.userId)
    return { success: true, data: drafts }
  } 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 saveMessageDraftAction(
  prevState: ActionState<string> | null,
  formData: FormData
): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_SEND)

    const draftId = formData.get("draftId") as string | null
    const receiverId = formData.get("receiverId") as string | null
    const subject = formData.get("subject") as string | null
    const content = formData.get("content") as string | null
    const parentMessageId = formData.get("parentMessageId") as string | null

    if (draftId) {
      // 更新现有草稿
      await updateMessageDraft(draftId, ctx.userId, {
        receiverId: receiverId || null,
        subject: subject || null,
        content: content || null,
        parentMessageId: parentMessageId || null,
      })
      return { success: true, message: "Draft saved", data: draftId }
    }

    // 创建新草稿
    const id = await createMessageDraft({
      userId: ctx.userId,
      receiverId: receiverId || null,
      subject: subject || null,
      content: content || null,
      parentMessageId: parentMessageId || null,
    })

    return { success: true, message: "Draft created", data: id }
  } 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 deleteMessageDraftAction(draftId: string): Promise<ActionState<string>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_SEND)

    await deleteMessageDraft(draftId, ctx.userId)
    revalidatePath("/messages/compose")

    return { success: true, message: "Draft deleted" }
  } 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" }
  }
}

// ---------------------------------------------------------------------------
// 通知相关 Server Actions（getNotificationsAction / markNotificationAsReadAction /
// markAllNotificationsAsReadAction / getUnreadNotificationCountAction）已迁移至
// @/modules/notifications/actions。请直接从 notifications 模块导入。
// ---------------------------------------------------------------------------

export async function getNotificationPreferencesAction(): Promise<ActionState<NotificationPreferences>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)
    const prefs = await getNotificationPreferences(ctx.userId)
    return { success: true, data: prefs }
  } 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 updateNotificationPreferencesAction(
  prevState: ActionState<NotificationPreferences> | null,
  formData: FormData
): Promise<ActionState<NotificationPreferences>> {
  try {
    const ctx = await requirePermission(Permissions.MESSAGE_READ)

    // 从 FormData 中解析布尔值（checkbox 提交 "on" 或不提交）
    const parseBool = (key: string): boolean => formData.get(key) === "on"
    // 从 FormData 中解析时间字符串（"HH:mm"），空字符串转为 null
    const parseTime = (key: string): string | null => {
      const v = formData.get(key)
      if (typeof v !== "string") return null
      const trimmed = v.trim()
      return trimmed.length > 0 ? trimmed : null
    }

    const parsed = UpdateNotificationPreferencesSchema.safeParse({
      emailEnabled: parseBool("emailEnabled"),
      smsEnabled: parseBool("smsEnabled"),
      pushEnabled: parseBool("pushEnabled"),
      homeworkNotifications: parseBool("homeworkNotifications"),
      gradeNotifications: parseBool("gradeNotifications"),
      announcementNotifications: parseBool("announcementNotifications"),
      messageNotifications: parseBool("messageNotifications"),
      attendanceNotifications: parseBool("attendanceNotifications"),
      quietHoursEnabled: parseBool("quietHoursEnabled"),
      quietHoursStart: parseTime("quietHoursStart"),
      quietHoursEnd: parseTime("quietHoursEnd"),
    })

    if (!parsed.success) {
      return { success: false, message: "Invalid form data", errors: parsed.error.flatten().fieldErrors }
    }

    const input: UpdateNotificationPreferencesInput = parsed.data

    const updated = await upsertNotificationPreferences(ctx.userId, input)
    if (!updated) {
      return { success: false, message: "Failed to update notification preferences" }
    }

    revalidatePath("/settings")

    return { success: true, message: "Notification preferences updated", data: updated }
  } 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" }
  }
}
