import { DefaultEventsMap, Server, Socket } from 'socket.io'
import constants from './constants'
import { IUser } from '../api/users/models'
import { Schema, Types } from 'mongoose'

export type ISocketServer = Server<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>
export type ISocket = Socket<DefaultEventsMap, DefaultEventsMap, DefaultEventsMap, any>
export type SocketEventHandler = (socket: ISocket, data: object) => any

export const scheduleEvents = ['user-offline'] as const
export type ScheduleEvent = typeof scheduleEvents[number]
export type ScheduleEventHandler = (data: Record<string, any>) => any

export type NotificationEvent = typeof constants.notificationEvents[number]

export type SocketEvent = 'user-online' | 'user-offline' | 'typing-started' | 'typing-stopped' | 'messages-read' | 'messages-sent' | 'messages-received' | 'chat-created' | 'account-terminated' | 'chat-joined' | 'chat-participant-removed' | 'chat-deleted' | 'reward-consumed' | 'score-updated'

export type SocketErrorEvent = 'authorization-failed' | 'verification-required' | 'account-terminated' | 'server-error' | 'validation-failed' | 'not-found' | 'permission-denied'

export type IFiles = Record<string, Express.Multer.File[] | undefined> | undefined
export type IFile = Express.Multer.File | undefined

export interface PushNotificationPayload {
  user: IUser
  title: string
  body: string
  event: NotificationEvent
  data?: Record<string, any>
  loggedinDevice?: Types.ObjectId
  deviceType?: 'all' | 'loggedin' | 'others'
}

export interface SocketNotificationPayload {
  userId: string
  event: SocketEvent
  data: Record<string, any>
  currentSocket?: string
  socketType?: 'all' | 'current' | 'others'
}

export interface NotificationPayload {
  user: IUser
  data?: Record<string, any>
  title: string
  description: string
  event: NotificationEvent
  from?: Types.ObjectId
  comment?: Types.ObjectId
  connection?: Types.ObjectId
  follower?: Types.ObjectId
  like?: Types.ObjectId
  superLike?: Types.ObjectId
  reel?: Types.ObjectId
  status?: Types.ObjectId
  chat?: Types.ObjectId
  request?: Types.ObjectId
  meetMeEvent?: Types.ObjectId
  rewardHash?: Types.ObjectId
}

export const LocationSchema = new Schema(
	{
		type: {
			type: String,
			enum: ['Point'],
			required: true
		},
		coordinates: {
			type: [Number],
			required: true,
			validate: {
				validator: (value: [number, number]) => {
					const [lng, lat] = value;
					return (
						lat >= -90 && lat <= 90 &&
						lng >= -180 && lng <= 180
					);
				},
				message: 'Invalid coordinates: latitude must be between -90 and 90, longitude between -180 and 180'
			}
		},
	},
	{ versionKey: false, _id: false }
)

export interface ILocation {
	type: 'Point'
	coordinates: [number, number]  // [longitude, latitude]
}

export interface AICommentPromptResponse {
  isKind: boolean
  isThankyou: boolean
  isNegative?: boolean
  isInappropriate: boolean
}

export interface AIReelPromptResponse {
  comments: string
  isInappropriate: boolean
  isExtremelyInappropriate: boolean
  vectorMetaData: number[]
  isPositive: boolean
  isNegative: boolean
  awarenessExercise?: ('mindful-breathing' | 'noticing-sound' | 'body-awareness' | 'focus-on-object' | 'cloud-watching' | 'mindful-walking' | 'gratitude-anchor')[]
  groundingExercise?: ('54321-technique' | 'body-scan' | 'box-breathing' | 'object-focus' | 'name-label-emotions' | 'mindful-walk-scroll' | 'name-surroundings')[]
  isProductivity: boolean
  isMeditation: boolean
}

export interface ReelData {
  video?: string
  photos?: string[]
  dynamic?: string[]
}
