<?php
namespace App\Services;

use App\Repositories\KpiRepository;
use App\Repositories\UserRepository;
use App\Utils\Logger;

class KpiService
{
    private $kpiRepo;
    private $userRepo;
    private $kpiCache;

    public function __construct(
        KpiRepository $kpiRepo,
        UserRepository $userRepo,
        $kpiCache = null
    ) {
        $this->kpiRepo = $kpiRepo;
        $this->userRepo = $userRepo;
        $this->kpiCache = $kpiCache;
    }

    /**
     * محاسبه تمام شاخص‌های KPI
     * پشتیبانی ۳ حالت:
     * 1. Admin بدون فیلتر: KPI سازمانی (global)
     * 2. Admin با فیلتر user_id: KPI آن کاربر خاص
     * 3. Agent بدون فیلتر: KPI خودش
     */
    public function calculateKPI(array $filters): array
    {
        Logger::logInfo('KPI calculation started', [
            'filters' => $filters,
            'user_role' => $_SESSION['role'] ?? 'unknown',
            'session_didar_id' => $_SESSION['didar_id'] ?? null
        ]);

        $kpi = [];

        $context = $this->resolveKpiContext($filters);
        $userRole = $context['user_role'];
        $sessionDidarId = $context['session_didar_id'];
        $isGlobalKpi = $context['is_global_kpi'];
        $isUserSpecificKpi = $context['is_user_specific_kpi'];
        $isSelfKpi = $context['is_self_kpi'];
        $hasAnyUserFilter = $context['has_any_user_filter'];

        Logger::logInfo('KPI Mode Determined', [
            'is_global_kpi' => $isGlobalKpi,
            'is_user_specific_kpi' => $isUserSpecificKpi,
            'is_self_kpi' => $isSelfKpi,
            'has_user_id_filter' => $context['has_user_id_filter'],
            'has_owner_filter' => $context['has_owner_filter'],
            'filter_user_id' => $filters['user_id'] ?? null,
            'filter_owner_id' => $filters['owner_didar_id'] ?? null,
            'session_didar_id' => $sessionDidarId
        ]);

        // اگر CRM Specialist بود، خطا بده
        if ($userRole === 'crm_specialist') {
            Logger::logWarning('CRM Specialist tried to access KPI - Access Denied');
            throw new \Exception('دسترسی محدود');
        }

        $context['repo_filters']['_kpi_activity_rev'] = 1;
        if ($cached = $this->getCachedKpiPayload('kpi_dashboard', $context['repo_filters'])) {
            return $cached;
        }

        // به‌روزرسانی فیلترها برای Repository
        $repoFilters = $context['repo_filters'];

        // KPI Dashboard باید با منطق Performance Dashboard هم‌راستا باشد.
        // برای شاخص‌های مشترک از همان خروجی repository در getPerformanceDashboardData استفاده می‌کنیم.
        $performanceBase = $this->kpiRepo->getPerformanceDashboardData($repoFilters);
        $summary = $performanceBase['summary_cards'] ?? [];
        $raw = $performanceBase['raw'] ?? [];
        $charts = $performanceBase['charts'] ?? [];

        // 1. فروش (هم‌راستا با performance summary)
        $sales = [
            'deal_count' => (int)($summary['with_sales_deals_count'] ?? 0),
            'total_collected_amount' => (float)($summary['total_sales_amount'] ?? 0),
            'total_contract_amount' => (float)($summary['total_contract_amount'] ?? 0),
        ];
        $kpi['sales'] = $sales;

        // 2. تسویه کامل
        $settled = [
            'deal_count' => (int)($summary['settled_count'] ?? 0),
            'total_amount' => (float)($summary['settled_amount'] ?? 0),
            'total_collected_amount' => (float)($summary['settled_collected_amount'] ?? 0),
        ];
        $kpi['settled'] = $settled;

        // 3. مانده حساب
        $outstanding = [
            'deal_count' => (int)($summary['outstanding_count'] ?? 0),
            'outstanding_amount' => (float)($summary['outstanding_amount'] ?? 0),
            'total_contract_amount' => (float)($summary['outstanding_contract_amount'] ?? 0),
            'total_collected' => (float)($summary['outstanding_collected_amount'] ?? 0),
        ];
        $kpi['outstanding'] = $outstanding;

        // 4. فروش ناموفق (لیست ردیفی از raw)
        $lost = $raw['lost_sales'] ?? $this->kpiRepo->getLostSales($repoFilters);
        $kpi['lost_sales'] = $lost;

        // 4.5. فروش موفق (Won) - کارت جدید KPI هم‌راستا با performance
        $kpi['won_sales'] = [
            'deal_count' => (int)($summary['won_count'] ?? 0),
            'total_amount' => (float)($summary['won_amount'] ?? 0),
        ];

        // 5. فروش جاری
        $openPipeline = [
            'deal_count' => (int)($summary['open_pipeline_count'] ?? 0),
            'total_potential_amount' => (float)($summary['open_pipeline_amount'] ?? 0),
        ];
        $kpi['open_pipeline'] = $openPipeline;

        // 5.5. معاملات بدون پرداخت
        $dealsWithoutPayments = [
            'deal_count' => (int)($summary['without_payment_count'] ?? 0),
            'total_potential_amount' => (float)($summary['without_payment_amount'] ?? 0),
        ];
        $kpi['deals_without_payments'] = $dealsWithoutPayments;

        // 5.6. تعداد فروش هر محصول
        $kpi['product_sales'] = $raw['product_sales'] ?? $this->kpiRepo->getProductSalesCounts($repoFilters);

        // 6. نرخ تبدیل‌ها
        $dealConversion = [
            'total_deals' => (int)($summary['deal_conversion_total_deals'] ?? 0),
            'conversion_rate' => (float)($summary['deal_conversion_rate'] ?? 0),
            'non_conversion_rate' => (float)($summary['deal_non_conversion_rate'] ?? 0),
        ];
        $kpi['deal_conversion'] = $dealConversion;

        $leadConversion = [
            'total_new_leads' => (int)($summary['lead_total_new'] ?? 0),
            'converted_leads' => (int)($summary['lead_converted'] ?? 0),
            'conversion_rate' => (float)($summary['lead_conversion_rate'] ?? 0),
            'non_conversion_rate' => (float)($summary['lead_non_conversion_rate'] ?? 0),
        ];
        $kpi['lead_conversion'] = $leadConversion;

        // 7. میانگین زمان تبدیل
        $timeToConversion = [
            'avg_conversion_days' => (float)($summary['avg_conversion_days'] ?? 0),
        ];
        $kpi['time_to_conversion'] = $timeToConversion;

        // 8. فروش روزانه / نمودارها
        $dailySales = $charts['daily_sales'] ?? $this->kpiRepo->getDailySales($repoFilters);
        $kpi['daily_sales'] = $dailySales;

        // 9. KPIهای عملیاتی روزانه (کلی + تفکیک کارشناس)
        $kpi['daily_operational'] = $raw['daily_operational'] ?? $this->kpiRepo->getDailyOperationalKpis($repoFilters);

        // 10. جداول پیشرفته KPI (از raw performance تا کاملاً هم‌منطق باشند)
        $kpi['advanced_tables'] = $raw['advanced_tables'] ?? $this->buildAdvancedKpiTables($repoFilters);

        // 9. محاسبه درصد تحقق هدف
        // فقط اگر فیلتر user_id داشت (برای KPI آن کاربر خاص) یا اگر حالت Agent بود
        if ($hasAnyUserFilter || $isSelfKpi) {
            $kpi['target_achievement'] = $this->calculateTargetAchievement($filters, $sales, $repoFilters);
        } else {
            // بدون فیلتر کاربر، هدف سازمانی وجود ندارد
            $kpi['target_achievement'] = [
                'has_target' => false,
                'target_amount' => 0,
                'actual_amount' => $sales['total_collected_amount'] ?? 0,
                'achievement_percent' => 0,
                'target_deal_count' => 0,
                'actual_deal_count' => $sales['deal_count'] ?? 0,
                'deal_achievement_percent' => 0
            ];
        }

        // افزودن حالت KPI به پاسخ
        $kpi['kpi_mode'] = $isGlobalKpi ? 'global' : ($isUserSpecificKpi ? 'user_specific' : 'self');

        Logger::logInfo('KPI calculation completed', [
            'kpi_mode' => $kpi['kpi_mode'],
            'kpi_keys' => array_keys($kpi)
        ]);

        $this->setCachedKpiPayload('kpi_dashboard', $context['repo_filters'], $kpi);
        return $kpi;
    }

    /**
     * خروجی دیباگ KPI برای تحلیل اختلافات
     * این متد همان منطق calculateKPI را با جزئیات هر کامپوننت برمی‌گرداند.
     */
    public function buildDebugSnapshot(array $filters): array
    {
        $context = $this->resolveKpiContext($filters);
        $repoFilters = $context['repo_filters'];

        $sales = $this->kpiRepo->getSales($repoFilters);
        $settled = $this->kpiRepo->getSettledDeals($repoFilters);
        $outstanding = $this->kpiRepo->getOutstandingBalance($repoFilters);
        $lost = $this->kpiRepo->getLostSales($repoFilters);
        $openPipeline = $this->kpiRepo->getOpenPipeline($repoFilters);
        $dealsWithoutPayments = $this->kpiRepo->getDealsWithoutPayments($repoFilters);
        $productSales = $this->kpiRepo->getProductSalesCounts($repoFilters);
        $dealConversion = $this->kpiRepo->getDealConversionRate($repoFilters);
        $leadConversion = $this->kpiRepo->getLeadConversionRate($repoFilters);
        $timeToConversion = $this->kpiRepo->getTimeToConversion($repoFilters);
        $dailySales = $this->kpiRepo->getDailySales($repoFilters);
        $dailyOperational = $this->kpiRepo->getDailyOperationalKpis($repoFilters);
        $advancedTables = $this->buildAdvancedKpiTables($repoFilters);

        return [
            'generated_at' => date('Y-m-d H:i:s'),
            'context' => [
                'user_role' => $context['user_role'],
                'session_didar_id' => $context['session_didar_id'],
                'is_global_kpi' => $context['is_global_kpi'],
                'is_user_specific_kpi' => $context['is_user_specific_kpi'],
                'is_self_kpi' => $context['is_self_kpi'],
                'has_user_id_filter' => $context['has_user_id_filter'],
                'has_owner_filter' => $context['has_owner_filter'],
            ],
            'filters' => [
                'input_filters' => $filters,
                'repo_filters' => $repoFilters,
            ],
            'components' => [
                'sales' => $sales,
                'settled' => $settled,
                'outstanding' => $outstanding,
                'lost_sales' => $lost,
                'open_pipeline' => $openPipeline,
                'deals_without_payments' => $dealsWithoutPayments,
                'product_sales' => $productSales,
                'deal_conversion' => $dealConversion,
                'lead_conversion' => $leadConversion,
                'time_to_conversion' => $timeToConversion,
                'daily_sales' => $dailySales,
                'daily_operational' => $dailyOperational,
                'advanced_tables' => $advancedTables,
            ],
        ];
    }

    /**
     * نرمال‌سازی context و فیلترهای KPI برای اطمینان از یکسان بودن محاسبات
     */
    private function resolveKpiContext(array $filters): array
    {
        $userRole = $_SESSION['role'] ?? '';
        $sessionDidarId = $_SESSION['didar_id'] ?? '';
        $isAgent = ($userRole === 'agent');
        $isAdmin = ($userRole === 'admin' || $userRole === 'system');

        $hasUserIdFilter = !empty($filters['user_id']) && $filters['user_id'] !== null;
        $hasOwnerFilter = !empty($filters['owner_didar_id']);
        $hasAnyUserFilter = $hasUserIdFilter || $hasOwnerFilter;

        $isGlobalKpi = $isAdmin && !$hasAnyUserFilter;
        $isUserSpecificKpi = $isAdmin && $hasAnyUserFilter;
        $isSelfKpi = $isAgent && !$hasAnyUserFilter;

        $repoFilters = $filters;
        unset($repoFilters['user_id']);
        $repoFilters = $this->normalizeKpiCalculationCriteria($repoFilters);

        if ($isSelfKpi && !$hasAnyUserFilter) {
            $repoFilters['owner_didar_id'] = $sessionDidarId;
        }

        if ($isGlobalKpi) {
            $repoFilters['owner_didar_id'] = null;
        }

        return [
            'user_role' => $userRole,
            'session_didar_id' => $sessionDidarId,
            'is_global_kpi' => $isGlobalKpi,
            'is_user_specific_kpi' => $isUserSpecificKpi,
            'is_self_kpi' => $isSelfKpi,
            'has_user_id_filter' => $hasUserIdFilter,
            'has_owner_filter' => $hasOwnerFilter,
            'has_any_user_filter' => $hasAnyUserFilter,
            'repo_filters' => $repoFilters,
        ];
    }

    private function normalizeKpiCalculationCriteria(array $filters): array
    {
        $allowedDateBases = ['ui_payment_date', 'db_payment_date', 'system_created_at'];
        $allowedCountRules = ['all_payments', 'first_payment_only'];
        $allowedStatusScopes = ['confirmed_only', 'all_statuses'];
        $allowedLegacyScopes = ['exclude', 'only', 'all'];

        $filters['kpi_sales_date_basis'] = in_array(($filters['kpi_sales_date_basis'] ?? ''), $allowedDateBases, true)
            ? $filters['kpi_sales_date_basis']
            : 'ui_payment_date';
        $filters['kpi_sales_count_rule'] = in_array(($filters['kpi_sales_count_rule'] ?? ''), $allowedCountRules, true)
            ? $filters['kpi_sales_count_rule']
            : 'first_payment_only';

        $filters['kpi_payment_date_basis'] = in_array(($filters['kpi_payment_date_basis'] ?? ''), $allowedDateBases, true)
            ? $filters['kpi_payment_date_basis']
            : 'ui_payment_date';
        $filters['kpi_payment_count_rule'] = in_array(($filters['kpi_payment_count_rule'] ?? ''), $allowedCountRules, true)
            ? $filters['kpi_payment_count_rule']
            : 'all_payments';

        $filters['kpi_payment_status_scope'] = in_array(($filters['kpi_payment_status_scope'] ?? ''), $allowedStatusScopes, true)
            ? $filters['kpi_payment_status_scope']
            : 'confirmed_only';
        $filters['legacy_deal_scope'] = in_array(($filters['legacy_deal_scope'] ?? ''), $allowedLegacyScopes, true)
            ? $filters['legacy_deal_scope']
            : 'exclude';

        return $filters;
    }

    /**
     * محاسبه درصد تحقق هدف
     * پشتیبانی ۲ حالت:
     * 1. Admin با فیلتر user_id: هدف آن کاربر
     * 2. Agent: هدف کاربر خودش
     */
    private function calculateTargetAchievement(array $filters, array $sales, array $repoFilters): array
    {
        // پیدا کردن user_id از owner_didar_id
        $userId = null;
        if (!empty($filters['owner_didar_id'])) {
            $user = $this->userRepo->findByDidarId($filters['owner_didar_id']);
            $userId = $user ? $user->id : null;
        }

        // اگر کاربر پیدا نشد، هدف وجود ندارد
        if (!$userId) {
            return [
                'has_target' => false,
                'target_amount' => 0,
                'actual_amount' => $sales['total_collected_amount'] ?? 0,
                'achievement_percent' => 0,
                'target_deal_count' => 0,
                'actual_deal_count' => $sales['deal_count'] ?? 0,
                'deal_achievement_percent' => 0
            ];
        }

        // پیدا کردن سال و ماه از فیلترها
        $dateFrom = !empty($filters['date_from']) ? new \DateTime($filters['date_from']) : new \DateTime();
        $year = (int) $dateFrom->format('Y');
        $month = (int) $dateFrom->format('m');

        // دریافت هدف
        $target = $this->kpiRepo->getKpiTarget($userId, $year, $month);

        if (!$target) {
            return [
                'has_target' => false,
                'target_amount' => 0,
                'actual_amount' => $sales['total_collected_amount'] ?? 0,
                'achievement_percent' => 0,
                'target_deal_count' => 0,
                'actual_deal_count' => $sales['deal_count'] ?? 0,
                'deal_achievement_percent' => 0
            ];
        }

        $actualAmount = floatval($sales['total_collected_amount'] ?? 0);
        $targetAmount = floatval($target['target_amount']);
        $achievementPercent = $targetAmount > 0 ? round(($actualAmount / $targetAmount) * 100, 2) : 0;

        $actualDealCount = intval($sales['deal_count'] ?? 0);
        $targetDealCount = intval($target['target_deal_count'] ?? 0);
        $dealAchievementPercent = $targetDealCount > 0 ? round(($actualDealCount / $targetDealCount) * 100, 2) : 0;

        return [
            'has_target' => true,
            'target_amount' => $targetAmount,
            'actual_amount' => $actualAmount,
            'achievement_percent' => $achievementPercent,
            'target_deal_count' => $targetDealCount,
            'actual_deal_count' => $actualDealCount,
            'deal_achievement_percent' => $dealAchievementPercent
        ];
    }

    /**
     * ثبت هدف جدید (Admin فقط)
     */
    public function setKpiTarget(int $userId, int $year, int $month, float $targetAmount, int $targetDealCount = 0): bool
    {
        try {
            return $this->kpiRepo->upsertKpiTarget($userId, $year, $month, $targetAmount, $targetDealCount);
        } catch (\Exception $e) {
            Logger::logError('Failed to set KPI target', $e, [
                'user_id' => $userId,
                'year' => $year,
                'month' => $month
            ]);
            return false;
        }
    }

    /**
     * دریافت لیست تمام اهداف KPI (فقط Admin)
     */
    public function getAllKpiTargets(): array
    {
        return $this->kpiRepo->getAllKpiTargets();
    }

    /**
     * دریافت جزئیات معاملات KPI (Admin فقط)
     */
    public function getKpiDealDetails(array $filters): array
    {
        return $this->kpiRepo->getKpiDealDetails($filters);
    }

    /**
     * دریافت Drill-down KPI برای سلول‌های جداول تحلیلی
     */
    public function getKpiDrilldown(array $filters, string $tableId, string $metricKey, array $rowContext): array
    {
        return $this->kpiRepo->getKpiDrilldown($filters, $tableId, $metricKey, $rowContext);
    }

    /**
     * داشبورد عملکرد نرمال‌شده برای UI جدید
     */
    public function calculatePerformanceDashboard(array $filters): array
    {
        $context = $this->resolveKpiContext($filters);

        if (($context['user_role'] ?? '') === 'crm_specialist' || ($context['user_role'] ?? '') === 'accountant') {
            throw new \Exception('دسترسی محدود');
        }

        $repoFilters = $context['repo_filters'];
        $repoFilters['_perf_phase1_features_rev'] = 1;
        $repoFilters['_perf_activity_rev'] = 1;
        $repoFilters['_perf_disable_chart_deal_status'] = 1;
        $repoFilters['_perf_disable_chart_conversion_funnel'] = 1;
        $repoFilters['_perf_skip_activity_tables'] = (($context['user_role'] ?? '') !== 'admin') ? 1 : 0;
        $context['repo_filters'] = $repoFilters;

        if ($cached = $this->getCachedKpiPayload('performance_dashboard', $context['repo_filters'])) {
            return $cached;
        }

        $dashboard = $this->kpiRepo->getPerformanceDashboardData($context['repo_filters']);
        if (!empty($context['repo_filters']['_perf_disable_chart_deal_status'])) {
            unset($dashboard['charts']['deal_status_breakdown']);
        }

        $sales = [
            'total_collected_amount' => (float)($dashboard['summary_cards']['total_sales_amount'] ?? 0),
            'deal_count' => (int)($dashboard['summary_cards']['with_sales_deals_count'] ?? 0)
        ];
        $target = [
            'has_target' => false,
            'target_amount' => 0,
            'actual_amount' => $sales['total_collected_amount'],
            'achievement_percent' => 0,
            'target_deal_count' => 0,
            'actual_deal_count' => $sales['deal_count'],
            'deal_achievement_percent' => 0
        ];

        $hasAnyUserFilter = $context['has_any_user_filter'] ?? false;
        $isSelfKpi = $context['is_self_kpi'] ?? false;
        if ($hasAnyUserFilter || $isSelfKpi) {
            $target = $this->calculateTargetAchievement($context['repo_filters'], $sales, $context['repo_filters']);
        }

        $dashboard['summary_cards']['target_achievement_percent'] = (float)($target['achievement_percent'] ?? 0);
        $dashboard['summary_cards']['target_has_target'] = !empty($target['has_target']);
        $dashboard['summary_cards']['target_amount'] = (float)($target['target_amount'] ?? 0);
        $dashboard['summary_cards']['target_actual_amount'] = (float)($target['actual_amount'] ?? 0);
        $dashboard['summary_cards']['target_daily_amount'] = $this->calculateTargetDailyAmount(
            (string)($context['repo_filters']['date_from'] ?? ''),
            (string)($context['repo_filters']['date_to'] ?? ''),
            (float)($target['target_amount'] ?? 0)
        );

        $previous = $this->buildPreviousPeriodFilters($context['repo_filters']);
        $previousFilters = $previous['filters'];
        $previousFilters['_perf_phase1_features_rev'] = 1;
        $previousFilters['_perf_activity_rev'] = 1;
        $previousFilters['_perf_disable_chart_deal_status'] = 1;
        $previousFilters['_perf_disable_chart_conversion_funnel'] = 1;
        $previousFilters['_perf_skip_activity_tables'] = (($context['user_role'] ?? '') !== 'admin') ? 1 : 0;
        $previousDashboard = $this->kpiRepo->getPerformanceDashboardData($previousFilters);
        if (!empty($previousFilters['_perf_disable_chart_deal_status'])) {
            unset($previousDashboard['charts']['deal_status_breakdown']);
        }
        $dashboard['comparison'] = [
            'label' => $previous['label'],
            'date_from' => $previous['filters']['date_from'] ?? '',
            'date_to' => $previous['filters']['date_to'] ?? '',
            'summary' => $this->buildSummaryComparison(
                $dashboard['summary_cards'] ?? [],
                $previousDashboard['summary_cards'] ?? []
            )
        ];
        $dashboard['charts']['daily_sales_previous'] = $previousDashboard['charts']['daily_sales'] ?? [];
        $dashboard['charts']['daily_activities_previous'] = $previousDashboard['charts']['daily_activities'] ?? [];

        if (empty($context['repo_filters']['_perf_disable_chart_conversion_funnel'])) {
            $dashboard['charts']['conversion_funnel'] = [
                ['stage' => 'لید جدید', 'count' => (int)($dashboard['summary_cards']['lead_total_new'] ?? 0)],
                ['stage' => 'معامله', 'count' => (int)($dashboard['summary_cards']['deal_conversion_total_deals'] ?? 0)],
                ['stage' => 'پرداخت', 'count' => (int)($dashboard['summary_cards']['with_sales_deals_count'] ?? 0)],
                ['stage' => 'تسویه کامل', 'count' => (int)($dashboard['summary_cards']['settled_count'] ?? 0)]
            ];
        } else {
            unset($dashboard['charts']['conversion_funnel']);
        }

        $this->setCachedKpiPayload('performance_dashboard', $context['repo_filters'], $dashboard);
        return $dashboard;
    }

    public function calculatePerformanceDashboardSection(array $filters, string $section): array
    {
        $section = trim(strtolower($section));
        if ($section === '') {
            $section = 'summary';
        }

        $context = $this->resolveKpiContext($filters);
        if (($context['user_role'] ?? '') === 'crm_specialist' || ($context['user_role'] ?? '') === 'accountant') {
            throw new \Exception('دسترسی محدود');
        }

        $repoFilters = $context['repo_filters'];
        $repoFilters['_perf_phase1_features_rev'] = 1;
        $repoFilters['_perf_phase2_split_rev'] = 1;
        $repoFilters['_perf_activity_rev'] = 1;
        $repoFilters['_perf_disable_chart_deal_status'] = 1;
        $repoFilters['_perf_disable_chart_conversion_funnel'] = 1;
        $repoFilters['_perf_skip_activity_tables'] = (($context['user_role'] ?? '') !== 'admin') ? 1 : 0;

        if ($section === 'summary') {
            $repoFilters['_perf_skip_charts'] = 1;
            $repoFilters['_perf_skip_tabs'] = 1;
            $repoFilters['_perf_skip_raw'] = 1;
            $surfaceKey = 'performance_dashboard_summary';
            if ($cached = $this->getCachedKpiPayload($surfaceKey, $repoFilters)) {
                return $cached;
            }

            $dashboard = $this->kpiRepo->getPerformanceDashboardData($repoFilters);
            $sales = [
                'total_collected_amount' => (float)($dashboard['summary_cards']['total_sales_amount'] ?? 0),
                'deal_count' => (int)($dashboard['summary_cards']['with_sales_deals_count'] ?? 0)
            ];
            $target = [
                'has_target' => false,
                'target_amount' => 0,
                'actual_amount' => $sales['total_collected_amount'],
                'achievement_percent' => 0,
                'target_deal_count' => 0,
                'actual_deal_count' => $sales['deal_count'],
                'deal_achievement_percent' => 0
            ];
            $hasAnyUserFilter = $context['has_any_user_filter'] ?? false;
            $isSelfKpi = $context['is_self_kpi'] ?? false;
            if ($hasAnyUserFilter || $isSelfKpi) {
                $target = $this->calculateTargetAchievement($repoFilters, $sales, $repoFilters);
            }
            $dashboard['summary_cards']['target_achievement_percent'] = (float)($target['achievement_percent'] ?? 0);
            $dashboard['summary_cards']['target_has_target'] = !empty($target['has_target']);
            $dashboard['summary_cards']['target_amount'] = (float)($target['target_amount'] ?? 0);
            $dashboard['summary_cards']['target_actual_amount'] = (float)($target['actual_amount'] ?? 0);
            $dashboard['summary_cards']['target_daily_amount'] = $this->calculateTargetDailyAmount(
                (string)($repoFilters['date_from'] ?? ''),
                (string)($repoFilters['date_to'] ?? ''),
                (float)($target['target_amount'] ?? 0)
            );

            $previous = $this->buildPreviousPeriodFilters($repoFilters);
            $previousFilters = $previous['filters'];
            $previousFilters['_perf_phase1_features_rev'] = 1;
            $previousFilters['_perf_phase2_split_rev'] = 1;
            $previousFilters['_perf_activity_rev'] = 1;
            $previousFilters['_perf_disable_chart_deal_status'] = 1;
            $previousFilters['_perf_disable_chart_conversion_funnel'] = 1;
            $previousFilters['_perf_skip_activity_tables'] = (($context['user_role'] ?? '') !== 'admin') ? 1 : 0;
            $previousFilters['_perf_skip_charts'] = 1;
            $previousFilters['_perf_skip_tabs'] = 1;
            $previousFilters['_perf_skip_raw'] = 1;
            $previousDashboard = $this->kpiRepo->getPerformanceDashboardData($previousFilters);

            $payload = [
                'summary_cards' => $dashboard['summary_cards'] ?? [],
                'comparison' => [
                    'label' => $previous['label'],
                    'date_from' => $previous['filters']['date_from'] ?? '',
                    'date_to' => $previous['filters']['date_to'] ?? '',
                    'summary' => $this->buildSummaryComparison(
                        $dashboard['summary_cards'] ?? [],
                        $previousDashboard['summary_cards'] ?? []
                    )
                ],
            ];
            $this->setCachedKpiPayload($surfaceKey, $repoFilters, $payload);
            return $payload;
        }

        if ($section === 'charts') {
            $repoFilters['_perf_skip_tabs'] = 1;
            $repoFilters['_perf_skip_raw'] = 0;
            $surfaceKey = 'performance_dashboard_charts';
            if ($cached = $this->getCachedKpiPayload($surfaceKey, $repoFilters)) {
                return $cached;
            }
            $dashboard = $this->kpiRepo->getPerformanceDashboardData($repoFilters);
            unset($dashboard['charts']['deal_status_breakdown'], $dashboard['charts']['conversion_funnel']);

            $previous = $this->buildPreviousPeriodFilters($repoFilters);
            $previousFilters = $previous['filters'];
            $previousFilters['_perf_phase1_features_rev'] = 1;
            $previousFilters['_perf_phase2_split_rev'] = 1;
            $previousFilters['_perf_activity_rev'] = 1;
            $previousFilters['_perf_disable_chart_deal_status'] = 1;
            $previousFilters['_perf_disable_chart_conversion_funnel'] = 1;
            $previousFilters['_perf_skip_activity_tables'] = (($context['user_role'] ?? '') !== 'admin') ? 1 : 0;
            $previousFilters['_perf_skip_tabs'] = 1;
            $previousDashboard = $this->kpiRepo->getPerformanceDashboardData($previousFilters);
            $charts = $dashboard['charts'] ?? [];
            $charts['daily_sales_previous'] = $previousDashboard['charts']['daily_sales'] ?? [];
            $charts['daily_activities_previous'] = $previousDashboard['charts']['daily_activities'] ?? [];
            $this->setCachedKpiPayload($surfaceKey, $repoFilters, ['charts' => $charts]);
            return ['charts' => $charts];
        }

        if ($section === 'tabs') {
            $repoFilters['_perf_skip_charts'] = 1;
            $repoFilters['_perf_skip_raw'] = 0;
            $surfaceKey = 'performance_dashboard_tabs';
            if ($cached = $this->getCachedKpiPayload($surfaceKey, $repoFilters)) {
                return $cached;
            }
            $dashboard = $this->kpiRepo->getPerformanceDashboardData($repoFilters);
            $payload = [
                'tabs' => $dashboard['tabs'] ?? [],
                'raw' => $dashboard['raw'] ?? []
            ];
            $this->setCachedKpiPayload($surfaceKey, $repoFilters, $payload);
            return $payload;
        }

        return $this->calculatePerformanceDashboard($filters);
    }

    public function calculateKPISection(array $filters, string $section): array
    {
        $section = trim(strtolower($section));
        if ($section === '') {
            $section = 'summary';
        }
        $context = $this->resolveKpiContext($filters);
        $repoFilters = $context['repo_filters'];
        $repoFilters['_kpi_phase2_split_rev'] = 1;
        $surfaceKey = 'kpi_dashboard_section_' . $section;
        if ($cached = $this->getCachedKpiPayload($surfaceKey, $repoFilters)) {
            return $cached;
        }

        // فعلاً برای KPI از منطق کامل استفاده می‌کنیم و خروجی را slice می‌کنیم تا semantics دقیقاً ثابت بماند.
        $full = $this->calculateKPI($filters);
        $payload = [];
        if ($section === 'summary') {
            $payload = [
                'sales' => $full['sales'] ?? [],
                'settled' => $full['settled'] ?? [],
                'outstanding' => $full['outstanding'] ?? [],
                'lost_sales' => $full['lost_sales'] ?? [],
                'won_sales' => $full['won_sales'] ?? [],
                'open_pipeline' => $full['open_pipeline'] ?? [],
                'deals_without_payments' => $full['deals_without_payments'] ?? [],
                'deal_conversion' => $full['deal_conversion'] ?? [],
                'lead_conversion' => $full['lead_conversion'] ?? [],
                'time_to_conversion' => $full['time_to_conversion'] ?? [],
                'target_achievement' => $full['target_achievement'] ?? [],
                'kpi_mode' => $full['kpi_mode'] ?? ''
            ];
        } elseif ($section === 'charts') {
            $payload = [
                'daily_sales' => $full['daily_sales'] ?? [],
                'lost_sales' => $full['lost_sales'] ?? [],
                'product_sales' => $full['product_sales'] ?? [],
            ];
        } elseif ($section === 'tabs') {
            $payload = [
                'daily_operational' => $full['daily_operational'] ?? [],
                'advanced_tables' => $full['advanced_tables'] ?? []
            ];
        } else {
            $payload = $full;
        }
        $this->setCachedKpiPayload($surfaceKey, $repoFilters, $payload);
        return $payload;
    }

    private function getCachedKpiPayload(string $surface, array $filters): ?array
    {
        if (!$this->kpiCache || !method_exists($this->kpiCache, 'get')) {
            return null;
        }
        try {
            return $this->kpiCache->get($surface, $filters);
        } catch (\Throwable $e) {
            Logger::logWarning('Kpi cache read failed', ['surface' => $surface, 'error' => $e->getMessage()]);
            return null;
        }
    }

    private function setCachedKpiPayload(string $surface, array $filters, array $payload): void
    {
        if (!$this->kpiCache || !method_exists($this->kpiCache, 'set')) {
            return;
        }
        try {
            $this->kpiCache->set($surface, $filters, $payload);
        } catch (\Throwable $e) {
            Logger::logWarning('Kpi cache write failed', ['surface' => $surface, 'error' => $e->getMessage()]);
        }
    }

    private function buildPreviousPeriodFilters(array $filters): array
    {
        $from = new \DateTime((string)($filters['date_from'] ?? date('Y-m-01')));
        $to = new \DateTime((string)($filters['date_to'] ?? date('Y-m-t')));
        $from->setTime(0, 0, 0);
        $to->setTime(0, 0, 0);
        $diffDays = max(1, (int)$from->diff($to)->days + 1);

        $prevTo = (clone $from)->modify('-1 day');
        $prevFrom = (clone $prevTo)->modify('-' . ($diffDays - 1) . ' days');

        $label = 'بازه قبل';
        if ($diffDays >= 6 && $diffDays <= 8) {
            $label = 'مقایسه هفتگی (WoW)';
        } elseif ($diffDays >= 27 && $diffDays <= 33) {
            $label = 'مقایسه ماهانه (MoM)';
        }

        $prevFilters = $filters;
        $prevFilters['date_from'] = $prevFrom->format('Y-m-d');
        $prevFilters['date_to'] = $prevTo->format('Y-m-d');
        $prevFilters['person_date_from'] = $prevFilters['date_from'];
        $prevFilters['person_date_to'] = $prevFilters['date_to'];

        return ['filters' => $prevFilters, 'label' => $label];
    }

    private function buildSummaryComparison(array $current, array $previous): array
    {
        $keys = [
            'total_sales_amount',
            'with_sales_deals_count',
            'outstanding_amount',
            'settled_count',
            'without_payment_count',
            'deal_conversion_rate',
            'lead_conversion_rate'
        ];
        $out = [];
        foreach ($keys as $key) {
            $curr = (float)($current[$key] ?? 0);
            $prev = (float)($previous[$key] ?? 0);
            $delta = $curr - $prev;
            $deltaPct = $prev != 0.0 ? (($delta / $prev) * 100.0) : ($curr == 0.0 ? 0.0 : 100.0);
            $out[$key] = [
                'current' => $curr,
                'previous' => $prev,
                'delta' => $delta,
                'delta_percent' => $deltaPct
            ];
        }
        return $out;
    }

    private function calculateTargetDailyAmount(string $dateFrom, string $dateTo, float $targetAmount): float
    {
        if ($targetAmount <= 0 || $dateFrom === '' || $dateTo === '') {
            return 0.0;
        }
        try {
            $from = new \DateTime($dateFrom);
            $to = new \DateTime($dateTo);
        } catch (\Exception $e) {
            return 0.0;
        }
        $days = max(1, (int)$from->diff($to)->days + 1);
        return round($targetAmount / $days, 2);
    }

    /**
     * جدول‌های پیشرفته KPI
     */
    private function buildAdvancedKpiTables(array $filters): array
    {
        return $this->kpiRepo->getAdvancedKpiTables($filters);
    }
}
