import { z } from 'zod';
import { type OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
import {
	RegisterBodySchema,
	RegisterResponseSchema,
	RefreshTokenBodySchema,
	RefreshTokenResponseSchema,
	ProfileResponseSchema,
	LoginMobileResponseSchema,
	MobileLoginBodySchema,
	ZaloLoginBodySchema,
	ZaloLoginResponseSchema,
	SendConfirmOtpResponseSchema,
	RevokeSessionResponseSchema,
	WebLoginResponseSchema,
	WebLoginBodySchema,
	SessionListResponseSchema,
	PasswordResetRequestResponseSchema,
	PasswordResetSubmitResponseSchema,
	ChangePasswordBodySchema,
	ChangePasswordResponseSchema,
} from '#contracts/auth/schema';
import { ApiResponseSchema, ErrorResponseSchema, QueryParamsSchema } from '#contracts/shared';

export function registerAuthPaths(registry: OpenAPIRegistry): void {
	// -------------------------------------------------------------------------
	// POST /auth/register
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/register',
		operationId: 'register',
		tags: ['Authentication'],
		summary: 'User registration',
		security: [],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: RegisterBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'Registration successful',
				content: { 'application/json': { schema: RegisterResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			429: { description: 'Too many requests', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/login/mobile
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/login/mobile',
		operationId: 'loginMobile',
		tags: ['Authentication'],
		summary: 'Mobile login (Bearer token)',
		description: 'Authenticate mobile app users. Tokens are returned in the response body.',
		security: [],
		request: {
			headers: z.object({
				'X-Device-Id': z.string().openapi({ description: 'Unique device identifier (required)' }),
				'X-Device-Name': z.string().optional().openapi({ description: 'Human-readable device name' }),
			}),
			body: {
				required: true,
				content: { 'application/json': { schema: MobileLoginBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'Login successful — tokens in body',
				content: { 'application/json': { schema: LoginMobileResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Invalid credentials', content: { 'application/json': { schema: ErrorResponseSchema } } },
			429: { description: 'Too many requests', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/login/web
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/login/web',
		operationId: 'loginWeb',
		tags: ['Authentication'],
		summary: 'Web login (HttpOnly Cookie)',
		description: 'Authenticate web users with HttpOnly cookies. Tokens stored in HttpOnly cookies (XSS protection).',
		security: [],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: WebLoginBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'Login successful - tokens in HttpOnly cookies',
				content: { 'application/json': { schema: WebLoginResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Invalid credentials', content: { 'application/json': { schema: ErrorResponseSchema } } },
			423: { description: 'Account locked', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/login/zalo
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/login/zalo',
		operationId: 'loginZalo',
		tags: ['Authentication'],
		summary: 'Zalo Mini App login (Bearer token)',
		description: 'Authenticate Zalo Mini App users via Zalo auth code or Open ID.',
		security: [],
		request: {
			headers: z.object({
				'X-Device-Id': z.string().openapi({ description: 'Unique device identifier (REQUIRED)' }),
				'X-Device-Name': z.string().optional().openapi({ description: 'Device name for display' }),
			}),
			body: {
				required: true,
				content: { 'application/json': { schema: ZaloLoginBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'Login successful',
				content: { 'application/json': { schema: ZaloLoginResponseSchema } },
			},
			400: { description: 'Bad Request', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: {
				description: 'Invalid Zalo code or authentication failed',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
			500: {
				description: 'Zalo configuration not set up',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
		},
	});

	// -------------------------------------------------------------------------
	// GET /auth/sessions
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/auth/sessions',
		operationId: 'listSessions',
		tags: ['Authentication'],
		summary: 'List active sessions',
		description: 'Get all active sessions for the authenticated user',
		security: [{ BearerAuth: [] }],
		request: {
			query: QueryParamsSchema,
		},
		responses: {
			200: {
				description: 'List of active sessions',
				content: { 'application/json': { schema: SessionListResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/sessions/{id}/revoke
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/sessions/{id}/revoke',
		operationId: 'revokeSession',
		tags: ['Authentication'],
		summary: 'Revoke a specific session',
		description: 'Revoke a specific active session belonging to the authenticated user',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({
				id: z.string().openapi({ description: 'Session ID to revoke' }),
			}),
		},
		responses: {
			200: {
				description: 'Session revoked successfully',
				content: { 'application/json': { schema: RevokeSessionResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			404: { description: 'Session not found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/logout
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/logout',
		operationId: 'logout',
		tags: ['Authentication'],
		summary: 'Logout user',
		description: 'Logout user and invalidate current session',
		security: [{ BearerAuth: [] }],
		responses: {
			200: {
				description: 'Logged out successfully',
				content: { 'application/json': { schema: ApiResponseSchema(z.null()) } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/logout-all
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/logout-all',
		operationId: 'logoutAll',
		tags: ['Authentication'],
		summary: 'Logout all devices',
		description:
			'Revoke all active sessions for the authenticated user. Requires password confirmation (confirm_password) or OTP (confirm_otp).',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: {
					'application/json': {
						schema: z
							.object({
								confirm_password: z.string().optional(),
								confirm_otp: z.string().optional(),
							})
							.openapi('LogoutAllBody'),
					},
				},
			},
		},
		responses: {
			200: {
				description: 'All sessions revoked successfully',
				content: { 'application/json': { schema: ApiResponseSchema(z.null()) } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			403: {
				description: 'Forbidden - missing or invalid confirmation',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/refresh
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/refresh',
		operationId: 'refreshToken',
		tags: ['Authentication'],
		summary: 'Refresh access token',
		security: [],
		request: {
			body: {
				required: false,
				content: { 'application/json': { schema: RefreshTokenBodySchema } },
			},
		},
		responses: {
			200: {
				description: 'Token refreshed. In development, new tokens are included in response body.',
				content: { 'application/json': { schema: RefreshTokenResponseSchema } },
			},
			401: {
				description: 'Unauthorized — invalid or expired refresh token',
				content: { 'application/json': { schema: ErrorResponseSchema } },
			},
		},
	});

	// -------------------------------------------------------------------------
	// GET /auth/profile
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'get',
		path: '/api/v1/auth/profile',
		operationId: 'getProfile',
		tags: ['Authentication'],
		summary: 'Get authenticated user profile',
		security: [{ BearerAuth: [] }],
		responses: {
			200: {
				description: 'Profile retrieved successfully',
				content: { 'application/json': { schema: ProfileResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/send-confirm-otp
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/send-confirm-otp',
		operationId: 'sendConfirmOtp',
		tags: ['Authentication'],
		summary: 'Request a sensitive-action confirmation OTP',
		description:
			"Generates a 6-digit OTP, stores it in Redis (TTL 5 min), and sends it to the authenticated user's email.",
		security: [{ BearerAuth: [] }],
		responses: {
			200: {
				description: 'OTP generated and sent successfully',
				content: { 'application/json': { schema: SendConfirmOtpResponseSchema } },
			},
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
			429: { description: 'Too many requests', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/forgot-password/send-otp
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/forgot-password/send-otp',
		operationId: 'forgotPasswordSendOtp',
		tags: ['Authentication'],
		summary: 'Request password reset OTP',
		description: 'Send 6-digit OTP code to user email (valid for 10 minutes)',
		security: [],
		request: {
			body: {
				required: true,
				content: { 'application/json': { schema: z.object({ email: z.email() }) } },
			},
		},
		responses: {
			200: {
				description: 'OTP code sent successfully',
				content: { 'application/json': { schema: PasswordResetRequestResponseSchema } },
			},
			404: { description: 'Email not found', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// POST /auth/forgot-password/confirm-reset
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'post',
		path: '/api/v1/auth/forgot-password/confirm-reset',
		operationId: 'forgotPasswordConfirmReset',
		tags: ['Authentication'],
		summary: 'Reset password',
		description: 'Reset user password after OTP verification',
		security: [],
		request: {
			body: {
				required: true,
				content: {
					'application/json': {
						schema: z
							.object({
								email: z.email(),
								code: z.string().length(6),
								new_password: z.string().min(8).max(128),
							})
							.openapi('PasswordResetBody', {
								example: {
									email: 'user@example.com',
									code: '123456',
									new_password: 'SecurePass123',
								},
							}),
					},
				},
			},
		},
		responses: {
			200: {
				description: 'Password reset successfully',
				content: { 'application/json': { schema: PasswordResetSubmitResponseSchema } },
			},
			400: { description: 'Invalid or expired code', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});

	// -------------------------------------------------------------------------
	// PUT /auth/change-password
	// -------------------------------------------------------------------------
	registry.registerPath({
		method: 'put',
		path: '/api/v1/auth/change-password',
		operationId: 'changePassword',
		tags: ['Authentication'],
		summary: 'Change user password',
		description: 'Change authenticated user password. Requires old password verification.',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: {
					'application/json': {
						schema: ChangePasswordBodySchema,
					},
				},
			},
		},
		responses: {
			200: {
				description: 'Password changed successfully',
				content: { 'application/json': { schema: ChangePasswordResponseSchema } },
			},
			400: { description: 'Bad Request - validation failed or invalid old password', content: { 'application/json': { schema: ErrorResponseSchema } } },
			401: { description: 'Unauthorized', content: { 'application/json': { schema: ErrorResponseSchema } } },
		},
	});
}
