import { z } from 'zod';
import { type OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
import {
	ResidentCreateBodySchema,
	ResidentUpdateBodySchema,
	ResidentResponseSchema,
	ResidentListResponseSchema,
	ResidentWithResidenceResponseSchema,
	ResidentWithResidenceAndDocumentsResponseSchema,
	ResidentDocumentSchema,
	RoommateListResponseSchema,
	ResidentAddBedsBodySchema,
	ResidentUpdateBedsBodySchema,
} from '#contracts/resident/schema';
import { ApiResponseSchema, QueryParamsSchema, SoftDeleteQueryParamsSchema } from '#contracts/shared';

const DocumentTypeEnum = z.enum([
	'id_card',
	'cccd_front',
	'cccd_back',
	'portrait',
	'passport',
	'household_registration',
	'temporary_residence',
	'contract',
	'other',
]);

const ResidentDocumentCreateBodySchema = z
	.object({
		file_id: z.uuid(),
		document_type: DocumentTypeEnum,
		document_name: z.string().max(255).optional(),
		description: z.string().optional(),
		is_primary: z.boolean().optional().default(false),
	})
	.openapi('ResidentDocumentCreateBody');

const ResidentDocumentBatchCreateBodySchema = z
	.array(ResidentDocumentCreateBodySchema)
	.min(1, 'At least one document is required')
	.openapi('ResidentDocumentBatchCreateBody');

const ResidentDocumentUpdateBodySchema = z
	.object({
		file_id: z.uuid().optional(),
		document_type: DocumentTypeEnum.optional(),
		document_name: z.string().max(255).nullable().optional(),
		description: z.string().nullable().optional(),
		is_primary: z.boolean().optional(),
		issued_date: z.string().optional(),
		expiry_date: z.string().optional(),
		status: z.enum(['pending', 'approved', 'rejected']).optional(),
	})
	.openapi('ResidentDocumentUpdateBody');

export function registerResidentPaths(registry: OpenAPIRegistry): void {
	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents',
		operationId: 'getResidents',
		tags: ['Residents'],
		summary: 'Get all residents with residence info',
		description:
			'Returns list of residents with their current residence location (building, apartment, room, bed) and move-in date. By default, soft-deleted records are excluded (deleted_at==null). To include soft-deleted records, omit the filters parameter or use filters=deleted_at!=null.',
		security: [{ BearerAuth: [] }],
		request: {
			query: SoftDeleteQueryParamsSchema,
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: ResidentListResponseSchema } } },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/residents',
		operationId: 'createResident',
		tags: ['Residents'],
		summary: 'Create resident',
		security: [{ BearerAuth: [] }],
		request: {
			body: { required: true, content: { 'application/json': { schema: ResidentCreateBodySchema } } },
		},
		responses: {
			200: { description: 'Created', content: { 'application/json': { schema: ResidentResponseSchema } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/residents/import',
		operationId: 'importResidentsExcel',
		tags: ['Residents'],
		summary: 'Import residents from Excel file',
		security: [{ BearerAuth: [] }],
		request: {
			body: {
				required: true,
				content: {
					'multipart/form-data': {
						schema: z.object({ file: z.string().openapi({ format: 'binary' }) }),
					},
				},
			},
		},
		responses: {
			200: { description: 'Import result', content: { 'application/json': { schema: z.any() } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents/import/template',
		operationId: 'downloadResidentImportTemplate',
		tags: ['Residents'],
		summary: 'Download Excel template for resident import',
		security: [{ BearerAuth: [] }],
		responses: {
			200: {
				description: 'Excel template file',
				content: { 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': { schema: z.string() } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents/export',
		operationId: 'exportResidents',
		tags: ['Residents'],
		summary: 'Export residents list to Excel file',
		security: [{ BearerAuth: [] }],
		request: {
			query: SoftDeleteQueryParamsSchema,
		},
		responses: {
			200: {
				description: 'Excel file',
				content: { 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': { schema: z.string() } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
		},
	});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents/{id}',
		operationId: 'getResidentById',
		tags: ['Residents'],
		summary: 'Get resident by ID with residence and documents',
		description: 'Returns resident details with current residence location and uploaded documents',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'OK',
				content: { 'application/json': { schema: ResidentWithResidenceAndDocumentsResponseSchema } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/residents/{id}',
		operationId: 'updateResident',
		tags: ['Residents'],
		summary: 'Update resident',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { content: { 'application/json': { schema: ResidentUpdateBodySchema } } },
		},
		responses: {
			200: { description: 'Updated', content: { 'application/json': { schema: ResidentWithResidenceResponseSchema } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/residents/{id}',
		operationId: 'deleteResident',
		tags: ['Residents'],
		summary: 'Delete resident (soft delete)',
		description: 'Soft deletes resident by setting deleted_at timestamp. Use status field to deactivate instead.',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Deleted',
				content: { 'application/json': { schema: ApiResponseSchema(z.null()) } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/resident-documents/{document_id}',
		operationId: 'updateResidentDocumentAdmin',
		tags: ['Residents'],
		summary: 'Admin update a resident document by document_id',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ document_id: z.uuid() }),
			body: { required: true, content: { 'application/json': { schema: ResidentDocumentUpdateBodySchema } } },
		},
		responses: {
			200: { description: 'Updated', content: { 'application/json': { schema: ApiResponseSchema(ResidentDocumentSchema) } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/residents/{id}/restore',
		operationId: 'restoreResident',
		tags: ['Residents'],
		summary: 'Restore a soft-deleted resident',
		description:
			'Restores a soft-deleted resident by setting deleted_at = null. Use force=true to bypass unique constraint checks.',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			query: z.object({
				force: z.coerce.boolean().optional().openapi({
					description: 'Bypass unique constraint checks (default: false)',
				}),
			}),
		},
		responses: {
			200: {
				description: 'Resident restored successfully',
				content: { 'application/json': { schema: ApiResponseSchema(z.string()) } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
			409: { description: 'Conflict - restore would violate unique constraints' },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/residents/{id}/force',
		operationId: 'forceDeleteResident',
		tags: ['Residents'],
		summary: 'Permanently delete a resident',
		description: 'Permanently deletes a resident from the database. Cannot be undone.',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: {
				description: 'Resident permanently deleted',
				content: { 'application/json': { schema: ApiResponseSchema(z.string()) } },
			},
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	// Document management endpoints
	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents/{id}/documents',
		operationId: 'getResidentDocuments',
		tags: ['Residents'],
		summary: 'Get all documents for a resident',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			query: QueryParamsSchema,
		},
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: ResidentListResponseSchema } } },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'post',
		path: '/api/v1/residents/{id}/documents',
		operationId: 'addResidentDocuments',
		tags: ['Residents'],
		summary: 'Add multiple documents to a resident',
		description: 'Add one or multiple documents in array format. Send as an array of document objects.',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { 
				required: true, 
				content: { 
					'application/json': { 
						schema: ResidentDocumentBatchCreateBodySchema
					} 
				} 
			},
		},
		responses: {
			200: { description: 'Created', content: { 'application/json': { schema: ApiResponseSchema(z.array(z.object({}).passthrough())) } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

		// Create documents using resident_id from token
		registry.registerPath({
			method: 'post',
			path: '/api/v1/resident-documents',
			operationId: 'createResidentDocumentsFromToken',
			tags: ['Residents'],
			summary: 'Create resident documents using resident_id from token for users',
			security: [{ BearerAuth: [] }],
			request: {
				body: { required: true, content: { 'application/json': { schema: ResidentDocumentBatchCreateBodySchema } } },
			},
			responses: {
				200: { description: 'Created', content: { 'application/json': { schema: ApiResponseSchema(z.array(ResidentDocumentSchema)) } } },
				400: { description: 'Bad Request' },
				401: { description: 'Unauthorized' },
				403: { description: 'Forbidden' },
			},
		});

	registry.registerPath({
		method: 'get',
		path: '/api/v1/residents/{id}/roommates',
		operationId: 'getResidentRoommates',
		tags: ['Residents'],
		summary: 'Get roommates of a resident',
		description: 'Returns list of residents in the same room with their phone numbers and bed information',
		security: [{ BearerAuth: [] }],
		request: { params: z.object({ id: z.uuid() }) },
		responses: {
			200: { description: 'OK', content: { 'application/json': { schema: RoommateListResponseSchema } } },
			401: { description: 'Unauthorized' },
			404: { description: 'Not Found' },
		},
	});

	// Bed management endpoints
	registry.registerPath({
		method: 'post',
		path: '/api/v1/residents/{id}/beds',
		operationId: 'addResidentBeds',
		tags: ['Residents'],
		summary: 'Add beds to a resident',
		description: 'Adds one or multiple beds to a resident with optional move-in date and stay type',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { required: true, content: { 'application/json': { schema: ResidentAddBedsBodySchema } } },
		},
		responses: {
			200: { description: 'Beds added', content: { 'application/json': { schema: ResidentWithResidenceResponseSchema } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'put',
		path: '/api/v1/residents/{id}/beds',
		operationId: 'updateResidentBeds',
		tags: ['Residents'],
		summary: 'Update beds for a resident',
		description: 'Updates the list of beds for a resident. Beds not in the new list will be marked as moved out, and new beds will be added.',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: { required: true, content: { 'application/json': { schema: ResidentUpdateBedsBodySchema } } },
		},
		responses: {
			200: { description: 'Beds updated', content: { 'application/json': { schema: ResidentWithResidenceResponseSchema } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});

	registry.registerPath({
		method: 'delete',
		path: '/api/v1/residents/{id}/beds',
		operationId: 'removeResidentBeds',
		tags: ['Residents'],
		summary: 'Remove beds from a resident',
		description: 'Removes one or multiple beds from a resident with optional move-out date, reason and notes',
		security: [{ BearerAuth: [] }],
		request: {
			params: z.object({ id: z.uuid() }),
			body: {
				required: true,
				content: {
					'application/json': {
						schema: z.object({
							bed_ids: z.array(z.uuid()).min(1),
							move_out_at: z.string().optional(),
							move_out_reason: z.string().optional(),
							move_out_notes: z.string().optional(),
						}),
					},
				},
			},
		},
		responses: {
			200: { description: 'Beds removed', content: { 'application/json': { schema: ResidentWithResidenceResponseSchema } } },
			400: { description: 'Bad Request' },
			401: { description: 'Unauthorized' },
			403: { description: 'Forbidden' },
			404: { description: 'Not Found' },
		},
	});
}
