import { Injectable, Inject } from '@nestjs/common';
import type { RecordPageViewInputDTO } from '../dtos/RecordPageViewInputDTO';
import type { RecordPageViewOutputDTO } from '../dtos/RecordPageViewOutputDTO';
import type { IPageViewRepository } from '@core/analytics/application/repositories/IPageViewRepository';
import type { Logger } from '@core/shared/application';
import { PageView } from '@core/analytics/domain/entities/PageView';

type RecordPageViewInput = RecordPageViewInputDTO;
type RecordPageViewOutput = RecordPageViewOutputDTO;

const Logger_TOKEN = 'Logger_TOKEN';
const IPAGE_VIEW_REPO_TOKEN = 'IPageViewRepository_TOKEN';

@Injectable()
export class RecordPageViewUseCase {
  constructor(
    @Inject(IPAGE_VIEW_REPO_TOKEN) private readonly pageViewRepository: IPageViewRepository,
    @Inject(Logger_TOKEN) private readonly logger: Logger,
  ) {}

  async execute(input: RecordPageViewInput): Promise<RecordPageViewOutput> {
    this.logger.debug('Executing RecordPageViewUseCase', { input });
    try {
      const pageViewId = `pv-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

      const baseProps: Omit<Parameters<typeof PageView.create>[0], 'timestamp'> = {
        id: pageViewId,
        entityType: input.entityType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment
        entityId: input.entityId,
        visitorType: input.visitorType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment
        sessionId: input.sessionId,
      };

      const pageView = PageView.create({
        ...baseProps,
        ...(input.visitorId !== undefined ? { visitorId: input.visitorId } : {}),
        ...(input.referrer !== undefined ? { referrer: input.referrer } : {}),
        ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}),
        ...(input.country !== undefined ? { country: input.country } : {}),
      });

      await this.pageViewRepository.save(pageView);
      this.logger.info('Page view recorded successfully', { pageViewId, input });
      return { pageViewId };
    } catch (error) {
      this.logger.error('Error recording page view', error, { input });
      throw error;
    }
  }
}