import { PageView } from '@core/analytics/domain/entities/PageView';
import type { EntityType, VisitorType } from '@core/analytics/domain/types/PageView';

import { PageViewOrmEntity } from '../entities/PageViewOrmEntity';
import { TypeOrmAnalyticsSchemaError } from '../errors/TypeOrmAnalyticsSchemaError';
import {
    assertDate,
    assertEnumValue,
    assertNonEmptyString,
    assertOptionalIntegerOrNull,
    assertOptionalStringOrNull,
} from '../schema/TypeOrmAnalyticsSchemaGuards';

const VALID_ENTITY_TYPES: readonly EntityType[] = ['league', 'driver', 'team', 'race', 'sponsor'] as const;
const VALID_VISITOR_TYPES: readonly VisitorType[] = ['anonymous', 'driver', 'sponsor'] as const;

export class PageViewOrmMapper {
  toOrmEntity(domain: PageView): PageViewOrmEntity {
    const entity = new PageViewOrmEntity();
    entity.id = domain.id;
    entity.entityType = domain.entityType;
    entity.entityId = domain.entityId;

    entity.visitorId = domain.visitorId ?? null;
    entity.visitorType = domain.visitorType;
    entity.sessionId = domain.sessionId;

    entity.referrer = domain.referrer ?? null;
    entity.userAgent = domain.userAgent ?? null;
    entity.country = domain.country ?? null;

    entity.timestamp = domain.timestamp;
    entity.durationMs = domain.durationMs ?? null;

    return entity;
  }

  toDomain(entity: PageViewOrmEntity): PageView {
    const entityName = 'AnalyticsPageView';

    try {
      assertNonEmptyString(entityName, 'id', entity.id);

      assertEnumValue<EntityType>(entityName, 'entityType', entity.entityType, VALID_ENTITY_TYPES);
      assertNonEmptyString(entityName, 'entityId', entity.entityId);

      assertOptionalStringOrNull(entityName, 'visitorId', entity.visitorId);
      assertEnumValue<VisitorType>(entityName, 'visitorType', entity.visitorType, VALID_VISITOR_TYPES);
      assertNonEmptyString(entityName, 'sessionId', entity.sessionId);

      assertOptionalStringOrNull(entityName, 'referrer', entity.referrer);
      assertOptionalStringOrNull(entityName, 'userAgent', entity.userAgent);
      assertOptionalStringOrNull(entityName, 'country', entity.country);

      assertDate(entityName, 'timestamp', entity.timestamp);
      assertOptionalIntegerOrNull(entityName, 'durationMs', entity.durationMs);

      return PageView.create({
        id: entity.id,
        entityType: entity.entityType,
        entityId: entity.entityId,
        visitorType: entity.visitorType,
        sessionId: entity.sessionId,
        timestamp: entity.timestamp,
        ...(entity.visitorId !== null && entity.visitorId !== undefined ? { visitorId: entity.visitorId } : {}),
        ...(entity.referrer !== null && entity.referrer !== undefined ? { referrer: entity.referrer } : {}),
        ...(entity.userAgent !== null && entity.userAgent !== undefined ? { userAgent: entity.userAgent } : {}),
        ...(entity.country !== null && entity.country !== undefined ? { country: entity.country } : {}),
        ...(entity.durationMs !== null && entity.durationMs !== undefined ? { durationMs: entity.durationMs } : {}),
      });
    } catch (error) {
      if (error instanceof TypeOrmAnalyticsSchemaError) {
        throw error;
      }

      const message = error instanceof Error ? error.message : 'Invalid persisted AnalyticsPageView';
      throw new TypeOrmAnalyticsSchemaError({ entityName, fieldName: 'unknown', reason: 'invalid_shape', message });
    }
  }
}