import { Types, PipelineStage } from 'mongoose';
import IndividualProperties from '../individualProperties.model';
import { Lead } from '@/modules/lead/lead.model';
import { getObjectId } from '@/shared/utils/commonHelper';

export async function findProspectLeadsForProperty({
  propertyId,
  companyId,
}: {
  propertyId: string;
  companyId: Types.ObjectId | string;
}) {
  const property = await IndividualProperties.findById(propertyId)
    .select(
      'state city locality price monthlyRent listingType propertyType subCategory category',
    )
    .lean();

  if (!property) throw new Error('Property not found');

  const lt = String(property.listingType ?? '').toLowerCase();

  // Handle desiredType and interestType mapping
  let desiredType: 'buy' | 'sell' | 'rent' | 'lease' | undefined;
  if (lt === 'sell' || lt === 'sale') desiredType = 'sell';
  else if (lt === 'buy') desiredType = 'buy';
  else if (lt === 'rent') desiredType = 'rent';
  else if (lt === 'lease') desiredType = 'lease';

  // Setup price logic
  let propertyPrice: number | null = null;
  let leadPriceFields: string[] = [];
  if (desiredType === 'sell') {
    propertyPrice = typeof property.price === 'number' ? property.price : null;
    leadPriceFields = ['budget', 'askingPrice'];
  } else if (desiredType === 'rent' || desiredType === 'lease') {
    propertyPrice =
      typeof property.monthlyRent === 'number' ? property.monthlyRent : null;
    leadPriceFields = ['rentAmount', 'leaseAmount'];
  }

  if (propertyPrice == null) return { total: 0, leads: [] };

  // Location OR clause
  // const locationOr: any[] = [];
  // if (property.locality)

  // if (property.city) {
  //   // locationOr.push({ propertyLocality: property.locality });
  //   // locationOr.push({ propertyCity: property.city });

  //   const cityId = getObjectId(property.city); // keep types consistent (ObjectId)
  //   locationOr.push({ propertyCity: cityId });
  //   locationOr.push({ preferredCity: cityId });
  // }

  const propSubcatIds = [];
  if (Array.isArray(property.propertyType) && property.propertyType.length)
    propSubcatIds.push(
      ...property.propertyType.map((id) => getObjectId(id)).filter(Boolean),
    );
  if (property.subcategory)
    propSubcatIds.push(getObjectId(property.subcategory));

  // priceOr clause for lead fields
  const priceOr = leadPriceFields.map((field) => ({
    [field]: { $gte: propertyPrice },
  }));

  // desired lead types for sell/listingType
  let interestTypeCriteria = undefined;
  if (desiredType === 'sell') interestTypeCriteria = { $in: ['buy', 'sell'] };
  else if (desiredType) interestTypeCriteria = desiredType;

  const baseMatch = {
    company: companyId && getObjectId(companyId),
    ...(property.category && {
      propertyCategory: property.category,
    }),
    ...(propSubcatIds.length
      ? {
          $or: [
            { subCategoryId: { $in: propSubcatIds } },
            { propertyType: { $in: propSubcatIds } },
          ],
        }
      : {}),
    ...(interestTypeCriteria && { interestType: interestTypeCriteria }),
    $and: [
      {
        $or: priceOr,
      },
    ],
  };

  const pipeline: PipelineStage[] = [
    { $match: baseMatch },
    {
      $facet: {
        totalCount: [{ $count: 'count' }],
        leads: [
          // Contact
          {
            $lookup: {
              from: 'contacts',
              localField: 'contact',
              foreignField: '_id',
              as: 'contact',
            },
          },
          { $unwind: { path: '$contact', preserveNullAndEmptyArrays: true } },

          // Score normalize
          {
            $addFields: {
              _score: {
                $convert: {
                  input: { $ifNull: ['$leadScore', '$score'] },
                  to: 'double',
                  onError: 0,
                  onNull: 0,
                },
              },
            },
          },

          // ---------- SIMPLE LOOKUPS ----------
          {
            $lookup: {
              from: 'projects',
              localField: 'project',
              foreignField: '_id',
              as: '_project',
            },
          },
          {
            $lookup: {
              from: 'subcategories',
              localField: 'propertyType',
              foreignField: '_id',
              as: '_subcatsFromArray',
            },
          },
          {
            $lookup: {
              from: 'subcategories',
              localField: 'subCategoryId',
              foreignField: '_id',
              as: '_subcatsFromSingle',
            },
          },
          {
            $lookup: {
              from: 'units',
              localField: 'unit',
              foreignField: '_id',
              as: '_unit',
            },
          },
          {
            $lookup: {
              from: 'cities',
              localField: 'propertyCity',
              foreignField: '_id',
              as: '_city',
            },
          },

          // ---------- FINAL PROJECTION (null-safe) ----------
          {
            $project: {
              id: '$_id',
              _id: 0,

              // Name from contact (kept as before)
              name: {
                $trim: {
                  input: {
                    $concat: [
                      { $ifNull: ['$contact.firstName', ''] },
                      ' ',
                      { $ifNull: ['$contact.lastName', ''] },
                    ],
                  },
                },
              },

              email: '$contact.email',

              // First phone of contact (falls back to lead.phone)
              phone: {
                $ifNull: [
                  {
                    $let: {
                      vars: {
                        p: {
                          $cond: [
                            { $isArray: '$contact.phone' },
                            { $arrayElemAt: ['$contact.phone', 0] },
                            null,
                          ],
                        },
                      },
                      in: {
                        $cond: [
                          { $ifNull: ['$$p', false] },
                          {
                            $trim: {
                              input: {
                                $concat: [
                                  '+',
                                  {
                                    $toString: {
                                      $ifNull: ['$$p.countryCode', ''],
                                    },
                                  },
                                  ' ',
                                  {
                                    $toString: { $ifNull: ['$$p.number', ''] },
                                  },
                                ],
                              },
                            },
                          },
                          null,
                        ],
                      },
                    },
                  },
                  '$phone',
                ],
              },

              // Budget mapped by interestType and converted to number
              budget: {
                $convert: {
                  input: {
                    $switch: {
                      branches: [
                        {
                          case: { $eq: ['$interestType', 'sell'] },
                          then: '$askingPrice',
                        },
                        {
                          case: { $eq: ['$interestType', 'buy'] },
                          then: '$budget',
                        },
                        {
                          case: { $eq: ['$interestType', 'lease'] },
                          then: '$leaseAmount',
                        },
                        {
                          case: { $eq: ['$interestType', 'rent'] },
                          then: '$monthlyRent',
                        },
                      ],
                      default: '$budget',
                    },
                  },
                  to: 'double',
                  onError: null,
                  onNull: null,
                },
              },

              // Status from score
              status: {
                $switch: {
                  branches: [
                    { case: { $lte: ['$_score', 40] }, then: 'Cold' },
                    {
                      case: {
                        $and: [
                          { $gt: ['$_score', 40] },
                          { $lte: ['$_score', 70] },
                        ],
                      },
                      then: 'Warm',
                    },
                  ],
                  default: 'Hot',
                },
              },

              // --------- SINGLE NAME FIELDS (return null when missing) ---------

              // Project name (try project.projectName, fallback to project.name, else null)
              projectName: {
                $ifNull: [
                  { $arrayElemAt: ['$_project.projectName', 0] },
                  {
                    $ifNull: [{ $arrayElemAt: ['$_project.name', 0] }, null],
                  },
                ],
              },

              // Subcategory names (array) -> return null if empty
              subcategoryNameList: {
                $let: {
                  vars: {
                    names: {
                      $setUnion: [
                        {
                          $map: {
                            input: '$_subcatsFromArray',
                            as: 's',
                            in: '$$s.name',
                          },
                        },
                        {
                          $map: {
                            input: '$_subcatsFromSingle',
                            as: 's',
                            in: '$$s.name',
                          },
                        },
                      ],
                    },
                  },
                  in: {
                    $cond: [
                      { $gt: [{ $size: '$$names' }, 0] },
                      '$$names',
                      null,
                    ],
                  },
                },
              },

              // Subcategory names (joined string) -> return null if none
              subcategoryNames: {
                $let: {
                  vars: {
                    names: {
                      $setUnion: [
                        {
                          $map: {
                            input: '$_subcatsFromArray',
                            as: 's',
                            in: '$$s.name',
                          },
                        },
                        {
                          $map: {
                            input: '$_subcatsFromSingle',
                            as: 's',
                            in: '$$s.name',
                          },
                        },
                      ],
                    },
                  },
                  in: {
                    $cond: [
                      { $gt: [{ $size: '$$names' }, 0] },
                      {
                        $reduce: {
                          input: '$$names',
                          initialValue: '',
                          in: {
                            $cond: [
                              { $eq: ['$$value', ''] },
                              '$$this',
                              { $concat: ['$$value', ', ', '$$this'] },
                            ],
                          },
                        },
                      },
                      null,
                    ],
                  },
                },
              },

              // Unit & City names (null if missing)
              unitName: {
                $ifNull: [{ $arrayElemAt: ['$_unit.name', 0] }, null],
              },
              cityName: {
                $ifNull: [{ $arrayElemAt: ['$_city.name', 0] }, null],
              },

              updatedAt: 1,
            },
          },
        ],
      },
    },
  ];

  const result = await Lead.aggregate(pipeline);
  const total = result?.[0]?.totalCount?.[0]?.count ?? 0;
  const leads = result?.[0]?.leads ?? [];

  return { total, leads };
}
