import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
import { BaseAccessory } from './base.accessory';
import { TSVESyncPlatform } from '../platform';
import { DeviceCapabilities, VeSyncAirPurifier } from '../types/device.types';

// Extended interface to include device-specific methods and properties
interface ExtendedVeSyncAirPurifier extends VeSyncAirPurifier {
  deviceType: string;
  // Override setMode from base interface to make it more specific
  setMode(mode: string): Promise<boolean>;
  // Add additional methods
  autoMode?(): Promise<boolean>;
  manualMode?(): Promise<boolean>;
  sleepMode?(): Promise<boolean>;
  turboMode?(): Promise<boolean>;
  petMode?(): Promise<boolean>;
  setDisplay?(on: boolean): Promise<boolean>;
  turnOnDisplay?(): Promise<boolean>;
  turnOffDisplay?(): Promise<boolean>;
  setChildLock?(enabled: boolean): Promise<boolean>;
  setOscillation?(enabled: boolean): Promise<boolean>;
  hasFeature?(feature: string): boolean;
  isFeatureSupportedInCurrentMode?(feature: string): boolean;
  getMaxFanSpeed?(): number;
  getSupportedModes?(): ReadonlyArray<string>;
  getSupportedAutoPreferences?(): ReadonlyArray<string>;
  // Filter life property from VeSyncFan base class (inherited from VeSyncAirPurifier)
  // filterLife: number; // Already defined in base interface
  details?: {
    filter_life?: number | { percent: number };
    child_lock?: boolean;
    air_quality_value?: number;
    air_quality?: string | number;
    screen_status?: 'on' | 'off';
    pm25?: number;
    pm10?: number;
    pm1?: number;
    mode?: string;
  };
}

export class AirPurifierAccessory extends BaseAccessory {
  private readonly capabilities: DeviceCapabilities;
  protected readonly device: VeSyncAirPurifier;
  private isAirBypassDevice: boolean;
  private isAirBaseV2Device: boolean;
  private isAir131Device: boolean;
  private lastSetSpeed: number = 0; // Track the last speed we set
  private lastSetPercentage: number = 0; // Track the last percentage we set
  private skipNextUpdate: boolean = false; // Flag to skip the next update

  constructor(
    platform: TSVESyncPlatform,
    accessory: PlatformAccessory,
    device: VeSyncAirPurifier
  ) {
    super(platform, accessory, device);
    this.device = device;
    this.capabilities = this.getDeviceCapabilities();
    
    // Detect device class based on model number patterns
    const extendedDevice = this.device as ExtendedVeSyncAirPurifier;
    const deviceType = extendedDevice.deviceType || '';
    
    // AirBypass Devices: Core series, LAP-C series, Vital series
    // Use case-insensitive check for Core series to handle 'Core300S', 'CORE300S', etc.
    this.isAirBypassDevice = deviceType.toUpperCase().includes('CORE') || 
                            deviceType.startsWith('LAP-C') || 
                            deviceType.toUpperCase().includes('VITAL');
    
    // AirBaseV2 Devices: LAP-V series, LAP-EL series, EverestAir series
    this.isAirBaseV2Device = deviceType.startsWith('LAP-V') || 
                            deviceType.startsWith('LAP-EL') || 
                            deviceType.toUpperCase().includes('EVERESTAIR');
    
    // Air131 Devices: LV-PUR131S, LV-RH131S
    this.isAir131Device = deviceType.startsWith('LV-');
    
    // Log device class detection with more detail
    this.platform.log.debug(`Device Classification for ${this.device.deviceName}:`);
    this.platform.log.debug(`  - Device Type: "${deviceType}"`);
    this.platform.log.debug(`  - Is AirBypass: ${this.isAirBypassDevice}`);
    this.platform.log.debug(`  - Is AirBaseV2: ${this.isAirBaseV2Device}`);
    this.platform.log.debug(`  - Is Air131: ${this.isAir131Device}`);
    
    if (this.isAirBypassDevice) {
      this.platform.log.debug(`Detected AirBypass device: ${this.device.deviceName} (${deviceType})`);
    } else if (this.isAirBaseV2Device) {
      this.platform.log.debug(`Detected AirBaseV2 device: ${this.device.deviceName} (${deviceType})`);
    } else if (this.isAir131Device) {
      this.platform.log.debug(`Detected Air131 device: ${this.device.deviceName} (${deviceType})`);
    } else {
      this.platform.log.warn(`Unknown device class: ${this.device.deviceName} (${deviceType}) - device may not function properly`);
    }
    
    // Remove any cached air quality service - these are now separate accessories
    const cachedAirQualityService = this.accessory.getService(this.platform.Service.AirQualitySensor);
    if (cachedAirQualityService) {
      this.platform.log.debug(`${this.device.deviceName} (${deviceType}): Removing cached embedded AQ service - AQ sensors are now separate accessories`);
      this.accessory.removeService(cachedAirQualityService);
    }
  }

  /**
   * Feature detection system
   */
  private hasFeature(feature: string): boolean {
    const extendedDevice = this.device as unknown as ExtendedVeSyncAirPurifier;
    
    // **ENHANCED DEBUGGING**: Log detailed device type information
    this.platform.log.debug(`${this.device.deviceName}: FEATURE CHECK - hasFeature('${feature}') for device type: "${this.device.deviceType}"`);
    
    // Use device's native hasFeature method if available
    if (typeof extendedDevice.hasFeature === 'function') {
      const result = extendedDevice.hasFeature(feature);
      this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Native hasFeature('${feature}') returned: ${result} (using tsvesync library configuration)`);
      
      // For air_quality, trust the library's configuration completely
      // The library was updated in v1.0.107 to correctly exclude air_quality for devices without sensors
      if (feature === 'air_quality') {
        this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Air quality feature decision based on tsvesync library config: ${result}`);
        
        // Add extra debugging for Core200S devices
        if (this.device.deviceType.includes('Core200S') || this.device.deviceType.includes('LAP-C20')) {
          this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Core200S variant detected - should NOT have air quality! hasFeature returned: ${result}`);
        }
        
        return result;
      }
      
      // **CRITICAL FIX**: Enhanced filter_life detection with explicit Core300S support
      if (feature === 'filter_life') {
        const deviceType = this.device.deviceType;
        this.platform.log.debug(`${this.device.deviceName} (${deviceType}): Native hasFeature('filter_life') returned: ${result}`);
        
        // **EXPLICIT Core300S CHECK**: Make sure Core300S is always recognized
        if (deviceType === 'Core300S' || deviceType.includes('Core300S')) {
          this.platform.log.debug(`${this.device.deviceName}: Core300S detected - SHOULD support filter_life! Native result: ${result}`);
          if (!result) {
            this.platform.log.warn(`${this.device.deviceName}: Core300S should support filter_life but native hasFeature returned false. OVERRIDING to true.`);
            return true;
          }
        }
        
        if (!result) {
          // Check if this looks like a device type that should support filter_life
          if (deviceType.includes('Core') || 
              deviceType.includes('300S') ||  // Add explicit check for 300S
              deviceType.includes('200S') ||  // Add explicit check for 200S
              deviceType.includes('400S') ||  // Add explicit check for 400S
              deviceType.includes('600S') ||  // Add explicit check for 600S
              deviceType.includes('LAP-') || 
              deviceType.includes('LV-') || 
              deviceType.includes('Vital')) {
            this.platform.log.warn(`${this.device.deviceName}: Device type ${deviceType} should support filter_life but native hasFeature returned false. Overriding to true.`);
            return true;
          }
        }
      }
      
      // **EXPLICIT Core300S auto_mode CHECK**: Make sure Core300S auto mode is recognized
      if (feature === 'auto_mode') {
        const deviceType = this.device.deviceType;
        this.platform.log.debug(`${this.device.deviceName} (${deviceType}): Native hasFeature('auto_mode') returned: ${result}`);
        
        if (deviceType === 'Core300S' || deviceType.includes('Core300S')) {
          this.platform.log.debug(`${this.device.deviceName}: Core300S detected - SHOULD support auto_mode! Native result: ${result}`);
          if (!result) {
            this.platform.log.warn(`${this.device.deviceName}: Core300S should support auto_mode but native hasFeature returned false. OVERRIDING to true.`);
            return true;
          }
        }
      }
      
      return result;
    }
    
    // Fallback feature detection based on device type
    switch (feature) {
      case 'air_quality':
        // Respect the tsvesync library's feature configuration for air quality
        // Only devices with actual hardware sensors should have air quality features
        // The library already correctly configures which devices support air quality
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') returned: false (device does not have air quality sensor per tsvesync config)`);
        return false;
        
      case 'child_lock':
        // Explicitly disable child lock features
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') returned: false (explicitly disabled)`);
        return false;
        
      case 'display':
        // Explicitly disable display control features
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') returned: false (explicitly disabled)`);
        return false;
        
      case 'filter_life':
        // For air purifiers, enable filter life features based on device type patterns
        const deviceType = this.device.deviceType;
        
        // Check device type patterns that should support filter_life
        const supportsFilterByType = deviceType.includes('Core') || 
                                    deviceType.includes('300S') ||  // Explicit check for 300S
                                    deviceType.includes('200S') ||  // Explicit check for 200S
                                    deviceType.includes('400S') ||  // Explicit check for 400S
                                    deviceType.includes('600S') ||  // Explicit check for 600S
                                    deviceType.includes('LAP-') || 
                                    deviceType.includes('LV-') || 
                                    deviceType.includes('Vital');
        
        if (supportsFilterByType) {
          this.platform.log.debug(`${this.device.deviceName}: Device type ${deviceType} supports filter_life by pattern matching`);
          return true;
        }
        
        // Fallback: Check if filter_life data exists in any format
        const filterDevice = this.device as unknown as ExtendedVeSyncAirPurifier;
        const filterLife = filterDevice.details?.filter_life;
        const hasFilterLife = !!(filterLife !== undefined && 
                 (typeof filterLife === 'number' || 
                  (typeof filterLife === 'object' && filterLife !== null && 'percent' in filterLife)));
        
        // Also check for filterLife property from VeSyncFan base class
        const hasFilterLifeProperty = typeof extendedDevice.filterLife === 'number';
        const result = hasFilterLife || hasFilterLifeProperty;
        
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') - details.filter_life: ${JSON.stringify(filterLife)}, device.filterLife: ${extendedDevice.filterLife}, result: ${result}`);
        return result;
        
      case 'fan_speed':
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') returned: true`);
        return true;
        
      default:
        this.platform.log.debug(`${this.device.deviceName}: Fallback hasFeature('${feature}') returned: false (unknown feature)`);
        return false;
    }
  }
  
  /**
   * Check if a feature is supported in the current device mode
   */
  private isFeatureSupportedInCurrentMode(feature: string): boolean {
    const extendedDevice = this.device as unknown as ExtendedVeSyncAirPurifier;
    
    // Use device's native method if available
    if (typeof extendedDevice.isFeatureSupportedInCurrentMode === 'function') {
      return extendedDevice.isFeatureSupportedInCurrentMode(feature);
    }
    
    // Fallback logic
    const mode = extendedDevice.mode || 'manual';
    
    // Air131 only supports fan speed in manual mode
    if (feature === 'fan_speed' && this.isAir131Device && mode !== 'manual') {
      return false;
    }
    
    return true;
  }
  
  /**
   * Get the maximum fan speed for the device
   */
  private getMaxFanSpeed(): number {
    const extendedDevice = this.device as unknown as ExtendedVeSyncAirPurifier;
    
    // Use device's native method if available
    if (typeof extendedDevice.getMaxFanSpeed === 'function') {
      const maxSpeed = extendedDevice.getMaxFanSpeed();
      if (typeof maxSpeed === 'number' && maxSpeed > 0) {
        return maxSpeed;
      }
    }
    
    // Use maxSpeed property if available
    if (typeof extendedDevice.maxSpeed === 'number' && extendedDevice.maxSpeed > 0) {
      return extendedDevice.maxSpeed;
    }
    
    // Fallback logic based on device type
    if (this.isAir131Device) {
      return 3; // LV-series devices have 3 speed levels
    } else if (this.isAirBypassDevice) {
      return 3; // All Core series have 3 speed levels
    } else if (this.isAirBaseV2Device) {
      if (this.device.deviceType.includes('LAP-EL551S')) {
        return 3; // LAP-EL551S has 3 speed levels
      } else {
        return 4; // LAP-V series have 4 speed levels
      }
    }
    
    // Default to 3 for unknown devices
    return 3;
  }

  private isCore200S(): boolean {
    return (this.device.deviceType || '').toUpperCase().includes('CORE200S');
  }

  /**
   * Calculate the appropriate step size for discrete speed levels
   */
  private calculateRotationSpeedStep(): number {
    // Expose Sleep as the first notch when supported.
    // Core 200S uses 3 manual speeds (25% step). 4-speed models use 20% step.
    if (this.hasFeature('sleep_mode')) {
      if (this.hasFeature('turbo_mode')) {
        return 20;
      }
      if (this.isCore200S()) return 25;
      const max = this.getMaxFanSpeed();
      return max >= 4 ? 20 : 25;
    }
    const maxSpeed = this.getMaxFanSpeed();
    if (maxSpeed === 3) return 33.33;
    if (maxSpeed === 4) return 25;
    return 1;
  }

  /**
   * Convert device speed to percentage
   */
  private speedToPercentage(speed: number): number {
    // Sleep as first notch: map manual speeds to notches based on model
    if (this.hasFeature('sleep_mode')) {
      const extended = this.device as ExtendedVeSyncAirPurifier;
      if (this.hasFeature('turbo_mode') && (extended.mode || '').toLowerCase() === 'turbo') {
        return 100;
      }
      if (typeof speed !== 'number' || speed <= 0) return 0;
      const step = this.calculateRotationSpeedStep();
      const max = this.isCore200S() ? 3 : this.getMaxFanSpeed();
      // Manual speeds occupy notches 2..(max+1)
      const notch = Math.max(2, Math.min(max + 1, speed + 1));
      return Math.min(100, notch * step);
    }

    const maxSpeed = this.getMaxFanSpeed();
    if (maxSpeed <= 0 || typeof speed !== 'number' || speed <= 0) return 0;
    if (maxSpeed === 3) return speed === 1 ? 33.33 : speed === 2 ? 66.67 : 100;
    if (maxSpeed === 4) return speed === 1 ? 25 : speed === 2 ? 50 : speed === 3 ? 75 : 100;
    return Math.min(100, Math.max(0, Math.round((speed / maxSpeed) * 100)));
  }
  
  /**
   * Updates the rotation speed characteristic for Air131 devices immediately after turning on.
   * This ensures the UI shows the restored speed instead of 0, providing better user experience.
   * 
   * Air131 devices remember their last speed setting when turned back on, but the characteristic
   * update can be delayed. This method proactively updates the HomeKit characteristic to reflect
   * the actual device speed.
   * 
   * @private
   * @returns {Promise<void>} Promise that resolves when the update is complete
   * @throws Will log errors through handleDeviceError but won't propagate them to avoid
   *         disrupting the main turn-on operation
   */
  private async updateAir131RotationSpeedAfterTurnOn(): Promise<void> {
    try {
      // Validate device and service state
      if (!this.device || !this.service) {
        this.platform.log.warn(`${this.device?.deviceName || 'Unknown'}: Cannot update rotation speed - device or service not available`);
        return;
      }

      // Check if device has a valid speed value
      if (typeof this.device.speed !== 'number' || this.device.speed <= 0) {
        this.platform.log.debug(`${this.device.deviceName}: No valid speed to restore (speed: ${this.device.speed})`);
        return;
      }

      // Convert device speed to percentage with validation
      const percentage = this.speedToPercentage(this.device.speed);
      
      if (typeof percentage !== 'number' || isNaN(percentage) || percentage < 0 || percentage > 100) {
        this.platform.log.warn(`${this.device.deviceName}: Invalid percentage calculated (${percentage}) from speed ${this.device.speed}`);
        return;
      }

      // Update the HomeKit characteristic
      this.service.updateCharacteristic(
        this.platform.Characteristic.RotationSpeed,
        percentage
      );

      this.platform.log.debug(
        `${this.device.deviceName}: Updated rotation speed to ${percentage}% (speed: ${this.device.speed}) after turning on`
      );
    } catch (error) {
      this.handleDeviceError('update Air131 rotation speed after turn on', error);
    }
  }

  /**
   * Convert percentage to device speed
   */
  private percentageToSpeed(percentage: number): number {
    // Sleep as first notch: round to nearest step and map notches → speeds
    if (this.hasFeature('sleep_mode')) {
      if (typeof percentage !== 'number') return 1;
      percentage = Math.min(100, Math.max(0, percentage));
      const step = this.calculateRotationSpeedStep();
      const max = this.isCore200S() ? 3 : this.getMaxFanSpeed();
      const supportsTurbo = this.hasFeature('turbo_mode');
      const totalNotches = max + (supportsTurbo ? 2 : 1); // sleep + manual + optional turbo
      const notch = Math.max(0, Math.min(totalNotches, Math.round(percentage / step)));
      if (supportsTurbo && notch === totalNotches) {
        return max;
      }
      const manualMaxNotch = totalNotches - (supportsTurbo ? 1 : 0);
      const manualNotch = Math.max(2, Math.min(manualMaxNotch, notch));
      return Math.min(max, manualNotch - 1);
    }

    const maxSpeed = this.getMaxFanSpeed();
    if (maxSpeed <= 0 || typeof percentage !== 'number') return 1;
    percentage = Math.min(100, Math.max(0, percentage));
    if (maxSpeed === 3) return percentage <= 33.34 ? 1 : percentage <= 66.67 ? 2 : 3;
    if (maxSpeed === 4) return percentage <= 25 ? 1 : percentage <= 50 ? 2 : percentage <= 75 ? 3 : 4;
    return Math.max(1, Math.min(Math.round((percentage / 100) * maxSpeed), maxSpeed));
  }

  /**
   * Set up the air purifier service
   */
  protected setupService(): void {
    // Get or create the air purifier service
    this.service = this.accessory.getService(this.platform.Service.AirPurifier) ||
      this.accessory.addService(this.platform.Service.AirPurifier);
    
    // Mark the AirPurifier service as primary
    // setPrimaryService may not be available in test environment
    if (typeof this.service.setPrimaryService === 'function') {
      this.service.setPrimaryService(true);
      this.platform.log.debug(`${this.device.deviceName}: Marked AirPurifier service as primary`);
    }

    // **CRITICAL FIX**: Add optional characteristics FIRST before setting up handlers
    // This ensures they persist through service configuration
    this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Pre-configuring optional characteristics`);
    
    // Always set up filter characteristics (like reference plugin does)
    // The reference implementation ALWAYS registers these for ALL air purifiers
    // This ensures they appear in HomeKit even if the device doesn't report having them initially
    this.platform.log.debug(`${this.device.deviceName}: Setting up filter characteristics for all air purifiers`);
    
    // Use getCharacteristic which auto-adds if missing (like reference plugin)
    this.service.getCharacteristic(this.platform.Characteristic.FilterChangeIndication)
      .onGet(this.getFilterChangeIndication.bind(this));
    
    this.service.getCharacteristic(this.platform.Characteristic.FilterLifeLevel)
      .onGet(this.getFilterLifeLevel.bind(this))
      .setProps({
        minValue: 0,
        maxValue: 100,
        minStep: 1
      });
    
    this.platform.log.debug(`${this.device.deviceName}: Filter characteristics registered (always present for air purifiers)`)

    // Set up required characteristics
    this.setupCharacteristic(
      this.platform.Characteristic.Active,
      this.getActive.bind(this),
      this.setActive.bind(this)
    );

    // Set up target state characteristic for mode mapping
    const targetStateChar = this.service.getCharacteristic(this.platform.Characteristic.TargetAirPurifierState);
    
    // Check if device supports auto mode
    const hasAutoMode = this.hasFeature('auto_mode');
    this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Auto mode support check - hasFeature('auto_mode') = ${hasAutoMode}`);
    
    // For Core200S, only allow manual mode
    if (this.device.deviceType.includes('Core200S')) {
      targetStateChar.setProps({
        validValues: [0] // MANUAL only
      });
      this.platform.log.debug(`${this.device.deviceName} (Core200S): Configured for MANUAL mode only - no auto mode support`);
    } else if (this.device.deviceType.includes('Core300S')) {
      // Core300S explicitly supports both modes
      targetStateChar.setProps({
        validValues: [0, 1] // MANUAL and AUTO
      });
      this.platform.log.debug(`${this.device.deviceName} (Core300S): ✅ Configured for BOTH AUTO and MANUAL modes - auto mode ENABLED`);
      this.platform.log.debug(`${this.device.deviceName} (Core300S): Target state characteristic should now show mode switcher in HomeKit`);
    } else if (hasAutoMode) {
      // Other devices with auto_mode feature
      targetStateChar.setProps({
        validValues: [0, 1] // MANUAL and AUTO
      });
      this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Configured for AUTO and MANUAL modes based on feature detection`);
    } else {
      // Devices without auto mode
      targetStateChar.setProps({
        validValues: [0] // MANUAL only
      });
      this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Configured for MANUAL mode only - no auto mode feature`);
    }
    
    // Set up the characteristic handlers for all devices
    this.setupCharacteristic(
      this.platform.Characteristic.TargetAirPurifierState,
      this.getTargetState.bind(this),
      this.setTargetState.bind(this)
    );

    // Set up current state
    this.setupCharacteristic(
      this.platform.Characteristic.CurrentAirPurifierState,
      this.getCurrentState.bind(this)
    );

    // Set up rotation speed characteristic using the simplified approach (like reference plugin)
    const minStep = this.calculateRotationSpeedStep();
    
    this.service.getCharacteristic(this.platform.Characteristic.RotationSpeed)
      .onGet(this.getRotationSpeed.bind(this))
      .onSet(this.setRotationSpeed.bind(this))
      .setProps({
        minValue: 0,
        maxValue: 100,
        minStep: minStep
      });
    
    this.platform.log.debug(`${this.device.deviceName}: Configured RotationSpeed with minStep: ${minStep}`);

    // Add Name characteristic
    this.setupCharacteristic(
      this.platform.Characteristic.Name,
      async () => this.device.deviceName
    );
    
    // Air quality sensors are now separate accessories
    // Remove any legacy embedded AQ service
    const existingAirQualityService = this.accessory.getService(this.platform.Service.AirQualitySensor);
    if (existingAirQualityService) {
      this.platform.log.debug(`${this.device.deviceName}: Removing legacy embedded air quality service`);
      this.accessory.removeService(existingAirQualityService);
    }
    
    // Clean up any existing FilterMaintenance service (from old implementation)
    const existingFilterService = this.accessory.getService(this.platform.Service.FilterMaintenance);
    if (existingFilterService) {
      this.platform.log.debug(`${this.device.deviceName}: Removing old FilterMaintenance service (migrating to AirPurifier service)`);
      this.accessory.removeService(existingFilterService);
    }
    
    // Check and log important features for debugging
    const autoModeSupported = this.hasFeature('auto_mode');
    this.platform.log.debug(`${this.device.deviceName} (${this.device.deviceType}): Features detected:`);
    this.platform.log.debug(`  - auto_mode: ${autoModeSupported} (controls mode switch)`);
    this.platform.log.debug(`  - filter_life: ${this.hasFeature('filter_life')} (controls filter display)`);
  }



  /**
   * Extract filter life from device data in a centralized way
   */
  private extractFilterLife(): number {
    const extendedDevice = this.device as unknown as ExtendedVeSyncAirPurifier;
    
    // Priority 1: Use device's normalized filterLife property
    if (typeof extendedDevice.filterLife === 'number' && !isNaN(extendedDevice.filterLife)) {
      return extendedDevice.filterLife;
    }
    
    // Priority 2: Check details.filter_life
    const filterLifeData = extendedDevice.details?.filter_life;
    
    // Handle number format
    if (typeof filterLifeData === 'number' && !isNaN(filterLifeData)) {
      return filterLifeData;
    }
    
    // Handle object format { percent: number }
    if (typeof filterLifeData === 'object' && filterLifeData !== null && 'percent' in filterLifeData) {
      const percent = (filterLifeData as { percent: number }).percent;
      return (typeof percent === 'number' && !isNaN(percent)) ? percent : 100;
    }
    
    // Default to 100% (filter OK)
    return 100;
  }

  /**
   * Get filter change indication
   */
  private async getFilterChangeIndication(): Promise<CharacteristicValue> {
    const filterLife = this.extractFilterLife();
    
    // Indicate filter change needed when life is below 10%
    return filterLife < 10 ? 1 : 0; // 0=FILTER_OK, 1=CHANGE_FILTER
  }

  /**
   * Get filter life level
   */
  private async getFilterLifeLevel(): Promise<CharacteristicValue> {
    const filterLife = this.extractFilterLife();
    
    // Ensure value is within HomeKit limits (0-100) and round to nearest integer
    return Math.round(Math.min(100, Math.max(0, filterLife)));
  }
  
  /**
   * Get current state (INACTIVE = 0, IDLE = 1, PURIFYING_AIR = 2)
   */
  private async getCurrentState(): Promise<CharacteristicValue> {
    return this.device.deviceStatus === 'on' ? 2 : 0;
  }

  /**
   * Get device capabilities
   */
  protected getDeviceCapabilities(): DeviceCapabilities {
    return {
      hasSpeed: true,
      hasAirQuality: false, // Air quality is now handled by separate accessories
      hasChildLock: false, // Explicitly disable child lock
      hasBrightness: false,
      hasColorTemp: false,
      hasColor: false,
      hasHumidity: false,
      hasWaterLevel: false,
      hasSwingMode: false,
    };
  }

  /**
   * Update device states based on the latest details
   */
  protected async updateDeviceSpecificStates(details: any): Promise<void> {
    // Update power state (treat sleep as on for some VeSync models)
    const extended = this.device as ExtendedVeSyncAirPurifier;
    const mode = (extended.mode || details.mode || '').toLowerCase();
    const isSleep = mode === 'sleep';
    const isTurbo = this.hasFeature('turbo_mode') && mode === 'turbo';
    const isOn = isSleep || details.enabled || details.deviceStatus === 'on';
    this.service.updateCharacteristic(this.platform.Characteristic.Active, isOn ? 1 : 0);
    
    // Update current state (INACTIVE = 0, IDLE = 1, PURIFYING_AIR = 2)
    this.service.updateCharacteristic(
      this.platform.Characteristic.CurrentAirPurifierState,
      isOn ? 2 : 0
    );

    // Get the extended device to access mode information
    const extendedDevice = this.device as ExtendedVeSyncAirPurifier;
    
    // Update target state (MANUAL = 0, AUTO = 1)
    // Special handling for Core200S
    let targetState = 0; // Default to MANUAL
    
    if (this.device.deviceType.includes('Core200S')) {
      // Core200S always reports MANUAL mode
      targetState = 0; // MANUAL
    } else if (extendedDevice.mode) {
      // For other devices, including Core300S, use the reported mode
      targetState = extendedDevice.mode === 'auto' ? 1 : 0;
    }
    
    this.service.updateCharacteristic(
      this.platform.Characteristic.TargetAirPurifierState,
      targetState
    );

    // Update rotation speed
    if (isOn && isTurbo) {
      this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, 100);
      this.lastSetSpeed = this.getMaxFanSpeed();
      this.lastSetPercentage = 100;
    } else if (isOn && this.hasFeature('sleep_mode') && isSleep) {
      const step = this.calculateRotationSpeedStep();
      this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, step);
      this.lastSetSpeed = 0;
      this.lastSetPercentage = step;
    } else if (isOn && details.speed !== undefined && details.speed !== null) {
      // Check if we should skip this update
      if (this.skipNextUpdate) {
        this.platform.log.debug(`Skipping update for ${this.device.deviceName} as requested`);
        this.skipNextUpdate = false;
        return;
      }
      
      // If we've recently set the speed, use the percentage we calculated
      if (this.lastSetSpeed > 0 && this.lastSetPercentage > 0) {
        this.platform.log.debug(`Using last set percentage for ${this.device.deviceName}: speed=${this.lastSetSpeed}, percentage=${this.lastSetPercentage}`);
        
        // Only update if the device speed matches what we set
        if (this.lastSetSpeed === details.speed) {
          this.platform.log.debug(`Device speed matches last set speed: ${details.speed}`);
          
          // Force update the characteristic to our last set percentage
          this.service.updateCharacteristic(
            this.platform.Characteristic.RotationSpeed,
            this.lastSetPercentage
          );
        } else {
          // Device speed doesn't match what we set, so convert from device speed
          const percentage = this.speedToPercentage(details.speed);
          this.platform.log.debug(`Device speed doesn't match last set speed. Device: ${details.speed}, Last set: ${this.lastSetSpeed}, Calculated percentage: ${percentage}`);
          
          // Update our tracking variables
          this.lastSetSpeed = details.speed;
          this.lastSetPercentage = percentage;
          
          // Update the characteristic
          this.service.updateCharacteristic(
            this.platform.Characteristic.RotationSpeed,
            percentage
          );
        }
      } else {
        // No recent set speed, so convert from device speed
        const percentage = this.speedToPercentage(details.speed);
        this.platform.log.debug(`No recent set speed for ${this.device.deviceName}. Device speed: ${details.speed}, Calculated percentage: ${percentage}`);
        
        // Update the characteristic
        this.service.updateCharacteristic(
          this.platform.Characteristic.RotationSpeed,
          percentage
        );
      }
    } else {
      this.service.updateCharacteristic(
        this.platform.Characteristic.RotationSpeed,
        0
      );
      // Reset tracking variables when device is off
      this.lastSetSpeed = 0;
      this.lastSetPercentage = 0;
    }
    
    // Air quality is now handled by separate accessories
    // No need to update AQ characteristics here
    
    // Update filter characteristics on main service if supported
    if (this.hasFeature('filter_life')) {
      const filterLife = this.extractFilterLife();
      
      // Update filter change indication on main service
      this.service?.updateCharacteristic(
        this.platform.Characteristic.FilterChangeIndication,
        filterLife < 10 ? 1 : 0
      );
      
      // Update filter life level on main service
      this.service?.updateCharacteristic(
        this.platform.Characteristic.FilterLifeLevel,
        Math.min(100, Math.max(0, filterLife))
      );
    }
  }

  /**
   * Get target state (MANUAL = 0, AUTO = 1)
   */
  private async getTargetState(): Promise<CharacteristicValue> {
    // For Core200S, always return MANUAL
    if (this.device.deviceType.includes('Core200S')) {
      return 0; // MANUAL
    }
    
    const extendedDevice = this.device as ExtendedVeSyncAirPurifier;
    const targetState = extendedDevice.mode === 'auto' ? 1 : 0;
    
    return targetState;
  }

  /**
   * Set target state (AUTO = 0, MANUAL = 1)
   */
  private async setTargetState(value: CharacteristicValue): Promise<void> {
    try {
      const targetState = value as number;
      const extendedDevice = this.device as ExtendedVeSyncAirPurifier;
      
      // For Core200S, don't allow mode changes
      if (this.device.deviceType.includes('Core200S')) {
        this.platform.log.warn(`Mode changes not supported on ${this.device.deviceName}, only fan speed control is available`);
        // Update the characteristic back to MANUAL (0)
        this.service.updateCharacteristic(this.platform.Characteristic.TargetAirPurifierState, 0);
        return;
      }
      
      // For all other devices, including Core300S, normal mode handling
      const mode = targetState === 1 ? 'auto' : 'manual';
      this.platform.log.info(`Changing mode to ${mode} for device: ${this.device.deviceName}`);
      
      let success = false;
      
      // Use the appropriate method to set the mode
      if (targetState === 1 && typeof extendedDevice.autoMode === 'function') {
        success = await extendedDevice.autoMode();
      } else if (targetState === 0 && typeof extendedDevice.manualMode === 'function') {
        success = await extendedDevice.manualMode();
      } else if (typeof extendedDevice.setMode === 'function') {
        success = await extendedDevice.setMode(mode as 'auto' | 'manual' | 'sleep');
      } else if (typeof this.device.setMode === 'function') {
        success = await this.device.setMode(mode);
      } else {
        throw new Error('Device API does not support mode setting operations');
      }
      
      if (!success) {
        throw new Error(`Failed to set mode to ${mode}`);
      }
      
      // Update device state and characteristics
      await this.updateDeviceSpecificStates(this.device);
    } catch (error) {
      this.handleDeviceError('set target state', error);
    }
  }

  /**
   * Get rotation speed
   */
  private async getRotationSpeed(): Promise<CharacteristicValue> {
    const extended = this.device as ExtendedVeSyncAirPurifier;
    if (this.hasFeature('turbo_mode') && (extended.mode || '').toLowerCase() === 'turbo') {
      return 100;
    }
    // If device is off or speed is not defined, return 0
    if (this.device.deviceStatus !== 'on' || 
        this.device.speed === undefined || 
        this.device.speed === null) {
      // If in sleep mode, surface the first notch
      if (this.hasFeature('sleep_mode') && (extended.mode || '').toLowerCase() === 'sleep') {
        return this.calculateRotationSpeedStep();
      }
      return 0;
    }
    
    // If we have a last set percentage, use that instead of calculating from device speed
    if (this.lastSetPercentage > 0 && this.lastSetSpeed === this.device.speed) {
      this.platform.log.debug(`getRotationSpeed returning last set percentage: ${this.lastSetPercentage} for speed: ${this.device.speed}`);
      return this.lastSetPercentage;
    }
    
    // Convert device speed to percentage using our consistent conversion method
    const percentage = this.speedToPercentage(this.device.speed);
    this.platform.log.debug(`getRotationSpeed calculated percentage: ${percentage} for speed: ${this.device.speed}`);
    
    return percentage;
  }

  /**
   * Set rotation speed
   */
  private async setRotationSpeed(value: CharacteristicValue): Promise<void> {
    try {
      // Ensure value is a valid number
      let percentage = value as number;
      if (isNaN(percentage) || percentage === null || percentage === undefined) {
        this.platform.log.warn(`Invalid rotation speed value: ${value} for device: ${this.device.deviceName}`);
        return;
      }
      
      // Ensure percentage is between 0 and 100
      percentage = Math.min(100, Math.max(0, percentage));
      
      this.platform.log.debug(`Setting rotation speed to ${percentage}% for device: ${this.device.deviceName}`);
      
      if (percentage === 0) {
        // Turn off the device instead of setting speed to 0
        this.platform.log.debug(`Turning off device ${this.device.deviceName} due to 0% rotation speed`);
        const success = await this.device.turnOff();
        if (!success) {
          throw new Error('Failed to turn off device');
        }
        // Reset tracking variables when turning off
        this.lastSetSpeed = 0;
        this.lastSetPercentage = 0;
        return;
      }
      
      const extendedDevice = this.device as ExtendedVeSyncAirPurifier;
      
      // Check if device is off and turn it on first
      if (this.device.deviceStatus !== 'on') {
        this.platform.log.debug(`Device ${this.device.deviceName} is off, turning on before setting speed`);
        const turnOnSuccess = await this.device.turnOn();
        if (!turnOnSuccess) {
          // For LV-PUR131S, this might return false if already on, so check actual state
          if (this.isAir131Device && this.device.deviceStatus === 'on') {
            this.platform.log.debug(`${this.device.deviceName}: Device is now on`);
          } else {
            throw new Error('Failed to turn on device');
          }
        }
        // Wait a bit for the device to turn on
        await new Promise(resolve => setTimeout(resolve, 1000));
        
        // Update device state to get fresh mode information
        await this.updateDeviceSpecificStates(this.device);
      }
      
      // When using sleep-as-first-notch, map slider notches robustly by rounding
      if (this.hasFeature('sleep_mode')) {
        const max = this.isCore200S() ? 3 : this.getMaxFanSpeed();
        const step = this.calculateRotationSpeedStep();
        const supportsTurbo = this.hasFeature('turbo_mode');
        const totalNotches = max + (supportsTurbo ? 2 : 1); // sleep + manual + optional turbo
        const notch = Math.max(0, Math.min(totalNotches, Math.round(percentage / step)));
        if (notch <= 1) {
          // Sleep
          this.platform.log.info(`Changing mode to sleep for device: ${this.device.deviceName}`);
          let ok = false;
          if (typeof extendedDevice.sleepMode === 'function') {
            ok = await extendedDevice.sleepMode();
          } else if (typeof extendedDevice.setMode === 'function') {
            ok = await extendedDevice.setMode('sleep');
          }
          if (!ok) {
            throw new Error('Failed to set sleep mode');
          }
          // Immediate UI feedback
          this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, step);
          this.service.updateCharacteristic(this.platform.Characteristic.Active, 1);
          this.service.updateCharacteristic(this.platform.Characteristic.CurrentAirPurifierState, 2);
          this.lastSetSpeed = 0;
          this.lastSetPercentage = step;
          this.skipNextUpdate = true;
          return;
        }
        if (supportsTurbo && notch === totalNotches) {
          this.platform.log.info(`Changing mode to turbo for device: ${this.device.deviceName}`);
          let ok = false;
          if (typeof extendedDevice.turboMode === 'function') {
            ok = await extendedDevice.turboMode();
          } else if (typeof extendedDevice.setMode === 'function') {
            ok = await extendedDevice.setMode('turbo');
          }
          if (!ok) {
            throw new Error('Failed to set turbo mode');
          }
          this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, 100);
          this.service.updateCharacteristic(this.platform.Characteristic.Active, 1);
          this.service.updateCharacteristic(this.platform.Characteristic.CurrentAirPurifierState, 2);
          this.lastSetSpeed = max;
          this.lastSetPercentage = 100;
          this.skipNextUpdate = true;
          return;
        }

        // Map manual notches (2..manualMaxNotch) to speeds 1..max
        const manualMaxNotch = totalNotches - (supportsTurbo ? 1 : 0);
        const manualNotch = Math.max(2, Math.min(manualMaxNotch, notch));
        const desiredSpeed = Math.min(max, manualNotch - 1);
        // Ensure manual mode before speed change if necessary
        const modeNow = (extendedDevice.mode || '').toLowerCase();
        if (modeNow === 'auto' || modeNow === 'sleep' || (supportsTurbo && modeNow === 'turbo')) {
          this.platform.log.info(`Changing mode to manual for device: ${this.device.deviceName}`);
          if (typeof extendedDevice.manualMode === 'function') {
            await extendedDevice.manualMode();
          } else if (typeof extendedDevice.setMode === 'function') {
            await extendedDevice.setMode('manual');
          }
        }
        // Update UI early
        const uiPct = Math.min(100, manualNotch * step);
        this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, uiPct);
        this.lastSetSpeed = desiredSpeed;
        this.lastSetPercentage = uiPct;
        this.skipNextUpdate = true;
        const ok = await this.device.changeFanSpeed(desiredSpeed);
        if (!ok) {
          this.lastSetSpeed = 0;
          this.lastSetPercentage = 0;
          throw new Error(`Failed to set speed to ${desiredSpeed}`);
        }
        return;
      }

      // Check if fan speed control is supported in current mode
      if (!this.isFeatureSupportedInCurrentMode('fan_speed')) {
        this.platform.log.warn(`Fan speed control not supported in ${extendedDevice.mode} mode for device: ${this.device.deviceName}`);
        
        // For Air131 devices, switch to manual mode first
        if (this.isAir131Device && extendedDevice.mode !== 'manual') {
          this.platform.log.debug(`Setting device to manual mode before changing fan speed: ${this.device.deviceName}`);
          
          // Use the appropriate method to set manual mode
          if (typeof extendedDevice.manualMode === 'function') {
            const modeSuccess = await extendedDevice.manualMode();
            this.platform.log.debug(`Set manual mode result: ${modeSuccess ? 'success' : 'failed'}`);
            // Wait for mode change to take effect
            await new Promise(resolve => setTimeout(resolve, 1000));
          } else if (typeof extendedDevice.setMode === 'function') {
            const modeSuccess = await extendedDevice.setMode('manual');
            this.platform.log.debug(`Set manual mode result: ${modeSuccess ? 'success' : 'failed'}`);
            // Wait for mode change to take effect
            await new Promise(resolve => setTimeout(resolve, 1000));
          }
        }
      }
      
      // For devices without sleep notch, ensure manual mode if required
      const modeNow = (extendedDevice.mode || '').toLowerCase();
      if (modeNow === 'auto') {
        if (typeof extendedDevice.manualMode === 'function') {
          await extendedDevice.manualMode();
        } else if (typeof extendedDevice.setMode === 'function') {
          await extendedDevice.setMode('manual');
        }
      }

      // Convert percentage to device speed using our consistent conversion method
      const speed = this.percentageToSpeed(percentage);
      
      // Final validation to ensure speed is a valid number
      if (isNaN(speed) || speed === null || speed === undefined) {
        this.platform.log.warn(`Calculated invalid speed: ${speed} from percentage: ${percentage} for device: ${this.device.deviceName}`);
        return;
      }
      
      this.platform.log.debug(`Setting fan speed to ${speed} for device: ${this.device.deviceName}`);
      
      // Store the values we're setting before making the API call
      this.lastSetSpeed = speed;
      this.lastSetPercentage = percentage;
      
      // Set the flag to skip the next update
      this.skipNextUpdate = true;
      
      // Immediately update the characteristic to show the correct percentage
      // This ensures the slider shows the value we set, not what the device reports
      this.service.updateCharacteristic(
        this.platform.Characteristic.RotationSpeed,
        percentage
      );
      
      const success = await this.device.changeFanSpeed(speed);
      
      if (!success) {
        // If the API call failed, reset our tracking variables
        this.lastSetSpeed = 0;
        this.lastSetPercentage = 0;
        throw new Error(`Failed to set speed to ${speed}`);
      }
      
      this.platform.log.debug(`Successfully set fan speed to ${speed} (${percentage}%) for device: ${this.device.deviceName}`);
      
      // Update device state and characteristics
      // Skip this to avoid overriding our UI update
      // await this.updateDeviceSpecificStates(this.device);
    } catch (error) {
      this.handleDeviceError('set rotation speed', error);
    }
  }

  private async getActive(): Promise<CharacteristicValue> {
    return this.device.deviceStatus === 'on' ? 1 : 0;
  }

  private async setActive(value: CharacteristicValue): Promise<void> {
    try {
      const isOn = value as number === 1;
      this.platform.log.debug(`Setting device ${this.device.deviceName} to ${isOn ? 'on' : 'off'}`);
      
      // Immediately update HomeKit characteristics for better responsiveness
      // This provides instant feedback to the user while the API call is made
      this.service.updateCharacteristic(this.platform.Characteristic.Active, isOn ? 1 : 0);
      this.service.updateCharacteristic(
        this.platform.Characteristic.CurrentAirPurifierState,
        isOn ? 2 : 0  // 2 = PURIFYING_AIR, 0 = INACTIVE
      );
      
      const success = isOn ? await this.device.turnOn() : await this.device.turnOff();
      
      if (!success) {
        // For LV-PUR131S, success=false might mean device is already in desired state
        if (this.isAir131Device) {
          this.platform.log.debug(`${this.device.deviceName}: turn${isOn ? 'On' : 'Off'}() returned false - device may already be ${isOn ? 'on' : 'off'}`);
          // Check actual device state
          const actualState = this.device.deviceStatus === 'on';
          if (actualState === isOn) {
            this.platform.log.debug(`${this.device.deviceName}: Device is already in desired state (${isOn ? 'on' : 'off'})`);
            return; // Don't throw error if already in desired state
          }
        }
        
        // If the API call failed, revert the HomeKit state
        this.platform.log.warn(`Failed to turn ${isOn ? 'on' : 'off'} device, reverting HomeKit state`);
        this.service.updateCharacteristic(this.platform.Characteristic.Active, isOn ? 0 : 1);
        this.service.updateCharacteristic(
          this.platform.Characteristic.CurrentAirPurifierState,
          isOn ? 0 : 2
        );
        throw new Error(`Failed to turn ${isOn ? 'on' : 'off'} device`);
      }
      
      // Reset tracking variables when turning off
      if (!isOn) {
        this.lastSetSpeed = 0;
        this.lastSetPercentage = 0;
        // Also immediately update rotation speed to 0
        this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, 0);
      } else if (isOn) {
        // For all air purifiers when turning on, restore the rotation speed
        if (this.isAir131Device) {
          // For Air131 devices, immediately update rotation speed characteristic
          // to show the restored speed instead of 0
          await this.updateAir131RotationSpeedAfterTurnOn();
        } else if (this.device.speed && this.device.speed > 0) {
          // For other devices, also update the speed immediately
          const percentage = this.speedToPercentage(this.device.speed);
          this.service.updateCharacteristic(this.platform.Characteristic.RotationSpeed, percentage);
        }
      }
      
      // Don't call updateDeviceSpecificStates to avoid polling the API
      // The device state is already reflected in HomeKit through our immediate updates
      // await this.updateDeviceSpecificStates(this.device);
      
      // Still persist the state for recovery after restarts
      await this.persistDeviceState('deviceStatus', isOn ? 'on' : 'off');
      
      this.platform.log.debug(`${this.device.deviceName}: Successfully turned ${isOn ? 'on' : 'off'} with immediate HomeKit feedback`);
    } catch (error) {
      this.handleDeviceError('set active state', error);
    }
  }
}
