import { ROOM_TYPES, defaultRoomAmenities } from './constants';

/**
 * Room shape held in the edit form state. Type aliases (not interfaces) on
 * purpose: interfaces have no implicit index signature, so an interface[]
 * would not satisfy Inertia's FormDataConvertible and useForm's generic
 * inference would silently degrade the whole edit form to untyped.
 */
export type FormCompositionRoom = {
    id: number;
    amenities: number[];
};

/** Room shape as delivered by the edit endpoint (ids/amenities may be strings). */
export type RawCompositionRoom = {
    id: number | string;
    amenities?: Array<number | string>;
};

export function normalizeComposition(raw: RawCompositionRoom[] | null | undefined): FormCompositionRoom[] {
    return (raw ?? []).map((room) => ({
        id: Number(room.id),
        amenities: (room.amenities ?? []).map(Number),
    }));
}

/**
 * The composition (local mirror of Rentals United's rooms) is the source of
 * truth for the bedroom count. The room count parsed from the property type
 * name is only a fallback for properties whose composition was never filled:
 * deriving the count from the type and trimming the rooms to it destroyed
 * real bedrooms whenever the type lagged behind a save (Rentals United
 * applies pushes asynchronously, so the type can stay stale for a while).
 */
export function resolveBedroomCount(composition: FormCompositionRoom[], typeNumberOfRooms: number | null | undefined, noOfUnits: unknown): number {
    if (composition.length > 0) {
        return composition.filter((room) => room.id === ROOM_TYPES.BEDROOM).length;
    }
    if (typeNumberOfRooms !== null && typeNumberOfRooms !== undefined) {
        return typeNumberOfRooms;
    }
    const parsed = Number(noOfUnits);

    return Number.isFinite(parsed) ? parsed : 0;
}

/** Pads bedrooms/bathrooms up to the targets without ever dropping existing rooms. */
export function buildInitialComposition(
    raw: RawCompositionRoom[] | null | undefined,
    targetBedrooms: number,
    targetBathrooms: number,
): FormCompositionRoom[] {
    const normalized = normalizeComposition(raw);
    const bedrooms = normalized.filter((room) => room.id === ROOM_TYPES.BEDROOM);
    const bathrooms = normalized.filter((room) => room.id === ROOM_TYPES.BATHROOM);
    const others = normalized.filter((room) => room.id !== ROOM_TYPES.BEDROOM && room.id !== ROOM_TYPES.BATHROOM);

    // Only freshly-created (padded) rooms get default amenities. Rooms coming
    // from `raw` (the DB) keep their stored amenities — see normalizeComposition.
    while (bedrooms.length < targetBedrooms) bedrooms.push({ id: ROOM_TYPES.BEDROOM, amenities: defaultRoomAmenities(ROOM_TYPES.BEDROOM) });
    while (bathrooms.length < targetBathrooms) bathrooms.push({ id: ROOM_TYPES.BATHROOM, amenities: defaultRoomAmenities(ROOM_TYPES.BATHROOM) });

    return [...others, ...bedrooms, ...bathrooms];
}
