/**
 * User Factory for Tests
 *
 * Generates test user data using faker-js.
 * Provides factory functions for creating consistent test data.
 */

import { faker } from '@faker-js/faker';

export interface UserFactoryData {
	id?: string;
	email?: string;
	username?: string;
	first_name?: string | null;
	last_name?: string | null;
	phone?: string | null;
	status?: 'active' | 'inactive' | 'suspended' | 'pending_verification';
	avatar?: string | null;
	created_at?: Date;
	updated_at?: Date;
	deleted_at?: Date | null;
}

export interface UserAuthFactoryData {
	id?: string;
	user_id?: string;
	password_hash?: string;
	last_login_at?: Date | null;
	login_attempts?: number;
	locked_until?: Date | null;
	password_changed_at?: Date | null;
	previous_passwords?: string[];
	social_accounts?: Record<string, any>;
	created_at?: Date;
	updated_at?: Date;
}

export interface UserSessionFactoryData {
	id?: string;
	user_id?: string;
	device_info?: Record<string, any>;
	ip_address?: string | null;
	user_agent?: string | null;
	expires_at?: Date;
	refresh_expires_at?: Date;
	is_active?: boolean;
	is_revoked?: boolean;
	permissions?: string[];
	roles?: string[];
	platform?: 'web' | 'mobile' | 'zalo_miniapp' | 'internal';
	device_id?: string | null;
	device_name?: string | null;
	token_version?: number;
	last_activity_at?: Date | null;
	created_at?: Date;
	updated_at?: Date;
}

/**
 * Create a test user
 */
export function createUser(overrides: UserFactoryData = {}): Required<UserFactoryData> {
	const firstName = faker.person.firstName();
	const lastName = faker.person.lastName();

	return {
		id: overrides.id || faker.string.uuid(),
		email: overrides.email || faker.internet.email({ firstName, lastName }).toLowerCase(),
		username: overrides.username || faker.internet.userName({ firstName, lastName }).toLowerCase(),
		first_name: overrides.first_name !== undefined ? overrides.first_name : firstName,
		last_name: overrides.last_name !== undefined ? overrides.last_name : lastName,
		phone: overrides.phone !== undefined ? overrides.phone : faker.phone.number(),
		status: overrides.status || 'active',
		avatar: overrides.avatar !== undefined ? overrides.avatar : null,
		created_at: overrides.created_at || new Date(),
		updated_at: overrides.updated_at || new Date(),
		deleted_at: overrides.deleted_at !== undefined ? overrides.deleted_at : null,
	};
}

/**
 * Create multiple test users
 */
export function createUsers(count: number, overrides?: UserFactoryData): Required<UserFactoryData>[] {
	return Array.from({ length: count }, () => createUser(overrides));
}

/**
 * Create a test user auth
 */
export function createUserAuth(userId: string, overrides: UserAuthFactoryData = {}): Required<UserAuthFactoryData> {
	return {
		id: overrides.id || faker.string.uuid(),
		user_id: userId,
		password_hash: overrides.password_hash || faker.string.alphanumeric(60),
		last_login_at: overrides.last_login_at !== undefined ? overrides.last_login_at : null,
		login_attempts: overrides.login_attempts || 0,
		locked_until: overrides.locked_until !== undefined ? overrides.locked_until : null,
		password_changed_at: overrides.password_changed_at !== undefined ? overrides.password_changed_at : null,
		previous_passwords: overrides.previous_passwords || [],
		social_accounts: overrides.social_accounts || {},
		created_at: overrides.created_at || new Date(),
		updated_at: overrides.updated_at || new Date(),
	};
}

/**
 * Create a test user session
 */
export function createUserSession(
	userId: string,
	overrides: UserSessionFactoryData = {},
): Required<UserSessionFactoryData> {
	const now = new Date();
	const sevenDaysFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);

	return {
		id: overrides.id || faker.string.uuid(),
		user_id: userId,
		device_info: overrides.device_info || { browser: 'Chrome', os: 'Windows' },
		ip_address: overrides.ip_address !== undefined ? overrides.ip_address : faker.internet.ip(),
		user_agent: overrides.user_agent !== undefined ? overrides.user_agent : faker.internet.userAgent(),
		expires_at: overrides.expires_at || sevenDaysFromNow,
		refresh_expires_at: overrides.refresh_expires_at || sevenDaysFromNow,
		is_active: overrides.is_active !== undefined ? overrides.is_active : true,
		is_revoked: overrides.is_revoked !== undefined ? overrides.is_revoked : false,
		permissions: overrides.permissions || ['read:profile'],
		roles: overrides.roles || ['user'],
		platform: overrides.platform || 'web',
		device_id: overrides.device_id !== undefined ? overrides.device_id : null,
		device_name: overrides.device_name !== undefined ? overrides.device_name : null,
		token_version: overrides.token_version || 1,
		last_activity_at: overrides.last_activity_at !== undefined ? overrides.last_activity_at : now,
		created_at: overrides.created_at || now,
		updated_at: overrides.updated_at || now,
	};
}

/**
 * Create a complete user with auth and session
 */
export function createCompleteUser(
	userOverrides: UserFactoryData = {},
	authOverrides: Partial<UserAuthFactoryData> = {},
	sessionOverrides: Partial<UserSessionFactoryData> = {},
) {
	const user = createUser(userOverrides);
	const userAuth = createUserAuth(user.id, { ...authOverrides, user_id: user.id });
	const session = createUserSession(user.id, { ...sessionOverrides, user_id: user.id });

	return {
		user,
		userAuth,
		session,
	};
}

/**
 * Create an admin user
 */
export function createAdminUser(overrides: UserFactoryData = {}): Required<UserFactoryData> {
	return createUser({
		...overrides,
		email: overrides.email || `admin-${faker.string.nanoid(6)}@example.com`,
		username: overrides.username || `admin-${faker.string.nanoid(6)}`,
	});
}

/**
 * Create a suspended user
 */
export function createSuspendedUser(overrides: UserFactoryData = {}): Required<UserFactoryData> {
	return createUser({
		...overrides,
		status: 'suspended',
	});
}

/**
 * Create an inactive user
 */
export function createInactiveUser(overrides: UserFactoryData = {}): Required<UserFactoryData> {
	return createUser({
		...overrides,
		status: 'inactive',
	});
}

/**
 * Create a locked user auth
 */
export function createLockedUserAuth(
	userId: string,
	overrides: UserAuthFactoryData = {},
): Required<UserAuthFactoryData> {
	const lockedUntil = new Date(Date.now() + 30 * 60 * 1000); // 30 minutes from now

	return createUserAuth(userId, {
		...overrides,
		login_attempts: 5,
		locked_until: lockedUntil,
	});
}
