<?php

declare(strict_types=1);

namespace App\Application\Admin\Analytics;

use App\Application\Admin\Service\AdminLayoutProcessor;
use App\Application\Analytics\Service\AnalyticsDashboardService;
use App\Application\Analytics\Service\AnalyticsRealTimeService;
use App\Application\Analytics\Service\AnalyticsReportService;
use App\Framework\Analytics\AnalyticsCategory;
use App\Framework\Analytics\AnalyticsCollector;
use App\Framework\Analytics\Storage\AnalyticsStorage;
use App\Framework\Attributes\Route;
use App\Framework\Auth\Auth;
use App\Framework\Http\Method;
use App\Framework\Http\Status;
use App\Framework\Meta\MetaData;
use App\Framework\Router\AdminRoutes;
use App\Framework\Router\Result\JsonResult;
use App\Framework\Router\Result\ViewResult;

final class AnalyticsController
{
    public function __construct(
        private AdminLayoutProcessor $layoutProcessor,
        private AnalyticsDashboardService $dashboardService,
        private AnalyticsStorage $storage,
        private AnalyticsReportService $reportService,
        private AnalyticsRealTimeService $realTimeService,
        private AnalyticsCollector $analyticsCollector,
    ) {
    }

    #[Auth]
    #[Route(path: '/admin/analytics', method: Method::GET, name: AdminRoutes::ANALYTICS_DASHBOARD)]
    public function dashboard(): ViewResult
    {
        // Use mock data for now since analytics services may not be fully configured
        $overview = [
            'today_page_views' => 0,
            'week_page_views' => 0,
            'month_page_views' => 0,
            'today_visitors' => 0,
            'week_visitors' => 0,
            'month_visitors' => 0,
            'avg_load_time' => 'N/A',
            'bounce_rate' => 'N/A',
            'avg_session_duration' => 'N/A',
        ];
        $topPages = [];
        $trafficSources = [];

        $data = [
            'title' => 'Analytics Dashboard',
            'today_page_views' => $overview['today_page_views'] ?? 0,
            'week_page_views' => $overview['week_page_views'] ?? 0,
            'month_page_views' => $overview['month_page_views'] ?? 0,
            'today_visitors' => $overview['today_visitors'] ?? 0,
            'week_visitors' => $overview['week_visitors'] ?? 0,
            'month_visitors' => $overview['month_visitors'] ?? 0,
            'avg_load_time' => $overview['avg_load_time'] ?? 'N/A',
            'bounce_rate' => $overview['bounce_rate'] ?? 'N/A',
            'avg_session_duration' => $overview['avg_session_duration'] ?? 'N/A',
            'top_pages' => $topPages,
            'traffic_sources' => $trafficSources,
            'last_update' => date('Y-m-d H:i:s'),
        ];

        $finalData = $this->layoutProcessor->processLayoutFromArray($data);

        return new ViewResult(
            template: 'analytics-dashboard',
            metaData: new MetaData('Analytics Dashboard', 'Website Analytics and User Behavior'),
            data: $finalData
        );
    }

    #[Route(path: '/admin/analytics/api/overview', method: Method::GET)]
    public function getOverview(): JsonResult
    {
        try {
            $endDate = $_GET['end_date'] ?? date('Y-m-d');
            $startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-30 days'));

            // Calculate days between dates
            $days = max(1, (strtotime($endDate) - strtotime($startDate)) / 86400 + 1);

            $overview = $this->dashboardService->getOverview($startDate, $endDate);

            return new JsonResult([
                'success' => true,
                'data' => $overview,
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => (int)$days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/timeseries', method: Method::GET)]
    public function getTimeSeries(): JsonResult
    {
        try {
            $metric = $_GET['metric'] ?? 'page_views';
            $period = $_GET['period'] ?? 'day';
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $timeSeries = $this->storage->getTimeSeries($metric, $startDate, $endDate, $period);

            return new JsonResult([
                'success' => true,
                'data' => $timeSeries,
                'metric' => $metric,
                'period' => $period,
                'range' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/top-pages', method: Method::GET)]
    public function getTopPages(): JsonResult
    {
        try {
            $limit = (int) ($_GET['limit'] ?? 10);
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $topPages = $this->dashboardService->getTopPages($startDate, $endDate, $limit);

            return new JsonResult([
                'success' => true,
                'data' => $topPages,
                'limit' => $limit,
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/traffic-sources', method: Method::GET)]
    public function getTrafficSources(): JsonResult
    {
        try {
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $sources = $this->dashboardService->getTrafficSources($startDate, $endDate);

            return new JsonResult([
                'success' => true,
                'data' => $sources,
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/user-behavior', method: Method::GET)]
    public function getUserBehavior(): JsonResult
    {
        try {
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $behavior = $this->reportService->getUserBehavior($startDate, $endDate);

            return new JsonResult([
                'success' => true,
                'data' => $behavior,
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/business-metrics', method: Method::GET)]
    public function getBusinessMetrics(): JsonResult
    {
        try {
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $metrics = $this->reportService->getBusinessMetrics($startDate, $endDate);

            return new JsonResult([
                'success' => true,
                'data' => $metrics,
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/real-time', method: Method::GET)]
    public function getRealTimeData(): JsonResult
    {
        try {
            $realTime = $this->realTimeService->getRealTimeData();

            return new JsonResult([
                'success' => true,
                'data' => $realTime,
                'timestamp' => time(),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/events', method: Method::GET)]
    public function getEvents(): JsonResult
    {
        try {
            $category = $_GET['category'] ?? null;
            $limit = (int) ($_GET['limit'] ?? 100);
            $offset = (int) ($_GET['offset'] ?? 0);
            $days = (int) ($_GET['days'] ?? 7);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $categoryFilter = $category ? AnalyticsCategory::tryFrom($category) : null;

            $events = $this->reportService->getEvents($startDate, $endDate, $categoryFilter, $limit, $offset);
            $total = $this->reportService->getEventsCount($startDate, $endDate, $categoryFilter);

            return new JsonResult([
                'success' => true,
                'data' => $events,
                'pagination' => [
                    'limit' => $limit,
                    'offset' => $offset,
                    'total' => $total,
                    'has_more' => ($offset + $limit) < $total,
                ],
                'filter' => [
                    'category' => $category,
                    'start' => $startDate,
                    'end' => $endDate,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/export', method: Method::GET)]
    public function exportData(): JsonResult
    {
        try {
            $format = $_GET['format'] ?? 'json';
            $category = $_GET['category'] ?? null;
            $days = (int) ($_GET['days'] ?? 30);

            $endDate = date('Y-m-d');
            $startDate = date('Y-m-d', strtotime("-{$days} days"));

            $categoryFilter = $category ? AnalyticsCategory::tryFrom($category) : null;

            $data = $this->reportService->exportData($startDate, $endDate, $categoryFilter, $format);

            return new JsonResult([
                'success' => true,
                'data' => $data,
                'format' => $format,
                'exported_at' => date('Y-m-d H:i:s'),
                'period' => [
                    'start' => $startDate,
                    'end' => $endDate,
                    'days' => $days,
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }

    #[Route(path: '/admin/analytics/api/track', method: Method::POST)]
    public function trackEvent(): JsonResult
    {
        try {
            $action = $_POST['action'] ?? null;
            $category = $_POST['category'] ?? 'user_behavior';
            $properties = json_decode($_POST['properties'] ?? '{}', true);

            if (! $action) {
                return new JsonResult([
                    'success' => false,
                    'error' => 'Action is required',
                ], Status::from(400));
            }

            $categoryEnum = AnalyticsCategory::tryFrom($category);
            if (! $categoryEnum) {
                return new JsonResult([
                    'success' => false,
                    'error' => 'Invalid category',
                ], Status::from(400));
            }

            $this->analyticsCollector->trackAction($action, $categoryEnum, $properties);

            return new JsonResult([
                'success' => true,
                'message' => 'Event tracked successfully',
                'tracked_at' => date('Y-m-d H:i:s'),
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::from(500));
        }
    }
}
