import * as Sequelize from 'sequelize';
import { Op } from 'sequelize';
import { DataTypes, Model, Optional } from 'sequelize';
import type { Contract, ContractId } from './Contract';
import type { ResidentDocument, ResidentDocumentId } from './ResidentDocument';
import type { ResidentEvent, ResidentEventId } from './ResidentEvent';
import type { ResidentStay, ResidentStayId } from './ResidentStay';
import type { User, UserId } from './User';
import type { WebhookLog, WebhookLogId } from './WebhookLog';
export interface ResidentAttributes {
	id: string;
	full_name: string;
	email?: string | null;
	phone?: string | null;
	id_card?: string | null;
	date_of_birth?: string | null;
	full_name_normalized?: string | null;
	email_normalized?: string | null;
	phone_normalized?: string | null;
	id_card_normalized?: string | null;
	emergency_contact_name?: string | null;
	emergency_contact_phone?: string | null;
	emergency_contact_relationship?: string | null;
	status: 'active' | 'inactive' | 'moved_out';
	version: number;
	deleted_at?: Date | null;
	deleted_by?: string | null;
	created_by?: string | null;
	updated_by?: string | null;
	created_at: Date;
	updated_at: Date;
	user_id?: string | null;
	nationality?: string | null;
	job?: string | null;
}
export type ResidentPk = 'id';
export type ResidentId = Resident[ResidentPk];
export type ResidentOptionalAttributes =
	| 'id'
	| 'email'
	| 'phone'
	| 'id_card'
	| 'date_of_birth'
	| 'full_name_normalized'
	| 'email_normalized'
	| 'phone_normalized'
	| 'id_card_normalized'
	| 'emergency_contact_name'
	| 'emergency_contact_phone'
	| 'emergency_contact_relationship'
	| 'status'
	| 'version'
	| 'deleted_at'
	| 'deleted_by'
	| 'created_by'
	| 'updated_by'
	| 'created_at'
	| 'updated_at'
	| 'user_id'
	| 'nationality'
	| 'job';
export type ResidentCreationAttributes = Optional<ResidentAttributes, ResidentOptionalAttributes>;
export class Resident extends Model<ResidentAttributes> implements ResidentAttributes {
	declare id: string;
	declare full_name: string;
	declare email?: string | null;
	declare phone?: string | null;
	declare id_card?: string | null;
	declare date_of_birth?: string | null;
	declare full_name_normalized?: string | null;
	declare email_normalized?: string | null;
	declare phone_normalized?: string | null;
	declare id_card_normalized?: string | null;
	declare emergency_contact_name?: string | null;
	declare emergency_contact_phone?: string | null;
	declare emergency_contact_relationship?: string | null;
	declare status: 'active' | 'inactive' | 'moved_out';
	declare version: number;
	declare deleted_at?: Date | null;
	declare deleted_by?: string | null;
	declare created_by?: string | null;
	declare updated_by?: string | null;
	declare created_at: Date;
	declare updated_at: Date;
	declare user_id?: string | null;
	declare nationality?: string | null;
	declare job?: string | null;
	// Resident hasMany Contract via resident_id
	declare contracts: Contract[];
	declare getContracts: Sequelize.HasManyGetAssociationsMixin<Contract>;
	declare setContracts: Sequelize.HasManySetAssociationsMixin<Contract, ContractId>;
	declare addContract: Sequelize.HasManyAddAssociationMixin<Contract, ContractId>;
	declare addContracts: Sequelize.HasManyAddAssociationsMixin<Contract, ContractId>;
	declare createContract: Sequelize.HasManyCreateAssociationMixin<Contract>;
	declare removeContract: Sequelize.HasManyRemoveAssociationMixin<Contract, ContractId>;
	declare removeContracts: Sequelize.HasManyRemoveAssociationsMixin<Contract, ContractId>;
	declare hasContract: Sequelize.HasManyHasAssociationMixin<Contract, ContractId>;
	declare hasContracts: Sequelize.HasManyHasAssociationsMixin<Contract, ContractId>;
	declare countContracts: Sequelize.HasManyCountAssociationsMixin;
	// Resident hasMany ResidentDocument via resident_id
	declare resident_documents: ResidentDocument[];
	declare getResident_documents: Sequelize.HasManyGetAssociationsMixin<ResidentDocument>;
	declare setResident_documents: Sequelize.HasManySetAssociationsMixin<ResidentDocument, ResidentDocumentId>;
	declare addResident_document: Sequelize.HasManyAddAssociationMixin<ResidentDocument, ResidentDocumentId>;
	declare addResident_documents: Sequelize.HasManyAddAssociationsMixin<ResidentDocument, ResidentDocumentId>;
	declare createResident_document: Sequelize.HasManyCreateAssociationMixin<ResidentDocument>;
	declare removeResident_document: Sequelize.HasManyRemoveAssociationMixin<ResidentDocument, ResidentDocumentId>;
	declare removeResident_documents: Sequelize.HasManyRemoveAssociationsMixin<ResidentDocument, ResidentDocumentId>;
	declare hasResident_document: Sequelize.HasManyHasAssociationMixin<ResidentDocument, ResidentDocumentId>;
	declare hasResident_documents: Sequelize.HasManyHasAssociationsMixin<ResidentDocument, ResidentDocumentId>;
	declare countResident_documents: Sequelize.HasManyCountAssociationsMixin;
	// Resident hasMany ResidentEvent via resident_id
	declare resident_events: ResidentEvent[];
	declare getResident_events: Sequelize.HasManyGetAssociationsMixin<ResidentEvent>;
	declare setResident_events: Sequelize.HasManySetAssociationsMixin<ResidentEvent, ResidentEventId>;
	declare addResident_event: Sequelize.HasManyAddAssociationMixin<ResidentEvent, ResidentEventId>;
	declare addResident_events: Sequelize.HasManyAddAssociationsMixin<ResidentEvent, ResidentEventId>;
	declare createResident_event: Sequelize.HasManyCreateAssociationMixin<ResidentEvent>;
	declare removeResident_event: Sequelize.HasManyRemoveAssociationMixin<ResidentEvent, ResidentEventId>;
	declare removeResident_events: Sequelize.HasManyRemoveAssociationsMixin<ResidentEvent, ResidentEventId>;
	declare hasResident_event: Sequelize.HasManyHasAssociationMixin<ResidentEvent, ResidentEventId>;
	declare hasResident_events: Sequelize.HasManyHasAssociationsMixin<ResidentEvent, ResidentEventId>;
	declare countResident_events: Sequelize.HasManyCountAssociationsMixin;
	// Resident hasMany ResidentStay via resident_id
	declare resident_stays: ResidentStay[];
	declare getResident_stays: Sequelize.HasManyGetAssociationsMixin<ResidentStay>;
	declare setResident_stays: Sequelize.HasManySetAssociationsMixin<ResidentStay, ResidentStayId>;
	declare addResident_stay: Sequelize.HasManyAddAssociationMixin<ResidentStay, ResidentStayId>;
	declare addResident_stays: Sequelize.HasManyAddAssociationsMixin<ResidentStay, ResidentStayId>;
	declare createResident_stay: Sequelize.HasManyCreateAssociationMixin<ResidentStay>;
	declare removeResident_stay: Sequelize.HasManyRemoveAssociationMixin<ResidentStay, ResidentStayId>;
	declare removeResident_stays: Sequelize.HasManyRemoveAssociationsMixin<ResidentStay, ResidentStayId>;
	declare hasResident_stay: Sequelize.HasManyHasAssociationMixin<ResidentStay, ResidentStayId>;
	declare hasResident_stays: Sequelize.HasManyHasAssociationsMixin<ResidentStay, ResidentStayId>;
	declare countResident_stays: Sequelize.HasManyCountAssociationsMixin;
	// Resident hasMany WebhookLog via resident_id
	declare webhook_logs: WebhookLog[];
	declare getWebhook_logs: Sequelize.HasManyGetAssociationsMixin<WebhookLog>;
	declare setWebhook_logs: Sequelize.HasManySetAssociationsMixin<WebhookLog, WebhookLogId>;
	declare addWebhook_log: Sequelize.HasManyAddAssociationMixin<WebhookLog, WebhookLogId>;
	declare addWebhook_logs: Sequelize.HasManyAddAssociationsMixin<WebhookLog, WebhookLogId>;
	declare createWebhook_log: Sequelize.HasManyCreateAssociationMixin<WebhookLog>;
	declare removeWebhook_log: Sequelize.HasManyRemoveAssociationMixin<WebhookLog, WebhookLogId>;
	declare removeWebhook_logs: Sequelize.HasManyRemoveAssociationsMixin<WebhookLog, WebhookLogId>;
	declare hasWebhook_log: Sequelize.HasManyHasAssociationMixin<WebhookLog, WebhookLogId>;
	declare hasWebhook_logs: Sequelize.HasManyHasAssociationsMixin<WebhookLog, WebhookLogId>;
	declare countWebhook_logs: Sequelize.HasManyCountAssociationsMixin;
	// Resident belongsTo User via created_by
	declare created_by_user: User;
	declare getCreated_by_user: Sequelize.BelongsToGetAssociationMixin<User>;
	declare setCreated_by_user: Sequelize.BelongsToSetAssociationMixin<User, UserId>;
	declare createCreated_by_user: Sequelize.BelongsToCreateAssociationMixin<User>;
	// Resident belongsTo User via deleted_by
	declare deleted_by_user: User;
	declare getDeleted_by_user: Sequelize.BelongsToGetAssociationMixin<User>;
	declare setDeleted_by_user: Sequelize.BelongsToSetAssociationMixin<User, UserId>;
	declare createDeleted_by_user: Sequelize.BelongsToCreateAssociationMixin<User>;
	// Resident belongsTo User via updated_by
	declare updated_by_user: User;
	declare getUpdated_by_user: Sequelize.BelongsToGetAssociationMixin<User>;
	declare setUpdated_by_user: Sequelize.BelongsToSetAssociationMixin<User, UserId>;
	declare createUpdated_by_user: Sequelize.BelongsToCreateAssociationMixin<User>;
	// Resident belongsTo User via user_id
	declare user: User;
	declare getUser: Sequelize.BelongsToGetAssociationMixin<User>;
	declare setUser: Sequelize.BelongsToSetAssociationMixin<User, UserId>;
	declare createUser: Sequelize.BelongsToCreateAssociationMixin<User>;
	static initModel(sequelize: Sequelize.Sequelize): typeof Resident {
		return Resident.init(
			{
				id: {
					type: DataTypes.UUID,
					allowNull: false,
					defaultValue: DataTypes.UUIDV4,
					primaryKey: true,
				},
				full_name: {
					type: DataTypes.STRING(200),
					allowNull: false,
				},
				email: {
					type: DataTypes.STRING(255),
					allowNull: true,
				},
				phone: {
					type: DataTypes.STRING(25),
					allowNull: true,
				},
				id_card: {
					type: DataTypes.STRING(50),
					allowNull: true,
				},
				date_of_birth: {
					type: DataTypes.DATEONLY,
					allowNull: true,
				},
				full_name_normalized: {
					type: DataTypes.STRING(200),
					allowNull: true,
					comment: 'Generated column for case-insensitive search and deduplication.',
				},
				email_normalized: {
					type: DataTypes.STRING(255),
					allowNull: true,
				},
				phone_normalized: {
					type: DataTypes.STRING(25),
					allowNull: true,
				},
				id_card_normalized: {
					type: DataTypes.STRING(50),
					allowNull: true,
				},
				emergency_contact_name: {
					type: DataTypes.STRING(200),
					allowNull: true,
				},
				emergency_contact_phone: {
					type: DataTypes.STRING(25),
					allowNull: true,
				},
				emergency_contact_relationship: {
					type: DataTypes.STRING(100),
					allowNull: true,
				},
				status: {
					type: DataTypes.ENUM('active', 'inactive', 'moved_out'),
					allowNull: false,
					defaultValue: 'active',
				},
				version: {
					type: DataTypes.INTEGER,
					allowNull: false,
					defaultValue: 1,
					comment: 'Optimistic locking version. Auto-incremented by trigger on UPDATE.',
				},
				deleted_at: {
					type: DataTypes.DATE,
					allowNull: true,
				},
				deleted_by: {
					type: DataTypes.UUID,
					allowNull: true,
					references: {
						model: 'users',
						key: 'id',
					},
				},
				created_by: {
					type: DataTypes.UUID,
					allowNull: true,
					references: {
						model: 'users',
						key: 'id',
					},
				},
				updated_by: {
					type: DataTypes.UUID,
					allowNull: true,
					references: {
						model: 'users',
						key: 'id',
					},
				},
				created_at: {
					type: DataTypes.DATE,
					allowNull: false,
					defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'),
				},
				updated_at: {
					type: DataTypes.DATE,
					allowNull: false,
					defaultValue: Sequelize.Sequelize.literal('CURRENT_TIMESTAMP'),
				},
				user_id: {
					type: DataTypes.UUID,
					allowNull: true,
					comment:
						'User account linked to this resident. Each resident has exactly one user account for authentication.',
					references: {
						model: 'users',
						key: 'id',
					},
					unique: 'residents_user_id_unique',
				},
				nationality: {
					type: DataTypes.STRING(100),
					allowNull: true,
				},
				job: {
					type: DataTypes.STRING(255),
					allowNull: true,
				},
			},
			{
				sequelize,
				tableName: 'residents',
				schema: 'public',
				hasTrigger: true,
				timestamps: false,

				scopes: {
					default: {
						where: {
							deleted_at: null,
						},
					},
					withDeleted: {},
					onlyDeleted: {
						where: {
							deleted_at: { [Op.ne]: null },
						},
					},
				},
				indexes: [
					{
						name: 'idx_residents_created_at',
						fields: [{ name: 'created_at' }],
					},
					{
						name: 'idx_residents_deleted_at',
						fields: [{ name: 'deleted_at' }],
					},
					{
						name: 'idx_residents_full_name',
						fields: [{ name: 'full_name' }],
					},
					{
						name: 'idx_residents_full_name_trgm',
						fields: [{ name: 'full_name' }],
					},
					{
						name: 'idx_residents_id_card',
						fields: [{ name: 'id_card' }],
					},
					{
						name: 'idx_residents_job',
						fields: [{ name: 'job' }],
					},
					{
						name: 'idx_residents_nationality',
						fields: [{ name: 'nationality' }],
					},
					{
						name: 'idx_residents_status',
						fields: [{ name: 'status' }],
					},
					{
						name: 'idx_residents_user_id',
						fields: [{ name: 'user_id' }],
					},
					{
						name: 'residents_pkey',
						unique: true,
						fields: [{ name: 'id' }],
					},
					{
						name: 'residents_user_id_unique',
						unique: true,
						fields: [{ name: 'user_id' }],
					},
					{
						name: 'uq_residents_email',
						unique: true,
						fields: [{ name: 'email_normalized' }],
					},
					{
						name: 'uq_residents_id_card',
						unique: true,
						fields: [{ name: 'id_card_normalized' }],
					},
					{
						name: 'uq_residents_phone',
						unique: true,
						fields: [{ name: 'phone_normalized' }],
					},
				],
			},
		);
	}
}
