package com.social.media.application.analytics.service;

import com.social.media.application.analytics.command.*;
import com.social.media.application.analytics.dto.AnalyticsResponseDto;
import com.social.media.application.analytics.handler.*;
import com.social.media.application.analytics.query.*;
import com.social.media.domain.analytics.valueobject.AnalyticsId;
import com.social.media.domain.analytics.valueobject.ReportType;
import com.social.media.domain.analytics.valueobject.MetricType;
import com.social.media.domain.company.valueobject.CompanyId;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * Application Service for Analytics Context
 * Orchestrates commands and queries through dedicated handlers
 */
@Service
public class AnalyticsApplicationService {
    
    private final CreateAnalyticsReportCommandHandler createAnalyticsReportCommandHandler;
    private final UpdateAnalyticsReportCommandHandler updateAnalyticsReportCommandHandler;
    private final RegenerateAnalyticsReportCommandHandler regenerateAnalyticsReportCommandHandler;
    private final DeleteAnalyticsReportCommandHandler deleteAnalyticsReportCommandHandler;
    private final GetAnalyticsReportByIdQueryHandler getAnalyticsReportByIdQueryHandler;
    private final GetAnalyticsReportsByCompanyQueryHandler getAnalyticsReportsByCompanyQueryHandler;
    private final GetRecentAnalyticsReportsQueryHandler getRecentAnalyticsReportsQueryHandler;
    
    public AnalyticsApplicationService(
            CreateAnalyticsReportCommandHandler createAnalyticsReportCommandHandler,
            UpdateAnalyticsReportCommandHandler updateAnalyticsReportCommandHandler,
            RegenerateAnalyticsReportCommandHandler regenerateAnalyticsReportCommandHandler,
            DeleteAnalyticsReportCommandHandler deleteAnalyticsReportCommandHandler,
            GetAnalyticsReportByIdQueryHandler getAnalyticsReportByIdQueryHandler,
            GetAnalyticsReportsByCompanyQueryHandler getAnalyticsReportsByCompanyQueryHandler,
            GetRecentAnalyticsReportsQueryHandler getRecentAnalyticsReportsQueryHandler) {
        this.createAnalyticsReportCommandHandler = createAnalyticsReportCommandHandler;
        this.updateAnalyticsReportCommandHandler = updateAnalyticsReportCommandHandler;
        this.regenerateAnalyticsReportCommandHandler = regenerateAnalyticsReportCommandHandler;
        this.deleteAnalyticsReportCommandHandler = deleteAnalyticsReportCommandHandler;
        this.getAnalyticsReportByIdQueryHandler = getAnalyticsReportByIdQueryHandler;
        this.getAnalyticsReportsByCompanyQueryHandler = getAnalyticsReportsByCompanyQueryHandler;
        this.getRecentAnalyticsReportsQueryHandler = getRecentAnalyticsReportsQueryHandler;
    }
    
    // Command Operations
    
    /**
     * Create a new analytics report
     */
    public AnalyticsResponseDto createAnalyticsReport(CreateAnalyticsReportCommand command) {
        return createAnalyticsReportCommandHandler.handle(command);
    }
    
    /**
     * Update an existing analytics report
     */
    public AnalyticsResponseDto updateAnalyticsReport(UpdateAnalyticsReportCommand command) {
        return updateAnalyticsReportCommandHandler.handle(command);
    }
    
    /**
     * Regenerate analytics report data
     */
    public AnalyticsResponseDto regenerateAnalyticsReport(RegenerateAnalyticsReportCommand command) {
        return regenerateAnalyticsReportCommandHandler.handle(command);
    }
    
    /**
     * Delete analytics report permanently
     */
    public void deleteAnalyticsReport(DeleteAnalyticsReportCommand command) {
        deleteAnalyticsReportCommandHandler.handle(command);
    }
    
    // Query Operations
    
    /**
     * Get analytics report by ID
     */
    public AnalyticsResponseDto getAnalyticsReportById(String analyticsId) {
        GetAnalyticsReportByIdQuery query = new GetAnalyticsReportByIdQuery(AnalyticsId.of(analyticsId));
        return getAnalyticsReportByIdQueryHandler.handle(query);
    }
    
    /**
     * Get analytics reports by company with optional filtering
     */
    public List<AnalyticsResponseDto> getAnalyticsReportsByCompany(String companyId, ReportType reportType, 
                                                                  MetricType metricType, LocalDateTime periodStart,
                                                                  LocalDateTime periodEnd, int page, int size) {
        GetAnalyticsReportsByCompanyQuery query = new GetAnalyticsReportsByCompanyQuery(
            CompanyId.of(Long.valueOf(companyId)),
            reportType,
            metricType,
            periodStart,
            periodEnd,
            page,
            size
        );
        return getAnalyticsReportsByCompanyQueryHandler.handle(query);
    }
    
    /**
     * Get recent analytics reports
     */
    public List<AnalyticsResponseDto> getRecentAnalyticsReports(String companyId, ReportType reportType, 
                                                               int hoursThreshold, int page, int size) {
        GetRecentAnalyticsReportsQuery query = new GetRecentAnalyticsReportsQuery(
            companyId != null ? CompanyId.of(Long.valueOf(companyId)) : null,
            reportType,
            hoursThreshold,
            page,
            size
        );
        return getRecentAnalyticsReportsQueryHandler.handle(query);
    }
    
    // Convenience Methods
    
    /**
     * Create analytics report with fluent interface
     */
    public AnalyticsResponseDto createReport(String companyId, ReportType reportType, MetricType metricType,
                                            LocalDateTime periodStart, LocalDateTime periodEnd, String title,
                                            String description, Map<String, Object> initialData) {
        CreateAnalyticsReportCommand command = new CreateAnalyticsReportCommand(
            companyId, reportType, metricType, periodStart, periodEnd, title, description, initialData
        );
        return createAnalyticsReport(command);
    }
    
    /**
     * Update analytics report with fluent interface
     */
    public AnalyticsResponseDto updateReport(String analyticsId, String description, Map<String, Object> data) {
        UpdateAnalyticsReportCommand command = new UpdateAnalyticsReportCommand(analyticsId, description, data);
        return updateAnalyticsReport(command);
    }
    
    /**
     * Regenerate analytics report with fluent interface
     */
    public AnalyticsResponseDto regenerateReport(String analyticsId, boolean forceRegeneration) {
        RegenerateAnalyticsReportCommand command = new RegenerateAnalyticsReportCommand(analyticsId, forceRegeneration);
        return regenerateAnalyticsReport(command);
    }
    
    /**
     * Delete analytics report with fluent interface
     */
    public void deleteReport(String analyticsId) {
        DeleteAnalyticsReportCommand command = new DeleteAnalyticsReportCommand(analyticsId);
        deleteAnalyticsReport(command);
    }
}

