import * as Sequelize from 'sequelize';
import { Op } from 'sequelize';
import { DataTypes, Model, Optional } from 'sequelize';
import type { ContractFile, ContractFileId } from './ContractFile';
import type { FileVariant, FileVariantId } from './FileVariant';
import type { IncidentFile, IncidentFileId } from './IncidentFile';
import type { Post, PostId } from './Post';
import type { ResidentDocument, ResidentDocumentId } from './ResidentDocument';
import type { Technician, TechnicianId } from './Technician';
import type { User, UserId } from './User';
export interface FileAttributes {
	id: string;
	tenant_id?: string | null;
	owner_user_id?: string | null;
	original_name: string;
	display_name?: string | null;
	title?: string | null;
	description?: string | null;
	note?: string | null;
	provider: 'local' | 'minio' | 's3';
	bucket_name: string;
	object_key: string;
	mime_type: string;
	extension?: string | null;
	category?: string | null;
	size_bytes: number;
	width?: number | null;
	height?: number | null;
	duration_sec?: number | null;
	page_count?: number | null;
	checksum_sha_256?: string | null;
	visibility: 'private' | 'tenant' | 'public';
	public_token?: string | null;
	is_library: boolean;
	status: 'pending_upload' | 'uploaded' | 'scanning' | 'quarantined' | 'processing' | 'ready' | 'failed' | 'expired';
	last_error?: string | null;
	processed_at?: Date | null;
	deleted_at?: Date | null;
	deleted_by?: string | null;
	created_by?: string | null;
	updated_by?: string | null;
	created_at: Date;
	updated_at: Date;
}
export type FilePk = 'id';
export type FileId = File[FilePk];
export type FileOptionalAttributes =
	| 'id'
	| 'tenant_id'
	| 'owner_user_id'
	| 'display_name'
	| 'title'
	| 'description'
	| 'note'
	| 'provider'
	| 'bucket_name'
	| 'extension'
	| 'category'
	| 'width'
	| 'height'
	| 'duration_sec'
	| 'page_count'
	| 'checksum_sha_256'
	| 'visibility'
	| 'public_token'
	| 'status'
	| 'last_error'
	| 'processed_at'
	| 'deleted_at'
	| 'deleted_by'
	| 'created_by'
	| 'updated_by'
	| 'created_at'
	| 'updated_at';
export type FileCreationAttributes = Optional<FileAttributes, FileOptionalAttributes>;
export class File extends Model<FileAttributes> implements FileAttributes {
	declare id: string;
	declare tenant_id?: string | null;
	declare owner_user_id?: string | null;
	declare original_name: string;
	declare display_name?: string | null;
	declare title?: string | null;
	declare description?: string | null;
	declare note?: string | null;
	declare provider: 'local' | 'minio' | 's3';
	declare bucket_name: string;
	declare object_key: string;
	declare mime_type: string;
	declare extension?: string | null;
	declare category?: string | null;
	declare size_bytes: number;
	declare width?: number | null;
	declare height?: number | null;
	declare duration_sec?: number | null;
	declare page_count?: number | null;
	declare checksum_sha_256?: string | null;
	declare visibility: 'private' | 'tenant' | 'public';
	declare public_token?: string | null;
	declare is_library: boolean;
	declare status:
		| 'pending_upload'
		| 'uploaded'
		| 'scanning'
		| 'quarantined'
		| 'processing'
		| 'ready'
		| 'failed'
		| 'expired';
	declare last_error?: string | null;
	declare processed_at?: Date | null;
	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;
	// File hasMany ContractFile via file_id
	declare contract_files: ContractFile[];
	declare getContract_files: Sequelize.HasManyGetAssociationsMixin<ContractFile>;
	declare setContract_files: Sequelize.HasManySetAssociationsMixin<ContractFile, ContractFileId>;
	declare addContract_file: Sequelize.HasManyAddAssociationMixin<ContractFile, ContractFileId>;
	declare addContract_files: Sequelize.HasManyAddAssociationsMixin<ContractFile, ContractFileId>;
	declare createContract_file: Sequelize.HasManyCreateAssociationMixin<ContractFile>;
	declare removeContract_file: Sequelize.HasManyRemoveAssociationMixin<ContractFile, ContractFileId>;
	declare removeContract_files: Sequelize.HasManyRemoveAssociationsMixin<ContractFile, ContractFileId>;
	declare hasContract_file: Sequelize.HasManyHasAssociationMixin<ContractFile, ContractFileId>;
	declare hasContract_files: Sequelize.HasManyHasAssociationsMixin<ContractFile, ContractFileId>;
	declare countContract_files: Sequelize.HasManyCountAssociationsMixin;
	// File hasMany FileVariant via file_id
	declare file_variants: FileVariant[];
	declare getFile_variants: Sequelize.HasManyGetAssociationsMixin<FileVariant>;
	declare setFile_variants: Sequelize.HasManySetAssociationsMixin<FileVariant, FileVariantId>;
	declare addFile_variant: Sequelize.HasManyAddAssociationMixin<FileVariant, FileVariantId>;
	declare addFile_variants: Sequelize.HasManyAddAssociationsMixin<FileVariant, FileVariantId>;
	declare createFile_variant: Sequelize.HasManyCreateAssociationMixin<FileVariant>;
	declare removeFile_variant: Sequelize.HasManyRemoveAssociationMixin<FileVariant, FileVariantId>;
	declare removeFile_variants: Sequelize.HasManyRemoveAssociationsMixin<FileVariant, FileVariantId>;
	declare hasFile_variant: Sequelize.HasManyHasAssociationMixin<FileVariant, FileVariantId>;
	declare hasFile_variants: Sequelize.HasManyHasAssociationsMixin<FileVariant, FileVariantId>;
	declare countFile_variants: Sequelize.HasManyCountAssociationsMixin;
	// File hasMany IncidentFile via file_id
	declare incident_files: IncidentFile[];
	declare getIncident_files: Sequelize.HasManyGetAssociationsMixin<IncidentFile>;
	declare setIncident_files: Sequelize.HasManySetAssociationsMixin<IncidentFile, IncidentFileId>;
	declare addIncident_file: Sequelize.HasManyAddAssociationMixin<IncidentFile, IncidentFileId>;
	declare addIncident_files: Sequelize.HasManyAddAssociationsMixin<IncidentFile, IncidentFileId>;
	declare createIncident_file: Sequelize.HasManyCreateAssociationMixin<IncidentFile>;
	declare removeIncident_file: Sequelize.HasManyRemoveAssociationMixin<IncidentFile, IncidentFileId>;
	declare removeIncident_files: Sequelize.HasManyRemoveAssociationsMixin<IncidentFile, IncidentFileId>;
	declare hasIncident_file: Sequelize.HasManyHasAssociationMixin<IncidentFile, IncidentFileId>;
	declare hasIncident_files: Sequelize.HasManyHasAssociationsMixin<IncidentFile, IncidentFileId>;
	declare countIncident_files: Sequelize.HasManyCountAssociationsMixin;
	// File hasMany Post via thumbnail_id
	declare posts: Post[];
	declare getPosts: Sequelize.HasManyGetAssociationsMixin<Post>;
	declare setPosts: Sequelize.HasManySetAssociationsMixin<Post, PostId>;
	declare addPost: Sequelize.HasManyAddAssociationMixin<Post, PostId>;
	declare addPosts: Sequelize.HasManyAddAssociationsMixin<Post, PostId>;
	declare createPost: Sequelize.HasManyCreateAssociationMixin<Post>;
	declare removePost: Sequelize.HasManyRemoveAssociationMixin<Post, PostId>;
	declare removePosts: Sequelize.HasManyRemoveAssociationsMixin<Post, PostId>;
	declare hasPost: Sequelize.HasManyHasAssociationMixin<Post, PostId>;
	declare hasPosts: Sequelize.HasManyHasAssociationsMixin<Post, PostId>;
	declare countPosts: Sequelize.HasManyCountAssociationsMixin;
	// File hasMany ResidentDocument via file_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;
	// File hasMany Technician via avatar_id
	declare technicians: Technician[];
	declare getTechnicians: Sequelize.HasManyGetAssociationsMixin<Technician>;
	declare setTechnicians: Sequelize.HasManySetAssociationsMixin<Technician, TechnicianId>;
	declare addTechnician: Sequelize.HasManyAddAssociationMixin<Technician, TechnicianId>;
	declare addTechnicians: Sequelize.HasManyAddAssociationsMixin<Technician, TechnicianId>;
	declare createTechnician: Sequelize.HasManyCreateAssociationMixin<Technician>;
	declare removeTechnician: Sequelize.HasManyRemoveAssociationMixin<Technician, TechnicianId>;
	declare removeTechnicians: Sequelize.HasManyRemoveAssociationsMixin<Technician, TechnicianId>;
	declare hasTechnician: Sequelize.HasManyHasAssociationMixin<Technician, TechnicianId>;
	declare hasTechnicians: Sequelize.HasManyHasAssociationsMixin<Technician, TechnicianId>;
	declare countTechnicians: Sequelize.HasManyCountAssociationsMixin;
	// File hasMany User via avatar_id
	declare users: User[];
	declare getUsers: Sequelize.HasManyGetAssociationsMixin<User>;
	declare setUsers: Sequelize.HasManySetAssociationsMixin<User, UserId>;
	declare addUser: Sequelize.HasManyAddAssociationMixin<User, UserId>;
	declare addUsers: Sequelize.HasManyAddAssociationsMixin<User, UserId>;
	declare createUser: Sequelize.HasManyCreateAssociationMixin<User>;
	declare removeUser: Sequelize.HasManyRemoveAssociationMixin<User, UserId>;
	declare removeUsers: Sequelize.HasManyRemoveAssociationsMixin<User, UserId>;
	declare hasUser: Sequelize.HasManyHasAssociationMixin<User, UserId>;
	declare hasUsers: Sequelize.HasManyHasAssociationsMixin<User, UserId>;
	declare countUsers: Sequelize.HasManyCountAssociationsMixin;
	// File 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>;
	// File 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>;
	// File belongsTo User via owner_user_id
	declare owner_user: User;
	declare getOwner_user: Sequelize.BelongsToGetAssociationMixin<User>;
	declare setOwner_user: Sequelize.BelongsToSetAssociationMixin<User, UserId>;
	declare createOwner_user: Sequelize.BelongsToCreateAssociationMixin<User>;
	// File 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>;
	static initModel(sequelize: Sequelize.Sequelize): typeof File {
		return File.init(
			{
				id: {
					type: DataTypes.UUID,
					allowNull: false,
					defaultValue: DataTypes.UUIDV4,
					primaryKey: true,
				},
				tenant_id: {
					type: DataTypes.UUID,
					allowNull: true,
				},
				owner_user_id: {
					type: DataTypes.UUID,
					allowNull: true,
					references: {
						model: 'users',
						key: 'id',
					},
				},
				original_name: {
					type: DataTypes.STRING(255),
					allowNull: false,
				},
				display_name: {
					type: DataTypes.STRING(255),
					allowNull: true,
				},
				title: {
					type: DataTypes.STRING(255),
					allowNull: true,
				},
				description: {
					type: DataTypes.TEXT,
					allowNull: true,
				},
				note: {
					type: DataTypes.TEXT,
					allowNull: true,
				},
				provider: {
					type: DataTypes.ENUM('local', 'minio', 's3'),
					allowNull: false,
					defaultValue: 'local',
					unique: 'uq_files_storage_location',
				},
				bucket_name: {
					type: DataTypes.STRING(100),
					allowNull: false,
					defaultValue: '',
					unique: 'uq_files_storage_location',
				},
				object_key: {
					type: DataTypes.TEXT,
					allowNull: false,
					unique: 'uq_files_storage_location',
				},
				mime_type: {
					type: DataTypes.STRING(100),
					allowNull: false,
				},
				extension: {
					type: DataTypes.STRING(20),
					allowNull: true,
				},
				category: {
					type: DataTypes.STRING(50),
					allowNull: true,
				},
				size_bytes: {
					type: DataTypes.BIGINT,
					allowNull: false,
				},
				width: {
					type: DataTypes.INTEGER,
					allowNull: true,
				},
				height: {
					type: DataTypes.INTEGER,
					allowNull: true,
				},
				duration_sec: {
					type: DataTypes.INTEGER,
					allowNull: true,
				},
				page_count: {
					type: DataTypes.INTEGER,
					allowNull: true,
				},
				checksum_sha_256: {
					type: DataTypes.STRING(64),
					allowNull: true,
					field: 'checksum_sha256',
				},
				visibility: {
					type: DataTypes.ENUM('private', 'tenant', 'public'),
					allowNull: false,
					defaultValue: 'private',
				},
				public_token: {
					type: DataTypes.STRING(100),
					allowNull: true,
					unique: 'uq_files_public_token',
				},
				is_library: {
					type: DataTypes.BOOLEAN,
					allowNull: false,
					defaultValue: false,
				},
				status: {
					type: DataTypes.ENUM(
						'pending_upload',
						'uploaded',
						'scanning',
						'quarantined',
						'processing',
						'ready',
						'failed',
						'expired',
					),
					allowNull: false,
					defaultValue: 'pending_upload',
				},
				last_error: {
					type: DataTypes.TEXT,
					allowNull: true,
				},
				processed_at: {
					type: DataTypes.DATE,
					allowNull: true,
				},
				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.fn('now'),
				},
				updated_at: {
					type: DataTypes.DATE,
					allowNull: false,
					defaultValue: Sequelize.Sequelize.fn('now'),
				},
			},
			{
				sequelize,
				tableName: 'files',
				schema: 'public',
				hasTrigger: true,
				timestamps: false,

				scopes: {
					default: {
						where: {
							deleted_at: null,
						},
					},
					withDeleted: {},
					onlyDeleted: {
						where: {
							deleted_at: { [Op.ne]: null },
						},
					},
				},
				indexes: [
					{
						name: 'files_pkey',
						unique: true,
						fields: [{ name: 'id' }],
					},
					{
						name: 'idx_files_category',
						fields: [{ name: 'category' }],
					},
					{
						name: 'idx_files_checksum',
						fields: [{ name: 'checksum_sha256' }],
					},
					{
						name: 'idx_files_is_library',
						fields: [{ name: 'is_library' }],
					},
					{
						name: 'idx_files_owner_created',
						fields: [{ name: 'owner_user_id' }, { name: 'created_at', order: 'DESC' }],
					},
					{
						name: 'idx_files_owner_size',
						fields: [{ name: 'owner_user_id' }, { name: 'size_bytes' }],
					},
					{
						name: 'idx_files_owner_user_id',
						fields: [{ name: 'owner_user_id' }],
					},
					{
						name: 'idx_files_status',
						fields: [{ name: 'status' }],
					},
					{
						name: 'idx_files_status_created',
						fields: [{ name: 'status' }, { name: 'created_at' }],
					},
					{
						name: 'idx_files_tenant_created',
						fields: [{ name: 'tenant_id' }, { name: 'created_at', order: 'DESC' }],
					},
					{
						name: 'idx_files_visibility',
						fields: [{ name: 'visibility' }],
					},
					{
						name: 'uq_files_public_token',
						unique: true,
						fields: [{ name: 'public_token' }],
					},
					{
						name: 'uq_files_storage_location',
						unique: true,
						fields: [{ name: 'provider' }, { name: 'bucket_name' }, { name: 'object_key' }],
					},
				],
			},
		);
	}
}
