<?php

namespace Modules\LandingPage\Services;

use Google\Analytics\Data\V1beta\BetaAnalyticsDataClient;
use Google\Analytics\Data\V1beta\DateRange;
use Google\Analytics\Data\V1beta\Dimension;
use Google\Analytics\Data\V1beta\Metric;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class GoogleAnalyticsService
{
    protected ?BetaAnalyticsDataClient $client = null;
    protected ?string $propertyId = null;
    protected bool $isEnabled = false;

    public function __construct()
    {
        $this->isEnabled = (bool) setting('google_analytics_enable_tracking', false);
        $credentialsPath = setting('google_analytics_credentials_path');
        $this->propertyId = setting('google_analytics_property_id');

        if ($this->isEnabled && $this->propertyId && $credentialsPath && file_exists($credentialsPath)) {
            try {
                $this->client = new BetaAnalyticsDataClient([
                    'credentials' => $credentialsPath,
                ]);
            } catch (\Exception $e) {
                Log::error('Google Analytics Service Initialization Error: ' . $e->getMessage());
                $this->client = null;
                $this->isEnabled = false;
            }
        } else {
            if ($this->isEnabled && (!$this->propertyId || !$credentialsPath || !file_exists($credentialsPath))) {
                Log::warning('Google Analytics Service is enabled but not properly configured (Property ID or Credentials Path missing/invalid).');
                $this->isEnabled = false;
            }
        }
    }

    private function runReport(array $dimensions, array $metrics, string $startDate = '7daysAgo', string $endDate = 'today', int $limit = 10, array $orderBy = [])
    {
        if (!$this->client || !$this->isEnabled) {
            return null;
        }

        $cacheKey = 'ga_report_' . md5(json_encode(func_get_args()) . $this->propertyId);
        $cacheDuration = now()->addHours(1); // Cache for 1 hour

        return Cache::remember($cacheKey, $cacheDuration, function () use ($dimensions, $metrics, $startDate, $endDate, $limit, $orderBy) {
            try {
                $dimensionObjects = [];
                foreach ($dimensions as $dim) {
                    $dimensionObjects[] = new Dimension(['name' => $dim]);
                }

                $metricObjects = [];
                foreach ($metrics as $met) {
                    $metricObjects[] = new Metric(['name' => $met]);
                }

                $orderBys = [];
                if (!empty($orderBy)) {
                    foreach($orderBy as $ob) {
                         $orderBys[] = new \Google\Analytics\Data\V1beta\OrderBy([
                            'metric' => new \Google\Analytics\Data\V1beta\OrderBy\MetricOrderBy(['metric_name' => $ob['metricName']]),
                            'desc' => $ob['desc'] ?? true,
                        ]);
                    }
                }


                $response = $this->client->runReport([
                    'property' => 'properties/' . $this->propertyId,
                    'dateRanges' => [
                        new DateRange([
                            'start_date' => $startDate,
                            'end_date' => $endDate,
                        ]),
                    ],
                    'dimensions' => $dimensionObjects,
                    'metrics' => $metricObjects,
                    'limit' => $limit,
                    'orderBys' => $orderBys,
                ]);
                return $response;
            } catch (\Exception $e) {
                Log::error('Google Analytics API Error: ' . $e->getMessage());
                return null;
            }
        });
    }

    public function getBasicStats(string $startDate = '7daysAgo', string $endDate = 'today')
    {
        if (!$this->isEnabled) return ['users' => 0, 'pageViews' => 0, 'sessions' => 0];

        $response = $this->runReport(
            [], // No dimensions for total aggregates
            ['activeUsers', 'screenPageViews', 'sessions']
        );

        $users = 0;
        $pageViews = 0;
        $sessions = 0;

        if ($response) {
            foreach ($response->getRows() as $row) {
                // For aggregate queries with no dimensions, there's usually one row or metrics are directly accessible
                // Depending on API version and query structure, access might differ.
                // This assumes metrics are summed up if multiple rows (though unlikely for this query)
                // or are in the first row.
                $users += (int) $row->getMetricValues()[0]->getValue(); // activeUsers
                $pageViews += (int) $row->getMetricValues()[1]->getValue(); // screenPageViews
                $sessions += (int) $row->getMetricValues()[2]->getValue(); // sessions
            }
        }
         // If no rows, but totals are available (GA4 sometimes returns totals separately)
        if ($response && $response->getTotals()->getMetricValues()->count() > 0) {
            $users = (int) $response->getTotals()->getMetricValues()[0]->getValue();
            $pageViews = (int) $response->getTotals()->getMetricValues()[1]->getValue();
            $sessions = (int) $response->getTotals()->getMetricValues()[2]->getValue();
        }


        return [
            'users' => $users,
            'pageViews' => $pageViews,
            'sessions' => $sessions,
        ];
    }

    public function getTopPages(string $startDate = '7daysAgo', string $endDate = 'today', int $limit = 5)
    {
        if (!$this->isEnabled) return [];

        $response = $this->runReport(
            ['pagePath'],
            ['screenPageViews'],
            $startDate,
            $endDate,
            $limit,
            [['metricName' => 'screenPageViews', 'desc' => true]]
        );

        $pages = [];
        if ($response) {
            foreach ($response->getRows() as $row) {
                $pages[] = [
                    'path' => $row->getDimensionValues()[0]->getValue(),
                    'views' => (int) $row->getMetricValues()[0]->getValue(),
                ];
            }
        }
        return $pages;
    }
}
