import { BaseProvider } from '#templates/base/provider';
import { Bed } from '#models/Bed';
import { ResidentStay } from '#models/ResidentStay';
import { GenericError } from '#interfaces/error/generic';

export class BedProvider extends BaseProvider<Bed> {
	public static instance: BedProvider;

	public static getInstance(): BedProvider {
		BedProvider.instance ??= new BedProvider();
		return BedProvider.instance;
	}

	public static get model() {
		return Bed;
	}

	constructor() {
		super('Bed');
	}

	override async delete(
		id: string,
		options?: {
			transaction?: any;
			force?: boolean;
			deleted_by?: string;
			warnOnActiveChildren?: boolean;
		},
	): Promise<string> {
		return this.executeInTransaction(async (tx) => {
			try {
				const bed = await Bed.findByPk(id, { transaction: tx });
				if (!bed) {
					throw new GenericError('NOT_FOUND', { resource: 'Bed', id });
				}

				// CRITICAL: Check for active resident stays
				const activeStayCount = await ResidentStay.count({
					where: {
						bed_id: id,
						move_out_at: null,
					},
					transaction: tx,
				});

				if (activeStayCount > 0) {
					// NEVER allow delete of occupied bed
					throw new GenericError('VALIDATION_ERROR', {
						message:
							`Cannot delete bed with ${activeStayCount} active resident(s). ` +
							'Occupancy consistency, billing, reporting, and emergency lookup depend on this.',
						id: bed.getDataValue('id'),
						activeResidentCount: activeStayCount,
					});
				}

				// Call BaseProvider delete with deleted_by
				return super.delete(id, { ...options, transaction: tx });
			} catch (error) {
				await this.logError(error as Error);
				throw error;
			}
		}, options?.transaction);
	}

	protected override getUniqueRestoreConstraints(): string[] {
		return ['room_id', 'code'];
	}
}
