import { z } from 'zod';
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
import { ApiResponseSchema, uuidSchema } from '#contracts/shared';
import { normalizePhone } from '#utils/stringUtils';

extendZodWithOpenApi(z);

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

// Request body schemas for validation and OpenAPI documentation
export const ResidentCreateBodySchema = z
	.object({
		full_name: z.string().min(1).max(200).openapi({ example: 'Nguyễn Văn A' }),
		email: z.string().email().max(255).optional().openapi({ example: 'nguyenvana@example.com' }),
		phone: z
			.string()
			.max(25)
			.optional()
			.transform((val) => (val ? normalizePhone(val) : null))
			.openapi({ example: '0901234567' }),
		id_card: z.string().max(50).optional().openapi({ example: '001234567890' }),
		date_of_birth: z.string().optional().openapi({ example: '1990-05-15' }),
		nationality: z.string().max(100).optional().openapi({ example: 'Việt Nam' }),
		job: z.string().max(255).optional().openapi({ example: 'Kỹ sư phần mềm' }),
		emergency_contact_name: z.string().max(200).optional().openapi({ example: 'Nguyễn Thị B' }),
		emergency_contact_phone: z
			.string()
			.max(25)
			.optional()
			.transform((val) => (val ? normalizePhone(val) : null))
			.openapi({ example: '0902345678' }),
		emergency_contact_relationship: z.string().max(100).optional().openapi({ example: 'Vợ' }),
		status: ResidentStatusEnum.optional().default('active').openapi({ example: 'active' }),
		// Optional residence info for immediate move-in
		bed_ids: z
			.array(uuidSchema)
			.optional()
			.openapi({ example: ['00000001-0001-0001-0001-000000000014', '00000001-0001-0001-0001-000000000015'] }),
		move_in_at: z.string().optional().openapi({ example: '2024-01-15T08:30:00Z' }),
	})
	.openapi('ResidentCreateBody');

export const ResidentUpdateBodySchema = z
	.object({
		full_name: z.string().min(1).max(200).optional().openapi({ example: 'Nguyễn Văn A' }),
		email: z.string().email().max(255).optional().openapi({ example: 'nguyenvana@example.com' }),
		id_card: z.string().max(50).optional().openapi({ example: '001234567890' }),
		date_of_birth: z.string().optional().openapi({ example: '1990-05-15' }),
		nationality: z.string().max(100).optional().openapi({ example: 'Việt Nam' }),
		job: z.string().max(255).optional().openapi({ example: 'Kỹ sư phần mềm' }),
		version: z.number().int().positive().optional().openapi({ example: 1 }),
		emergency_contact_name: z.string().max(200).optional().openapi({ example: 'Nguyễn Thị B' }),
		emergency_contact_phone: z
			.string()
			.max(25)
			.optional()
			.transform((val) => (val ? normalizePhone(val) : null))
			.openapi({ example: '0902345678' }),
		emergency_contact_relationship: z.string().max(100).optional().openapi({ example: 'Vợ' }),
		status: ResidentStatusEnum.optional().openapi({ example: 'active' }),
		avatar_id: z.uuid().optional().openapi({ example: '550e8400-e29b-41d4-a716-446655440000' }),
	})
	.openapi('ResidentUpdateBody');

// Response schemas for OpenAPI documentation
export const UserInfoSchema = z
	.object({
		id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440000' }),
		email: z.string().openapi({ example: 'nguyenvana@example.com' }),
		username: z.string().nullable().openapi({ example: 'nguyenvana' }),
		first_name: z.string().nullable().openapi({ example: 'Nguyễn' }),
		last_name: z.string().nullable().openapi({ example: 'Văn A' }),
		phone: z.string().nullable().openapi({ example: '0901234567' }),
		status: z
			.enum(['active', 'inactive', 'suspended', 'pending_verification'])
			.nullable()
			.openapi({ example: 'active' }),
	})
	.openapi('UserInfo');
export const ResidentSchema = z
	.object({
		id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440001' }),
		user_id: z.uuid().nullable().openapi({ example: '550e8400-e29b-41d4-a716-446655440000' }),
		user: UserInfoSchema.nullable().optional(),
		full_name: z.string().openapi({ example: 'Nguyễn Văn A' }),
		email: z.string().nullable().openapi({ example: 'nguyenvana@example.com' }),
		phone: z.string().nullable().openapi({ example: '0901234567' }),
		id_card: z.string().nullable().openapi({ example: '001234567890' }),
		date_of_birth: z.string().nullable().openapi({ example: '1990-05-15' }),
		nationality: z.string().nullable().openapi({ example: 'Việt Nam' }),
		job: z.string().nullable().openapi({ example: 'Kỹ sư phần mềm' }),
		emergency_contact_name: z.string().nullable().openapi({ example: 'Nguyễn Thị B' }),
		emergency_contact_phone: z.string().nullable().openapi({ example: '0902345678' }),
		emergency_contact_relationship: z.string().nullable().openapi({ example: 'Vợ' }),
		status: ResidentStatusEnum.openapi({ example: 'active' }),
		version: z.number().int().positive().openapi({ example: 1 }),
		created_at: z.iso.datetime().openapi({ example: '2024-01-15T08:30:00Z' }),
		updated_at: z.iso.datetime().nullable().openapi({ example: '2024-01-20T10:00:00Z' }),
		deleted_at: z.iso.datetime().nullable().openapi({ example: null }),
	})
	.openapi('Resident');

export const ResidentDocumentSchema = z
	.object({
		id: z.uuid().openapi({ example: '660e8400-e29b-41d4-a716-446655440001' }),
		resident_id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440001' }),
		file_id: z.uuid().openapi({ example: '770e8400-e29b-41d4-a716-446655440001' }),
		document_type: DocumentTypeEnum.openapi({ example: 'id_card' }),
		document_name: z.string().nullable().openapi({ example: 'CCCD Nguyễn Văn A' }),
		description: z.string().nullable().openapi({ example: 'Căn cước công dân' }),
		is_primary: z.boolean().openapi({ example: true }),
		// Document metadata
		issued_date: z.string().nullable().openapi({ example: '2020-01-15' }),
		expiry_date: z.string().nullable().openapi({ example: '2030-01-15' }),
		verified_at: z.iso.datetime().nullable().openapi({ example: '2024-01-16T09:00:00Z' }),
		verified_by: z.string().uuid().nullable().openapi({ example: '550e8400-e29b-41d4-a716-446655440002' }),
		created_at: z.iso.datetime().openapi({ example: '2024-01-15T08:30:00Z' }),
		updated_at: z.iso.datetime().nullable().openapi({ example: '2024-01-16T09:00:00Z' }),
		deleted_at: z.iso.datetime().nullable().openapi({ example: null }),
	})
	.openapi('ResidentDocument');

export const ResidenceInfoSchema = z
	.object({
		building_id: z.uuid().nullable().openapi({ example: '880e8400-e29b-41d4-a716-446655440001' }),
		building_name: z.string().nullable().openapi({ example: 'Tòa nhà A' }),
		building_code: z.string().nullable().openapi({ example: 'TNA-001' }),
		apartment_id: z.uuid().nullable().openapi({ example: '990e8400-e29b-41d4-a716-446655440001' }),
		apartment_name: z.string().nullable().openapi({ example: 'Căn hộ 101' }),
		apartment_code: z.string().nullable().openapi({ example: 'CH-101' }),
		apartment_floor: z.number().nullable().openapi({ example: 1 }),
		room_id: z.uuid().nullable().openapi({ example: 'aa0e8400-e29b-41d4-a716-446655440001' }),
		room_name: z.string().nullable().openapi({ example: 'Phòng 101A' }),
		room_code: z.string().nullable().openapi({ example: 'P-101A' }),
		bed_id: z.uuid().nullable().openapi({ example: 'bb0e8400-e29b-41d4-a716-446655440001' }),
		bed_name: z.string().nullable().openapi({ example: 'Giường 1' }),
		bed_code: z.string().nullable().openapi({ example: 'G-001' }),
		move_in_at: z.iso.datetime().nullable().openapi({ example: '2024-01-15T08:00:00Z' }),
	})
	.openapi('ResidenceInfo');

export const ResidentSchemaWithDocuments = z
	.object({
		id: z.uuid(),
		user_id: z.uuid().nullable(),
		user: UserInfoSchema.nullable().optional(),
		full_name: z.string(),
		email: z.string().nullable(),
		phone: z.string().nullable(),
		id_card: z.string().nullable(),
		date_of_birth: z.string().nullable(),
		emergency_contact_name: z.string().nullable(),
		emergency_contact_phone: z.string().nullable(),
		emergency_contact_relationship: z.string().nullable(),
		status: ResidentStatusEnum,
		version: z.number().int().positive(),
		created_at: z.iso.datetime(),
		updated_at: z.iso.datetime().nullable(),
		deleted_at: z.iso.datetime().nullable(),
		documents: z.array(ResidentDocumentSchema).optional(),
	})
	.openapi('ResidentWithDocuments');

export const ResidentWithResidenceSchema = z
	.object({
		id: z.uuid(),
		user_id: z.uuid().nullable(),
		user: UserInfoSchema.nullable().optional(),
		full_name: z.string(),
		email: z.string().nullable(),
		phone: z.string().nullable(),
		id_card: z.string().nullable(),
		date_of_birth: z.string().nullable(),
		emergency_contact_name: z.string().nullable(),
		emergency_contact_phone: z.string().nullable(),
		emergency_contact_relationship: z.string().nullable(),
		status: ResidentStatusEnum,
		version: z.number().int().positive(),
		created_at: z.iso.datetime(),
		updated_at: z.iso.datetime().nullable(),
		deleted_at: z.iso.datetime().nullable(),
		residence: ResidenceInfoSchema.optional(),
	})
	.openapi('ResidentWithResidence');

export const ResidentWithResidenceAndDocumentsSchema = z
	.object({
		id: z.uuid(),
		user_id: z.uuid().nullable(),
		user: UserInfoSchema.nullable().optional(),
		full_name: z.string(),
		email: z.string().nullable(),
		phone: z.string().nullable(),
		id_card: z.string().nullable(),
		date_of_birth: z.string().nullable(),
		emergency_contact_name: z.string().nullable(),
		emergency_contact_phone: z.string().nullable(),
		emergency_contact_relationship: z.string().nullable(),
		status: ResidentStatusEnum,
		version: z.number().int().positive(),
		created_at: z.iso.datetime(),
		updated_at: z.iso.datetime().nullable(),
		deleted_at: z.iso.datetime().nullable(),
		residence: ResidenceInfoSchema.optional(),
		documents: z.array(ResidentDocumentSchema).optional(),
	})
	.openapi('ResidentWithResidenceAndDocuments');

export const ResidentListDataSchema = z
	.object({
		count: z.number(),
		rows: z.array(ResidentWithResidenceSchema),
		page: z.number(),
		pageSize: z.number(),
	})
	.openapi('ResidentListData');

export const ResidentResponseSchema = ApiResponseSchema(ResidentSchema).openapi('ResidentResponse');

export const ResidentListResponseSchema = ApiResponseSchema(ResidentListDataSchema).openapi('ResidentListResponse');

export const ResidentWithDocumentsResponseSchema = ApiResponseSchema(ResidentSchemaWithDocuments).openapi(
	'ResidentWithDocumentsResponse',
);

export const ResidentWithResidenceResponseSchema = ApiResponseSchema(ResidentWithResidenceSchema).openapi(
	'ResidentWithResidenceResponse',
);

export const ResidentWithResidenceAndDocumentsResponseSchema = ApiResponseSchema(
	ResidentWithResidenceAndDocumentsSchema,
).openapi('ResidentWithResidenceAndDocumentsResponse');

// Roommate schema
export const RoommateSchema = z
	.object({
		resident_id: z.uuid().openapi({ example: '550e8400-e29b-41d4-a716-446655440002' }),
		full_name: z.string().openapi({ example: 'Nguyễn Văn B' }),
		phone: z.string().nullable().openapi({ example: '0333748720' }),
		bed_id: z.uuid().openapi({ example: 'bb0e8400-e29b-41d4-a716-446655440002' }),
		bed_name: z.string().openapi({ example: 'Giường 2' }),
		bed_code: z.string().openapi({ example: 'G-002' }),
		room_id: z.uuid().openapi({ example: 'aa0e8400-e29b-41d4-a716-446655440001' }),
		room_name: z.string().openapi({ example: 'Phòng 101A' }),
		room_code: z.string().openapi({ example: 'P-101A' }),
	})
	.openapi('Roommate');

export const RoommateListDataSchema = z
	.object({
		count: z.number(),
		rows: z.array(RoommateSchema),
	})
	.openapi('RoommateListData');

export const RoommateListResponseSchema = ApiResponseSchema(RoommateListDataSchema).openapi('RoommateListResponse');

// Schemas for managing resident bed_ids
export const ResidentAddBedsBodySchema = z
	.object({
		bed_ids: z.array(uuidSchema).min(1).openapi({ example: ['00000001-0001-0001-0001-000000000014'] }),
		move_in_at: z.string().optional().openapi({ example: '2024-01-15T08:30:00Z' }),
		stay_type: z.enum(['permanent', 'temporary']).optional().default('permanent').openapi({ example: 'permanent' }),
	})
	.openapi('ResidentAddBedsBody');

export const ResidentUpdateBedsBodySchema = z
	.object({
		bed_ids: z.array(uuidSchema).min(1).openapi({ example: ['00000001-0001-0001-0001-000000000015'] }),
		move_out_at: z.string().optional().openapi({ example: '2024-12-15T10:00:00Z' }),
		move_out_reason: z.string().optional().openapi({ example: ' chuyển phòng' }),
		move_out_notes: z.string().optional().openapi({ example: 'Yêu cầu chuyển sang phòng khác' }),
	})
	.openapi('ResidentUpdateBedsBody');
