import { z } from 'zod';
import { ApiResponseSchema } from '#contracts/shared';
import { normalizePhone } from '#utils/stringUtils';

// ---------------------------------------------------------------------------
// User schemas
// ---------------------------------------------------------------------------

export const UserSchema = z
	.object({
		id: z.uuid(),
		email: z.email(),
		username: z.string().nullable(),
		first_name: z.string().nullable(),
		last_name: z.string().nullable(),
		phone: z.string().nullable(),
		status: z.string(),
		avatar_id: z.uuid().nullable(),
		created_at: z.iso.datetime().nullable(),
		updated_at: z.iso.datetime().nullable(),
	})
	.openapi('User');

export type User = z.infer<typeof UserSchema>;

export const UserCreateBodySchema = z
	.object({
		email: z.email().openapi({ example: 'user@example.com' }),
		password: z.string().min(8).max(128).openapi({ example: 'SecurePass123' }),
		username: z.string().min(3).max(50).optional().openapi({ example: 'johndoe' }),
		first_name: z.string().min(1).max(100).optional().openapi({ example: 'John' }),
		last_name: z.string().min(1).max(100).optional().openapi({ example: 'Doe' }),
		phone: z
			.string()
			.optional()
			.transform((val) => (val ? normalizePhone(val) : null))
			.openapi({ example: '0901234567' }),
		role: z.enum(['user', 'admin', 'system_admin']).optional().openapi({ example: 'user' }),
	})
	.openapi('UserCreateBody');

export const UserUpdateBodySchema = z
	.object({
		username: z.string().min(3).max(50).optional().openapi({ example: 'johndoe_updated' }),
		first_name: z.string().min(1).max(100).optional().openapi({ example: 'John' }),
		last_name: z.string().min(1).max(100).optional().openapi({ example: 'Smith' }),
		avatar_id: z.uuid().nullable().optional().openapi({ example: '550e8400-e29b-41d4-a716-446655440000' }),
	})
	.openapi('UserUpdateBody');

// ---------------------------------------------------------------------------
// Role schemas
// ---------------------------------------------------------------------------

export const RoleSchema = z
	.object({
		id: z.uuid(),
		name: z.string(),
		description: z.string().nullable(),
		created_at: z.iso.datetime().nullable(),
		updated_at: z.iso.datetime().nullable(),
		created_by: z.uuid().nullable(),
		updated_by: z.uuid().nullable(),
	})
	.openapi('Role');

export type Role = z.infer<typeof RoleSchema>;

export const RoleMutateBodySchema = z
	.object({
		name: z.string().min(1).max(100).openapi({ example: 'Manager' }),
		description: z.string().nullable().optional().openapi({ example: 'Can manage users and content' }),
	})
	.openapi('RoleMutateBody');

// ---------------------------------------------------------------------------
// Permission schemas
// ---------------------------------------------------------------------------

export const PermissionSchema = z
	.object({
		id: z.uuid(),
		name: z.string(),
		description: z.string().nullable(),
		resource: z.string(),
		action: z.string(),
		created_at: z.iso.datetime().nullable(),
		created_by: z.uuid().nullable(),
		updated_by: z.uuid().nullable(),
	})
	.openapi('Permission');

export type Permission = z.infer<typeof PermissionSchema>;

export const PermissionMutateBodySchema = z
	.object({
		name: z.string().min(1).max(255).openapi({ example: 'create_user' }),
		description: z.string().nullable().optional().openapi({ example: 'Create new users' }),
		resource: z.string().min(1).max(100).openapi({ example: 'users' }),
		action: z.string().min(1).max(100).openapi({ example: 'create' }),
	})
	.openapi('PermissionMutateBody');

// ---------------------------------------------------------------------------
// Paginated list schemas
// ---------------------------------------------------------------------------

export const UserListDataSchema = z
	.object({
		count: z.number().int(),
		rows: z.array(UserSchema),
		page: z.number().int(),
		pageSize: z.number().int(),
	})
	.openapi('UserListData');

export const RoleListDataSchema = z
	.object({
		count: z.number().int(),
		rows: z.array(RoleSchema),
		page: z.number().int(),
		pageSize: z.number().int(),
	})
	.openapi('RoleListData');

export const PermissionListDataSchema = z
	.object({
		count: z.number().int(),
		rows: z.array(PermissionSchema),
		page: z.number().int(),
		pageSize: z.number().int(),
	})
	.openapi('PermissionListData');

// ---------------------------------------------------------------------------
// Full response schemas (envelope + data)
// ---------------------------------------------------------------------------

export const UserResponseSchema = ApiResponseSchema(UserSchema).openapi('UserResponse');
export type UserResponse = z.infer<typeof UserResponseSchema>;

export const UserListResponseSchema = ApiResponseSchema(UserListDataSchema).openapi('UserListResponse');
export type UserListResponse = z.infer<typeof UserListResponseSchema>;

export const RoleResponseSchema = ApiResponseSchema(RoleSchema).openapi('RoleResponse');
export type RoleResponse = z.infer<typeof RoleResponseSchema>;

export const RoleListResponseSchema = ApiResponseSchema(RoleListDataSchema).openapi('RoleListResponse');
export type RoleListResponse = z.infer<typeof RoleListResponseSchema>;

export const PermissionResponseSchema = ApiResponseSchema(PermissionSchema).openapi('PermissionResponse');
export type PermissionResponse = z.infer<typeof PermissionResponseSchema>;

export const PermissionListResponseSchema =
	ApiResponseSchema(PermissionListDataSchema).openapi('PermissionListResponse');
export type PermissionListResponse = z.infer<typeof PermissionListResponseSchema>;

// ---------------------------------------------------------------------------
// Reset password schema
// ---------------------------------------------------------------------------

export const ResetPasswordResponseDataSchema = z
	.object({
		success: z.boolean(),
	})
	.openapi('ResetPasswordResponseData');

export const ResetPasswordResponseSchema = ApiResponseSchema(ResetPasswordResponseDataSchema).openapi(
	'ResetPasswordResponse',
);
export type ResetPasswordResponse = z.infer<typeof ResetPasswordResponseSchema>;

// ---------------------------------------------------------------------------
// UserRole schemas
// ---------------------------------------------------------------------------

export const UserRoleSchema = z
	.object({
		id: z.uuid(),
		user_id: z.uuid(),
		role_id: z.uuid(),
		assigned_at: z.iso.datetime().nullable(),
		assigned_by: z.uuid().nullable(),
		updated_at: z.iso.datetime().nullable(),
	})
	.openapi('UserRole');

export type UserRole = z.infer<typeof UserRoleSchema>;

export const UserRoleMutateBodySchema = z
	.object({
		user_id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440000' }),
		role_id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440001' }),
	})
	.openapi('UserRoleMutateBody');

export const UserRoleListDataSchema = z
	.object({
		count: z.number().int(),
		rows: z.array(UserRoleSchema),
		page: z.number().int(),
		pageSize: z.number().int(),
	})
	.openapi('UserRoleListData');

export const UserRoleResponseSchema = ApiResponseSchema(UserRoleSchema).openapi('UserRoleResponse');
export type UserRoleResponse = z.infer<typeof UserRoleResponseSchema>;

export const UserRoleListResponseSchema = ApiResponseSchema(UserRoleListDataSchema).openapi('UserRoleListResponse');
export type UserRoleListResponse = z.infer<typeof UserRoleListResponseSchema>;

// ---------------------------------------------------------------------------
// RolePermission schemas
// ---------------------------------------------------------------------------

export const RolePermissionSchema = z
	.object({
		id: z.uuid(),
		role_id: z.uuid(),
		permission_id: z.uuid(),
		created_at: z.iso.datetime().nullable(),
	})
	.openapi('RolePermission');

export type RolePermission = z.infer<typeof RolePermissionSchema>;

export const RolePermissionListDataSchema = z
	.object({
		count: z.number().int(),
		rows: z.array(RolePermissionSchema),
		page: z.number().int(),
		pageSize: z.number().int(),
	})
	.openapi('RolePermissionListData');

export const RolePermissionBulkAssignBodySchema = z
	.object({
		permission_ids: z.array(z.uuid()).openapi({
			example: ['550e8400-e29b-41d4-a716-446655440002', '550e8400-e29b-41d4-a716-446655440003'],
		}),
	})
	.openapi('RolePermissionBulkAssignBody');

export const RolePermissionListResponseSchema =
	ApiResponseSchema(RolePermissionListDataSchema).openapi('RolePermissionListResponse');
export type RolePermissionListResponse = z.infer<typeof RolePermissionListResponseSchema>;

export const RolePermissionArrayResponseSchema = ApiResponseSchema(z.array(RolePermissionSchema)).openapi(
	'RolePermissionArrayResponse',
);
export type RolePermissionArrayResponse = z.infer<typeof RolePermissionArrayResponseSchema>;
