import { NotificationPreference } from '@core/notifications/domain/entities/NotificationPreference';
import { NotificationPreferenceOrmEntity } from '../entities/NotificationPreferenceOrmEntity';
import { TypeOrmPersistenceSchemaError } from '../errors/TypeOrmPersistenceSchemaError';
import {
    assertBoolean,
    assertChannelPreferences,
    assertDate,
    assertNonEmptyString,
    assertOptionalInteger,
    assertOptionalObject,
} from '../schema/NotificationSchemaGuards';

export class NotificationPreferenceOrmMapper {
  toDomain(entity: NotificationPreferenceOrmEntity): NotificationPreference {
    const entityName = 'NotificationPreference';

    try {
      assertNonEmptyString(entityName, 'id', entity.id);
      assertNonEmptyString(entityName, 'driverId', entity.driverId);
      assertChannelPreferences(entityName, 'channels', entity.channels);
      assertOptionalObject(entityName, 'typePreferences', entity.typePreferences);
      assertBoolean(entityName, 'digestMode', entity.digestMode);
      assertOptionalInteger(entityName, 'digestFrequencyHours', entity.digestFrequencyHours);
      assertOptionalInteger(entityName, 'quietHoursStart', entity.quietHoursStart);
      assertOptionalInteger(entityName, 'quietHoursEnd', entity.quietHoursEnd);
      assertDate(entityName, 'createdAt', entity.createdAt);
      assertDate(entityName, 'updatedAt', entity.updatedAt);
    } catch (error) {
      if (error instanceof TypeOrmPersistenceSchemaError) {
        throw error;
      }
      const message = error instanceof Error ? error.message : 'Invalid persisted NotificationPreference';
      throw new TypeOrmPersistenceSchemaError({ entityName, fieldName: 'unknown', reason: 'invalid_shape', message });
    }

    try {
      const domainProps: any = {
        id: entity.id,
        driverId: entity.driverId,
        channels: entity.channels,
        digestMode: entity.digestMode,
        updatedAt: entity.updatedAt,
      };

      if (entity.typePreferences !== null && entity.typePreferences !== undefined) {
        domainProps.typePreferences = entity.typePreferences;
      }

      if (entity.digestFrequencyHours !== null && entity.digestFrequencyHours !== undefined) {
        domainProps.digestFrequencyHours = entity.digestFrequencyHours;
      }

      if (entity.quietHoursStart !== null && entity.quietHoursStart !== undefined) {
        domainProps.quietHoursStart = entity.quietHoursStart;
      }

      if (entity.quietHoursEnd !== null && entity.quietHoursEnd !== undefined) {
        domainProps.quietHoursEnd = entity.quietHoursEnd;
      }

      return NotificationPreference.create(domainProps);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Invalid persisted NotificationPreference';
      throw new TypeOrmPersistenceSchemaError({ entityName, fieldName: 'unknown', reason: 'invalid_shape', message });
    }
  }

  toOrmEntity(preference: NotificationPreference): NotificationPreferenceOrmEntity {
    const entity = new NotificationPreferenceOrmEntity();
    const props = preference.toJSON();

    entity.id = props.id;
    entity.driverId = props.driverId;
    entity.channels = props.channels;
    entity.typePreferences = props.typePreferences ?? null;
    entity.digestMode = props.digestMode ?? false;
    entity.digestFrequencyHours = props.digestFrequencyHours ?? null;
    entity.quietHoursStart = props.quietHoursStart ?? null;
    entity.quietHoursEnd = props.quietHoursEnd ?? null;
    entity.updatedAt = props.updatedAt;

    return entity;
  }

  toStored(entity: NotificationPreferenceOrmEntity): NotificationPreference {
    return this.toDomain(entity);
  }
}