/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/naming-convention */
import {inject} from '@loopback/core';
import {
  AnyObject,
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  del,
  get,
  getModelSchemaRef,
  HttpErrors,
  param,
  patch,
  post,
  put,
  Request,
  requestBody,
  response,
  RestBindings,
} from '@loopback/rest';
import axios from 'axios';
import {URL} from '../config/constants';
import {PostPropertyMaster} from '../models';
import {
  BestpropertyLaunchRepository,
  NewLaunchMasterRepository,
  PostPropertyAmenitiesRepository,
  PostPropertyMasterRepository,
  RecommendedLaunchRepository
} from '../repositories';

import fs from 'fs';
import multer from 'multer';
import path from 'path';

const BASE_URL = URL;
const FALLBACK_URL = `${BASE_URL}/default.jpg`;

// --- Helper to resolve any type of photo value ---
function resolvePhoto(photo?: string | null): string {
  if (!photo) return FALLBACK_URL;

  const filename = path.basename(photo);

  // Return correct URL that points to the served static folder
  return `${BASE_URL}/uploads/property-images/${filename}`;
}

function resolveVideo(video?: string | null): string {
  if (!video) return FALLBACK_URL;

  const filename = path.basename(video);
  return `${BASE_URL}/uploads/property-images/${filename}`;
}

// --- Normalize property (main + multiple photos) ---
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function normalizeProperty(item: any) {
  let photosArray: string[] = [];
  try {
    photosArray = item.photos ? JSON.parse(item.photos) : [];
  } catch (err) {
    console.error('Error parsing photos JSON:', err);
    photosArray = [];
  }

  return {
    ...item,
    photo: resolvePhoto(item.photo),
    photos: photosArray.map((f: string) => resolvePhoto(f)),
    video: resolveVideo(item.video),
  };
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function pickIdAndName(obj: any, idField: string, nameField: string) {
  if (!obj) return null;
  return {
    [idField]: obj[idField],
    [nameField]: obj[nameField],
  };
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
// In postpropertymaster.controller.ts

function transformProperty(item: any) {
  if (!item) return item;

  const normalized = normalizeProperty(item);

  // Transform amenities array properly
  let amenitiesArray = [];
  if (item.amenities && Array.isArray(item.amenities)) {
    amenitiesArray = item.amenities.map((amenity: any) => ({
      amenitiesId: amenity.amenitiesId,
      amenitiesName: amenity.amenitiesName,
    }));
  }

  return {
    // ...normalized,
    annualduespay: normalized.annualduespay,
    apartmentNameAreaName: normalized.apartmentNameAreaName,
    bookingamount: normalized.bookingamount,
    builduparea: normalized.builduparea,
    carpetarea: normalized.carpetarea,
    coverparking: normalized.coverparking,
    description: normalized.description,
    expectedrental: normalized.expectedrental,
    fkavailablestatusId: normalized.fkavailablestatusId,
    fksellerId: normalized.fksellerId,
    publish_Fag: normalized.publish_Fag,
    fkpublish_TypeId: normalized.fkpublish_TypeId,
    publish_StartDate: normalized.publish_StartDate,
    publish_EndDate: normalized.publish_EndDate,
    fkcityId: normalized.fkcityId,
    fkfloorId: normalized.fkfloorId,
    fkfurnishingtypeId: normalized.fkfurnishingtypeId,
    fktransactionId: normalized.fktransactionId,
    fkpossessionId: normalized.fkpossessionId,
    fkfacingId: normalized.fkfacingId,
    // Remove fkamenitiesId from the response
    // fkamenitiesId: normalized.fkamenitiesId,
    fklocalityId: normalized.fklocalityId,
    fkmainpropertytypeId: normalized.fkmainpropertytypeId,
    fkmaintnecemonthId: normalized.fkmaintnecemonthId,
    fkotherrooms: normalized.fkotherrooms,
    fkownershipId: normalized.fkownershipId,
    fkuserId: normalized.fkuserId,
    fkpostpropertytypeId: normalized.fkpostpropertytypeId,
    fkpropertytypeId: normalized.fkpropertytypeId,
    housenumber: normalized.housenumber,
    isActive: normalized.isActive,
    maintenance: normalized.maintenance,
    membershipcharge: normalized.membershipcharge,
    noofbalkanies: normalized.noofbalkanies,
    noofbathrooms: normalized.noofbathrooms,
    noofbedrooms: normalized.noofbedrooms,
    openparking: normalized.openparking,
    photo: normalized.photo,
    photos: normalized.photos,
    postpropertyId: normalized.postpropertyId,
    price: normalized.price,
    RERA_NO: normalized.RERA_NO,
    RERA_is_active: normalized.RERA_is_active,
    pricepersqft: normalized.pricepersqft,
    sublocality: normalized.sublocality,
    Property_Title: normalized.Property_Title,
    Property_Description: normalized.Property_Description,
    supperbuilduparea: normalized.supperbuilduparea,
    totalfloor: normalized.totalfloor,
    video: normalized.video,
    availableStatus: pickIdAndName(
      item.availableStatus,
      'availableStatusId',
      'availableStatusName',
    ),
    seller: pickIdAndName(item.seller, 'sellerId', 'sellerName'),
    publishType: pickIdAndName(item.publishType, 'publishTypeId', 'publishTypeName'),
    floor: pickIdAndName(item.floor, 'floorId', 'floorName'),
    furnishingType: pickIdAndName(
      item.furnishingType,
      'furnishingTypeId',
      'furnishingTypeName',
    ),
    possessionType: pickIdAndName(
      item.possessionType,
      'possessionId',
      'possessionName',
    ),
    transactionType: pickIdAndName(
      item.transactionType,
      'transactionId',
      'transactionName',
    ),
    mainPropertyType: pickIdAndName(
      item.mainPropertyType,
      'mainpropertytypeId',
      'mainprpoertyName',
    ),
    maintenanceMonth: pickIdAndName(
      item.maintenanceMonth,
      'maintenanceMonthId',
      'maintenanceMonthName',
    ),
    otherRoom: pickIdAndName(item.otherRoom, 'otherRoomId', 'otherRoomName'),
    ownership: pickIdAndName(item.ownership, 'ownershipId', 'ownershipName'),
    userType: pickIdAndName(item.userType, 'userTypeId', 'userTypeName'),
    postType: pickIdAndName(item.postType, 'postTypeId', 'posttypeName'),
    propertyType: pickIdAndName(
      item.propertyType,
      'propertyTypeId',
      'propertytypeName',
    ),
    facing: pickIdAndName(item.facing, 'facingId', 'facingName'),
    // Use the properly transformed amenities array
    amenities: amenitiesArray,
  };
}

// --- Relations list ---
const allRelations = [
  // {relation: 'city'},
  {relation: 'availableStatus'},
  {relation: 'seller'},
  {relation: 'publishType'},
  {relation: 'floor'},
  {relation: 'furnishingType'},
  {relation: 'transactionType'},
  {relation: 'possessionType'},
  {relation: 'mainPropertyType'},
  {relation: 'maintenanceMonth'},
  {relation: 'otherRoom'},
  {relation: 'ownership'},
  {relation: 'userType'},
  {relation: 'postType'},
  {relation: 'propertyType'},
  {relation: 'amenities'},
  {relation: 'facing'},

];

// --- Numeric Fields for robust parsing ---
const numericFields = [
  'price',
  'pricepersqft',
  'builduparea',
  'carpetarea',
  'supperbuilduparea',
  'annualduespay',
  'bookingamount',
  'coverparking',
  'openparking',
  'expectedrental',
  'maintenance',
  'membershipcharge',
  'totalfloor',
  'noofbedrooms',
  'noofbathrooms',
  'noofbalkanies',
  'fkavailablestatusId',
  'fksellerId',
  'fkpublish_TypeId',
  'fkfloorId',
  'fkfurnishingtypeId',
  'fkpossessionId',
  'fktransactionId',
  'fkmainpropertytypeId',
  'fkmaintnecemonthId',
  'fkotherrooms',
  'fkownershipId',
  'fkuserId',
  'fkpostpropertytypeId',
  'fkpropertytypeId',
  'publish_Fag',
  'fkfacingId',
  'isReraRegistered',
];

export class PostpropertymasterController {
  constructor(
    @repository(PostPropertyMasterRepository)
    public postPropertyMasterRepository: PostPropertyMasterRepository,
    @repository(RecommendedLaunchRepository)
    public recommendedLaunchRepository: RecommendedLaunchRepository,
    @repository(BestpropertyLaunchRepository)
    public bestpropertyLaunch: BestpropertyLaunchRepository,
    @repository(PostPropertyAmenitiesRepository)
    public propertyAmenitiesRepository: PostPropertyAmenitiesRepository,

    @repository(NewLaunchMasterRepository)
    public newLaunchRepository: NewLaunchMasterRepository,
  ) { }
  async saveImageFromPathOrUrl(imagePath: string): Promise<string> {
    const uploadDir = path.join(__dirname, '../../uploads/property-images');
    if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, {recursive: true});

    const fileName = Date.now() + '-' + path.basename(imagePath);

    if (imagePath.startsWith('http')) {
      // eslint-disable-next-line @typescript-eslint/no-shadow
      const response = await axios.get(imagePath, {responseType: 'arraybuffer'});
      fs.writeFileSync(path.join(uploadDir, fileName), response.data);
    } else if (fs.existsSync(imagePath)) {
      fs.copyFileSync(imagePath, path.join(uploadDir, fileName));
    } else {
      throw new Error(`Image not found: ${imagePath}`);
    }

    return fileName;
  }

  private getMulterUpload() {
    const storage = multer.diskStorage({
      destination: (req, file, cb) => {
        const dir = path.join(__dirname, '../../uploads/property-images');
        if (!fs.existsSync(dir)) fs.mkdirSync(dir, {recursive: true});
        cb(null, dir);
      },
      filename: (req, file, cb) => {
        cb(null, Date.now() + '-' + file.originalname);
      },
    });
    return multer({storage});
  }

  // Create property with multiple photo upload
  // In postpropertymaster.controller.ts

  @post('/post-property-masters/uploads')
  @response(200, {
    description: 'PostPropertyMaster model instance',
  })
  async createWithPhotos(
    @inject(RestBindings.Http.REQUEST) request: Request,
  ): Promise<PostPropertyMaster> {
    const upload = this.getMulterUpload().fields([
      {name: 'photo', maxCount: 15},
      {name: 'video', maxCount: 1},
    ]);

    return new Promise((resolve, reject) => {
      upload(request, {} as any, async err => {
        if (err) return reject(err);

        try {
          const files = request.files as any;
          const imageFiles = files?.photo || [];
          const videoFile = files?.video?.[0] || null;
          const photos = imageFiles.map((f: any) => f.filename);
          const amenitiesData = request.body.amenities;

          const bodyData: any = {};
          for (const key in request.body) {
            let value = request.body[key];

            if (value === undefined || value === 'undefined') continue;
            if (key === 'amenities') continue;
            if (value === 'null' || value === '' || value === null) {
              value = null;
            }

            if (numericFields.includes(key)) {
              if (value === null) {
                bodyData[key] = null;
              } else {
                const parsed = Number(value);
                if (!isFinite(parsed)) {
                  bodyData[key] = null;
                } else {
                  bodyData[key] = parsed;
                }
              }
            } else {
              bodyData[key] = value;
            }
          }

          if (bodyData.isReraRegistered !== undefined) {
            bodyData.RERA_is_active = bodyData.isReraRegistered;
            delete bodyData.isReraRegistered;
          }

          // Remove fkamenitiesId from bodyData if it exists
          if (bodyData.fkamenitiesId !== undefined) {
            delete bodyData.fkamenitiesId;
          }

          // FINAL SAFETY SWEEP: Ensure no numeric NaN remains in the final object
          Object.keys(bodyData).forEach(key => {
            const value = bodyData[key];
            if (typeof value === 'number' && !isFinite(value)) {
              bodyData[key] = null;
            }
          });

          const saved = await this.postPropertyMasterRepository.create({
            ...bodyData,
            createdDate: new Date().toISOString(),
            photos: JSON.stringify(photos),
            photo: photos[0] || null,
            video: videoFile?.filename || null,
          });

          if (amenitiesData) {
            try {
              let amenitiesIds: number[] = [];

              if (typeof amenitiesData === 'string') {
                amenitiesIds = JSON.parse(amenitiesData);
              } else if (Array.isArray(amenitiesData)) {
                amenitiesIds = amenitiesData
                  .map(id => Number(id))
                  .filter(id => !isNaN(id) && id > 0);
              }

              // console.log('📋 Amenities to save:', amenitiesIds);
              // console.log('🏠 Property ID:', saved.postpropertyId);

              if (amenitiesIds.length > 0 && saved.postpropertyId) {
                for (const amenityId of amenitiesIds) {
                  const amenityRecord = {
                    postpropertyId: saved.postpropertyId,
                    amenitiesId: amenityId,
                    createdDate: new Date().toISOString(),
                    lastChanged: new Date().toISOString(), // ✅ ADD THIS
                  };

                  // console.log('💾 Saving amenity record:', amenityRecord);

                  await this.propertyAmenitiesRepository.create(amenityRecord);

                  // console.log('✅ Amenity saved successfully');
                }
              } else {
                console.log('⚠️ No amenities to save or property ID missing');
              }
            } catch (e) {
              console.error('❌ Error saving amenities:', e);
              // Don't throw - just log, so property still saves
            }
          }

          resolve(normalizeProperty(saved));
        } catch (e) {
          reject(e);
        }
      });
    });
  }

  @post('/post-property-masters')
  @response(200, {
    description: 'PostPropertyMaster model instance',
    content: {
      'application/json': {schema: getModelSchemaRef(PostPropertyMaster)},
    },
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(PostPropertyMaster, {
            title: 'NewPostPropertyMaster',
            exclude: ['postpropertyId'],
          }),
        },
      },
    })
    postPropertyMaster: Omit<PostPropertyMaster, 'postpropertyId'>,
  ): Promise<PostPropertyMaster> {
    const property =
      await this.postPropertyMasterRepository.create(postPropertyMaster);
    return normalizeProperty(property);
  }

  @get('/post-property-masters/count')
  @response(200, {
    description: 'PostPropertyMaster model count',
    content: {'application/json': {schema: CountSchema}},
  })
  async count(
    @param.where(PostPropertyMaster) where?: Where<PostPropertyMaster>,
  ): Promise<Count> {
    return this.postPropertyMasterRepository.count(where);
  }

  // In postpropertymaster.controller.ts

  @get('/post-property-masters')
  @response(200, {
    description: 'Array of PostPropertyMaster model instances',
  })
  async find(
    @param.filter(PostPropertyMaster) filter?: Filter<PostPropertyMaster>,
  ): Promise<any[]> {
    const data = await this.postPropertyMasterRepository.find({
      ...filter,
      include: [
        ...allRelations,
        {
          relation: 'amenities',
          scope: {
            fields: {
              amenitiesId: true,
              amenitiesName: true,
            }
          }
        }
      ],
      order: ['created_date DESC'],
    });
    return data.map(transformProperty);
  }

  @patch('/post-property-masters')
  @response(200, {
    description: 'PostPropertyMaster PATCH success count',
    content: {'application/json': {schema: CountSchema}},
  })
  async updateAll(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(PostPropertyMaster, {partial: true}),
        },
      },
    })
    postPropertyMaster: PostPropertyMaster,
    @param.where(PostPropertyMaster) where?: Where<PostPropertyMaster>,
  ): Promise<Count> {
    return this.postPropertyMasterRepository.updateAll(
      postPropertyMaster,
      where,
    );
  }

  // In postpropertymaster.controller.ts

  @get('/post-property-masters/{id}')
  @response(200, {
    description: 'PostPropertyMaster model instance',
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(PostPropertyMaster, {exclude: 'where'})
    filter?: FilterExcludingWhere<PostPropertyMaster>,
  ): Promise<any> {
    const item = await this.postPropertyMasterRepository.findById(id, {
      ...filter,
      include: [
        ...allRelations,
        {
          relation: 'amenities',
          scope: {
            fields: {
              amenitiesId: true,
              amenitiesName: true,
            }
          }
        }
      ],
      order: ['created_date DESC'],
    });
    return normalizeProperty(item);
  }

  @get('/post-property-masters/recommended-all')
  async getRecommended() {
    const data = await this.postPropertyMasterRepository.find({
      where: {and: [{fkpublish_TypeId: 1}, {publish_Fag: 2}]},
      order: ['created_date DESC'],
      include: allRelations,
    });
    return data.map(transformProperty);
  }

  @get('/post-property-masters/recommended')
  async getRecommendedFromRecommendedLaunch() {
    const recommended = await this.recommendedLaunchRepository.find();
    const propertyIds = recommended.map(item => item.fkpostpropertyId);

    if (propertyIds.length === 0) return [];

    const properties = await this.postPropertyMasterRepository.find({
      where: {postpropertyId: {inq: propertyIds}},
      include: allRelations,
    });

    const sortedProperties = propertyIds
      .map(id => properties.find(p => p.postpropertyId === id))
      .filter(p => p)
      .slice(0, 4); // ⚡ Get 4 properties

    return sortedProperties.map(transformProperty);
  }

  @get('/post-property-masters/best-value-all')
  async getBestValue() {
    const data = await this.postPropertyMasterRepository.find({
      where: {and: [{fkpublish_TypeId: 2}, {publish_Fag: 2}]},
      order: ['created_date DESC'],
      include: allRelations,
    });
    return data.map(transformProperty);
  }

  @get('/post-property-masters/best-value')
  async getBestpropertyFromBestLaunch() {
    const best = await this.bestpropertyLaunch.find();
    const propertyIds = best.map(item => item.fkpostpropertyId);
    if (propertyIds.length === 0) return [];
    const properties = await this.postPropertyMasterRepository.find({
      where: {postpropertyId: {inq: propertyIds}},
      include: allRelations,
    });
    return properties.map(transformProperty);
  }

  @get('/post-property-masters/new-launch')
  async getNewLaunchFromLaunchTable() {
    const newLaunch = await this.newLaunchRepository.find();

    const propertyIds = newLaunch.map(item => item.fkpostpropertyId);

    if (propertyIds.length === 0) return [];

    const properties = await this.postPropertyMasterRepository.find({
      where: {
        postpropertyId: {inq: propertyIds},
        publish_Fag: 2,
        isActive: 1,
      },
      include: allRelations,
    });

    // Optional: sequence maintain करायचा असेल तर
    const sortedProperties = propertyIds
      .map(id => properties.find(p => p.postpropertyId === id))
      .filter(p => p)
      .slice(0, 3); // ⚡ limit 4

    return sortedProperties.map(transformProperty);
  }


  @get('/post-property-masters/new-launch-all')
  async getAllNewLaunch() {
    const data = await this.postPropertyMasterRepository.find({
      where: {and: [{fkpublish_TypeId: 3}, {publish_Fag: 2}]},
      order: ['created_date DESC'],
      include: allRelations,
    });
    return data.map(transformProperty);
  }

  // In postpropertymaster.controller.ts

  @patch('/post-property-masters/{id}')
  @response(200, {
    description: 'PostPropertyMaster PATCH success',
  })
  async updateWithPhotos(
    @param.path.number('id') id: number,
    @inject(RestBindings.Http.REQUEST) request: Request,
  ): Promise<void> {
    const upload = this.getMulterUpload().fields([
      {name: 'photo', maxCount: 15},
      {name: 'video', maxCount: 1},
    ]);

    return new Promise((resolve, reject) => {
      upload(request, {} as any, async err => {
        if (err) return reject(err);

        try {
          const files = request.files as any;
          const imageFiles = files?.photo || [];
          const videoFile = files?.video?.[0] || null;

          const updateData: any = {};
          const amenitiesData = request.body.amenities;

          // Parse body fields
          for (const key in request.body) {
            let value = request.body[key];

            if (value === undefined || value === 'undefined') continue;

            if (value === 'null' || value === '') {
              value = null;
            }

            if (key === 'amenities' || key === 'existingPhotos') continue;

            if (value === 'true' || value === 'false') {
              value = value === 'true';
            }

            if (numericFields.includes(key)) {
              if (value === null) {
                updateData[key] = null;
              } else {
                const parsed = Number(value);
                if (!isFinite(parsed)) {
                  updateData[key] = null;
                } else {
                  updateData[key] = parsed;
                }
              }
            } else {
              updateData[key] = value;
            }
          }

          if (updateData.isReraRegistered !== undefined) {
            updateData.RERA_is_active = updateData.isReraRegistered;
            delete updateData.isReraRegistered;
          }

          // Remove fkamenitiesId from updateData if it exists
          if (updateData.fkamenitiesId !== undefined) {
            delete updateData.fkamenitiesId;
          }

          // Handle Photos - Merge existing + new
          let allPhotos: string[] = [];

          if (request.body.existingPhotos) {
            try {
              const existingPhotoUrls = JSON.parse(request.body.existingPhotos);
              allPhotos = existingPhotoUrls.map((url: string) => {
                const urlParts = url.split('/');
                return urlParts[urlParts.length - 1];
              });
            } catch (e) {
              console.error('Error parsing existing photos:', e);
            }
          }

          if (imageFiles.length > 0) {
            const newPhotos = imageFiles.map((f: any) => f.filename);
            allPhotos = [...allPhotos, ...newPhotos];
          }

          if (allPhotos.length > 0) {
            updateData.photos = JSON.stringify(allPhotos);
            updateData.photo = allPhotos[0];
          }

          if (videoFile) {
            updateData.video = videoFile.filename;
          }

          await this.postPropertyMasterRepository.updateById(id, updateData);

          // Handle amenities relationship update
          if (amenitiesData) {
            try {
              let amenitiesIds: number[] = [];

              if (typeof amenitiesData === 'string') {
                amenitiesIds = JSON.parse(amenitiesData);
              } else if (Array.isArray(amenitiesData)) {
                amenitiesIds = amenitiesData
                  .map(aid => Number(aid))
                  .filter(aid => !isNaN(aid) && aid > 0);
              }

              // console.log('📋 Updating amenities with IDs:', amenitiesIds);

              // Delete old amenities relationships
              await this.propertyAmenitiesRepository.deleteAll({
                postpropertyId: id,
              });

              // console.log('🗑️ Old amenities deleted');

              // Create new amenities relationships
              if (amenitiesIds && amenitiesIds.length > 0) {
                for (const amenityId of amenitiesIds) {
                  const amenityRecord = {
                    postpropertyId: id,
                    amenitiesId: amenityId,
                    createdDate: new Date().toISOString(),
                    lastChanged: new Date().toISOString(), // ✅ ADD THIS
                  };

                  // console.log('💾 Creating amenity record:', amenityRecord);

                  await this.propertyAmenitiesRepository.create(amenityRecord);
                }

                // console.log('✅ Amenities updated successfully');
              }
            } catch (e) {
              console.error('❌ Error updating amenities:', e);
              // Don't throw - just log
            }
          }

          resolve();
        } catch (e) {
          reject(e);
        }
      });
    });
  }

  @put('/post-property-masters/{id}')
  @response(204, {
    description: 'PostPropertyMaster PUT success',
  })
  async replaceById(
    @param.path.number('id') id: number,
    @requestBody() postPropertyMaster: PostPropertyMaster,
  ): Promise<void> {
    await this.postPropertyMasterRepository.replaceById(id, postPropertyMaster);
  }

  @del('/post-property-masters/{id}')
  @response(204, {
    description: 'PostPropertyMaster DELETE success',
  })
  async deleteById(@param.path.number('id') id: number): Promise<void> {
    await this.postPropertyMasterRepository.deleteById(id);
  }

  // --- New Published/Active Query Methods ---

  @get('/post-property-masters/published-active')
  @response(200, {
    description:
      'Published and active PostPropertyMaster model instances using simple query params',
  })
  async getPublishedActive(
    @param.query.string('fkcityId') fkcityId?: string,
    @param.query.number('fkpostType') fkpostType?: number,
    @param.query.string('fklocalityId') fklocalityId?: string,
    @param.query.number('fkpropertytypeId') fkpropertytypeId?: number,
    @param.query.number('fkfurnishingtypeId') fkfurnishingtypeId?: number,
    //
    @param.query.number('fktransactionId') fktransactionId?: number,
    @param.query.number('fkpossessionId') fkpossessionId?: number,
    @param.query.number('fkfacingId') fkfacingId?: number,
    // @param.query.number('fkamenitiesId') fkamenitiesId?: number,
    @param.query.number('fkmainpropertytypeId') fkmainpropertytypeId?: number,
    @param.query.number('fkuserId') fkuserId?: number,
    @param.query.number('RERA_is_active') RERA_is_active?: number,
    @param.query.string('Property_Title') Property_Title?: string,
    // @param.query.number('fkamenitiesId') fkamenitiesId?: number,
  ): Promise<any[]> {
    const baseWhere: AnyObject[] = [{isActive: 1}, {publish_Fag: 2}];

    if (fkcityId) {
      baseWhere.push({fkcityId});
    }
    // fkpostType maps to fkpostpropertytypeId in the model
    if (fkpostType !== undefined) {
      baseWhere.push({fkpostpropertytypeId: fkpostType});
    }
    if (fklocalityId) {
      baseWhere.push({fklocalityId});
    }
    if (fkpropertytypeId !== undefined) {
      baseWhere.push({fkpropertytypeId});
    }
    if (fkfurnishingtypeId !== undefined) {
      baseWhere.push({fkfurnishingtypeId});
    }
    //
    if (fktransactionId !== undefined) {
      baseWhere.push({fktransactionId});
    }
    if (fkpossessionId !== undefined) {
      baseWhere.push({fkpossessionId});
    }
    if (fkfacingId !== undefined) {
      baseWhere.push({fkfacingId});
    }
    // ⚠️ NOTE: fkamenitiesId is generally handled via a relation,
    // but if it's a direct column in PostPropertyMaster, this is okay.
    // if (fkamenitiesId !== undefined) {
    //  baseWhere.push({fkamenitiesId});
    // }
    if (fkmainpropertytypeId !== undefined) {
      baseWhere.push({fkmainpropertytypeId});
    }
    if (fkuserId !== undefined) {
      baseWhere.push({fkuserId});
    }
    // fkpostpropertytypeId is already handled by fkpostType

    if (RERA_is_active !== undefined) {
      baseWhere.push({RERA_is_active});
    }
    if (Property_Title) {
      // 💡 Consideration: Use a LIKE query for partial matching if needed
      // baseWhere.push({ Property_Title: { like: `%${Property_Title}%` } });
      baseWhere.push({Property_Title});
    }

    const finalFilter = {
      where: {and: baseWhere},
      order: ['created_date DESC'],
      include: allRelations,
    };

    const data = await this.postPropertyMasterRepository.find(finalFilter);
    return data.map(transformProperty);
  }

  @get('/post-property-masters/published-active/{id}')
  @response(200, {
    description:
      'Published and active PostPropertyMaster model instance by ID',
  })
  async getPublishedActiveById(
    @param.path.number('id') id: number,
    @param.filter(PostPropertyMaster, {exclude: 'where'})
    filter?: FilterExcludingWhere<PostPropertyMaster>,
  ): Promise<any> {
    const item = await this.postPropertyMasterRepository.findOne({
      where: {
        and: [
          {postpropertyId: id}, // Match by the provided ID
          {isActive: 1}, // Must be active
          {publish_Fag: 2}, // Must be published
        ],
      },
      // Use the filter to include relations if specified in the query, but we override 'where'
      ...filter,
      include: allRelations, // Include all related models
    });

    if (!item) {
      // Throw a standard 404 error if the item is not found or not active/ published
      throw new HttpErrors.NotFound(
        `PostPropertyMaster with id ${id} (active and published) not found`,
      );
    }

    // Transform the data to normalize photo URLs and return only selected fields
    return transformProperty(item);
  }
}
