import { type PropertyType, type Direction, type Furnishing, type PropertyCondition } from '@prisma/client';
import { AggregateRoot } from '@modules/shared';
import { type Address } from '../value-objects/address.vo';
import { type GeoPoint } from '../value-objects/geo-point.vo';

export interface PropertyProps {
  propertyType: PropertyType;
  title: string;
  description: string;
  address: Address;
  location: GeoPoint;
  areaM2: number;
  usableAreaM2: number | null;
  bedrooms: number | null;
  bathrooms: number | null;
  floors: number | null;
  floor: number | null;
  totalFloors: number | null;
  direction: Direction | null;
  yearBuilt: number | null;
  legalStatus: string | null;
  amenities: unknown;
  nearbyPOIs: unknown;
  metroDistanceM: number | null;
  projectName: string | null;
  // --- Rich fields (Phase B) -----------------------------
  furnishing?: Furnishing | null;
  propertyCondition?: PropertyCondition | null;
  balconyDirection?: Direction | null;
  maintenanceFeeVND?: bigint | null;
  parkingSlots?: number | null;
  viewType?: string[];
  petFriendly?: boolean | null;
  suitableFor?: string[];
  whyThisLocation?: string | null;
}

export class PropertyEntity extends AggregateRoot<string> {
  private _propertyType: PropertyType;
  private _title: string;
  private _description: string;
  private _address: Address;
  private _location: GeoPoint;
  private _areaM2: number;
  private _usableAreaM2: number | null;
  private _bedrooms: number | null;
  private _bathrooms: number | null;
  private _floors: number | null;
  private _floor: number | null;
  private _totalFloors: number | null;
  private _direction: Direction | null;
  private _yearBuilt: number | null;
  private _legalStatus: string | null;
  private _amenities: unknown;
  private _nearbyPOIs: unknown;
  private _metroDistanceM: number | null;
  private _projectName: string | null;
  private _furnishing: Furnishing | null;
  private _propertyCondition: PropertyCondition | null;
  private _balconyDirection: Direction | null;
  private _maintenanceFeeVND: bigint | null;
  private _parkingSlots: number | null;
  private _viewType: string[];
  private _petFriendly: boolean | null;
  private _suitableFor: string[];
  private _whyThisLocation: string | null;

  constructor(id: string, props: PropertyProps, createdAt?: Date, updatedAt?: Date) {
    super(id, createdAt, updatedAt);
    this._propertyType = props.propertyType;
    this._title = props.title;
    this._description = props.description;
    this._address = props.address;
    this._location = props.location;
    this._areaM2 = props.areaM2;
    this._usableAreaM2 = props.usableAreaM2;
    this._bedrooms = props.bedrooms;
    this._bathrooms = props.bathrooms;
    this._floors = props.floors;
    this._floor = props.floor;
    this._totalFloors = props.totalFloors;
    this._direction = props.direction;
    this._yearBuilt = props.yearBuilt;
    this._legalStatus = props.legalStatus;
    this._amenities = props.amenities;
    this._nearbyPOIs = props.nearbyPOIs;
    this._metroDistanceM = props.metroDistanceM;
    this._projectName = props.projectName;
    this._furnishing = props.furnishing ?? null;
    this._propertyCondition = props.propertyCondition ?? null;
    this._balconyDirection = props.balconyDirection ?? null;
    this._maintenanceFeeVND = props.maintenanceFeeVND ?? null;
    this._parkingSlots = props.parkingSlots ?? null;
    this._viewType = props.viewType ?? [];
    this._petFriendly = props.petFriendly ?? null;
    this._suitableFor = props.suitableFor ?? [];
    this._whyThisLocation = props.whyThisLocation ?? null;
  }

  get propertyType(): PropertyType { return this._propertyType; }
  get title(): string { return this._title; }
  get description(): string { return this._description; }
  get address(): Address { return this._address; }
  get location(): GeoPoint { return this._location; }
  get areaM2(): number { return this._areaM2; }
  get usableAreaM2(): number | null { return this._usableAreaM2; }
  get bedrooms(): number | null { return this._bedrooms; }
  get bathrooms(): number | null { return this._bathrooms; }
  get floors(): number | null { return this._floors; }
  get floor(): number | null { return this._floor; }
  get totalFloors(): number | null { return this._totalFloors; }
  get direction(): Direction | null { return this._direction; }
  get yearBuilt(): number | null { return this._yearBuilt; }
  get legalStatus(): string | null { return this._legalStatus; }
  get amenities(): unknown { return this._amenities; }
  get nearbyPOIs(): unknown { return this._nearbyPOIs; }
  get metroDistanceM(): number | null { return this._metroDistanceM; }
  get projectName(): string | null { return this._projectName; }
  get furnishing(): Furnishing | null { return this._furnishing; }
  get propertyCondition(): PropertyCondition | null { return this._propertyCondition; }
  get balconyDirection(): Direction | null { return this._balconyDirection; }
  get maintenanceFeeVND(): bigint | null { return this._maintenanceFeeVND; }
  get parkingSlots(): number | null { return this._parkingSlots; }
  get viewType(): string[] { return this._viewType; }
  get petFriendly(): boolean | null { return this._petFriendly; }
  get suitableFor(): string[] { return this._suitableFor; }
  get whyThisLocation(): string | null { return this._whyThisLocation; }

  static createNew(id: string, props: PropertyProps): PropertyEntity {
    return new PropertyEntity(id, props);
  }

  /**
   * Updates mutable property content fields.
   * Returns list of changed field names.
   */
  updateContent(fields: {
    title?: string;
    description?: string;
    amenities?: unknown;
    furnishing?: Furnishing | null;
    propertyCondition?: PropertyCondition | null;
    balconyDirection?: Direction | null;
    maintenanceFeeVND?: bigint | null;
    parkingSlots?: number | null;
    viewType?: string[];
    petFriendly?: boolean | null;
    suitableFor?: string[];
    whyThisLocation?: string | null;
  }): string[] {
    const updatedFields: string[] = [];

    if (fields.title !== undefined) {
      this._title = fields.title;
      updatedFields.push('title');
    }

    if (fields.description !== undefined) {
      this._description = fields.description;
      updatedFields.push('description');
    }

    if (fields.amenities !== undefined) {
      this._amenities = fields.amenities;
      updatedFields.push('amenities');
    }

    if (fields.furnishing !== undefined) {
      this._furnishing = fields.furnishing;
      updatedFields.push('furnishing');
    }
    if (fields.propertyCondition !== undefined) {
      this._propertyCondition = fields.propertyCondition;
      updatedFields.push('propertyCondition');
    }
    if (fields.balconyDirection !== undefined) {
      this._balconyDirection = fields.balconyDirection;
      updatedFields.push('balconyDirection');
    }
    if (fields.maintenanceFeeVND !== undefined) {
      this._maintenanceFeeVND = fields.maintenanceFeeVND;
      updatedFields.push('maintenanceFeeVND');
    }
    if (fields.parkingSlots !== undefined) {
      this._parkingSlots = fields.parkingSlots;
      updatedFields.push('parkingSlots');
    }
    if (fields.viewType !== undefined) {
      this._viewType = fields.viewType;
      updatedFields.push('viewType');
    }
    if (fields.petFriendly !== undefined) {
      this._petFriendly = fields.petFriendly;
      updatedFields.push('petFriendly');
    }
    if (fields.suitableFor !== undefined) {
      this._suitableFor = fields.suitableFor;
      updatedFields.push('suitableFor');
    }
    if (fields.whyThisLocation !== undefined) {
      this._whyThisLocation = fields.whyThisLocation;
      updatedFields.push('whyThisLocation');
    }

    if (updatedFields.length > 0) {
      this.updatedAt = new Date();
    }

    return updatedFields;
  }
}
