import type { Logger, UseCase, UseCaseOutputPort } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { IPageViewRepository } from '../repositories/IPageViewRepository';

export interface GetAnalyticsMetricsInput {
  startDate?: Date;
  endDate?: Date;
}

export interface GetAnalyticsMetricsOutput {
  pageViews: number;
  uniqueVisitors: number;
  averageSessionDuration: number;
  bounceRate: number;
}

export type GetAnalyticsMetricsErrorCode = 'REPOSITORY_ERROR';

export class GetAnalyticsMetricsUseCase implements UseCase<GetAnalyticsMetricsInput, void, GetAnalyticsMetricsErrorCode> {
  constructor(
    private readonly logger: Logger,
    private readonly output: UseCaseOutputPort<GetAnalyticsMetricsOutput>,
    private readonly pageViewRepository?: IPageViewRepository,
  ) {}

  async execute(
    input: GetAnalyticsMetricsInput = {},
  ): Promise<Result<void, ApplicationErrorCode<GetAnalyticsMetricsErrorCode, { message: string }>>> {
    try {
      const startDate = input.startDate ?? new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // 30 days ago
      const endDate = input.endDate ?? new Date();

      const pageViews = this.pageViewRepository
        ? (await this.pageViewRepository.findByDateRange(startDate, endDate)).length
        : 0;

      // Note: additional metrics require dedicated repositories / event sources.
      const uniqueVisitors = 0;
      const averageSessionDuration = 0;
      const bounceRate = 0;

      const resultModel: GetAnalyticsMetricsOutput = {
        pageViews,
        uniqueVisitors,
        averageSessionDuration,
        bounceRate,
      };

      this.output.present(resultModel);

      this.logger.info('Analytics metrics retrieved', {
        startDate,
        endDate,
        pageViews,
        uniqueVisitors,
      });

      return Result.ok(undefined);
    } catch (error) {
      const err = error as Error;
      this.logger.error('Failed to get analytics metrics', err, { input });
      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message: err.message ?? 'Failed to get analytics metrics' },
      });
    }
  }
}