<?php

namespace App\Services\Stats;

use App\Models\Stats\Daily\StatFinanceDaily;
use App\Models\Stats\Daily\StatHrAttendanceDaily;
use App\Models\Stats\Daily\StatInventoryDaily;
use App\Models\Stats\Daily\StatProductionDaily;
use App\Models\Stats\Daily\StatQuotePipelineDaily;
use App\Models\Stats\Daily\StatSalesDaily;
use App\Models\Stats\Daily\StatSystemDaily;
use App\Models\Stats\Monthly\StatFinanceMonthly;
use App\Models\Stats\Monthly\StatProductionMonthly;
use App\Models\Stats\Monthly\StatProjectMonthly;
use App\Models\Stats\Monthly\StatSalesMonthly;
use App\Models\Stats\StatAlert;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;

class StatQueryService extends Service
{
    private const CACHE_TTL = 300; // 5분

    /**
     * 도메인별 일간 통계 조회
     */
    public function getDailyStat(string $domain, array $params): array
    {
        $tenantId = $this->tenantId();
        $startDate = $params['start_date'];
        $endDate = $params['end_date'];

        $cacheKey = "stat:daily:{$tenantId}:{$domain}:{$startDate}:{$endDate}";

        return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($domain, $tenantId, $startDate, $endDate) {
            $model = $this->getDailyModel($domain);
            if (! $model) {
                return [];
            }

            return $model::where('tenant_id', $tenantId)
                ->whereBetween('stat_date', [$startDate, $endDate])
                ->orderBy('stat_date')
                ->get()
                ->toArray();
        });
    }

    /**
     * 도메인별 월간 통계 조회
     */
    public function getMonthlyStat(string $domain, array $params): array
    {
        $tenantId = $this->tenantId();
        $year = (int) $params['year'];
        $month = isset($params['month']) ? (int) $params['month'] : null;

        $cacheKey = "stat:monthly:{$tenantId}:{$domain}:{$year}:".($month ?? 'all');

        return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($domain, $tenantId, $year, $month) {
            $model = $this->getMonthlyModel($domain);
            if (! $model) {
                return [];
            }

            $query = $model::where('tenant_id', $tenantId)
                ->where('stat_year', $year);

            if ($month) {
                $query->where('stat_month', $month);
            }

            return $query->orderBy('stat_month')
                ->get()
                ->toArray();
        });
    }

    /**
     * 대시보드 요약 통계 (sam_stat 기반)
     */
    public function getDashboardSummary(): array
    {
        $tenantId = $this->tenantId();
        $today = Carbon::today()->format('Y-m-d');
        $year = Carbon::now()->year;
        $month = Carbon::now()->month;

        $cacheKey = "stat:dashboard:{$tenantId}:{$today}";

        return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($tenantId, $today, $year, $month) {
            return [
                'sales_today' => $this->getTodaySales($tenantId, $today),
                'finance_today' => $this->getTodayFinance($tenantId, $today),
                'production_today' => $this->getTodayProduction($tenantId, $today),
                'sales_monthly' => $this->getMonthlySalesOverview($tenantId, $year, $month),
                'alerts' => $this->getActiveAlerts($tenantId),
            ];
        });
    }

    /**
     * 알림 목록 조회
     */
    public function getAlerts(array $params): array
    {
        $tenantId = $this->tenantId();
        $limit = $params['limit'] ?? 20;
        $unreadOnly = $params['unread_only'] ?? false;

        $query = StatAlert::where('tenant_id', $tenantId)
            ->orderByDesc('created_at');

        if ($unreadOnly) {
            $query->where('is_read', false);
        }

        return $query->limit($limit)->get()->toArray();
    }

    /**
     * 집계 완료 시 관련 캐시 무효화
     */
    public static function invalidateCache(int $tenantId, ?string $domain = null): void
    {
        $patterns = [
            "stat:dashboard:{$tenantId}:*",
        ];

        if ($domain) {
            $patterns[] = "stat:daily:{$tenantId}:{$domain}:*";
            $patterns[] = "stat:monthly:{$tenantId}:{$domain}:*";
        } else {
            $patterns[] = "stat:daily:{$tenantId}:*";
            $patterns[] = "stat:monthly:{$tenantId}:*";
        }

        // Redis 태그 기반 또는 키 패턴 삭제
        $redis = Cache::getStore();
        if (method_exists($redis, 'getRedis')) {
            $connection = $redis->getRedis();
            $prefix = config('cache.prefix', '').':';

            foreach ($patterns as $pattern) {
                $keys = $connection->keys($prefix.$pattern);
                if (! empty($keys)) {
                    $connection->del($keys);
                }
            }
        } else {
            // Redis가 아닌 경우 개별 키 삭제 (대시보드만)
            $today = Carbon::today()->format('Y-m-d');
            Cache::forget("stat:dashboard:{$tenantId}:{$today}");
        }
    }

    private function getTodaySales(int $tenantId, string $today): ?array
    {
        $stat = StatSalesDaily::where('tenant_id', $tenantId)
            ->where('stat_date', $today)
            ->first();

        return $stat?->toArray();
    }

    private function getTodayFinance(int $tenantId, string $today): ?array
    {
        $stat = StatFinanceDaily::where('tenant_id', $tenantId)
            ->where('stat_date', $today)
            ->first();

        return $stat?->toArray();
    }

    private function getTodayProduction(int $tenantId, string $today): ?array
    {
        $stat = StatProductionDaily::where('tenant_id', $tenantId)
            ->where('stat_date', $today)
            ->first();

        return $stat?->toArray();
    }

    private function getMonthlySalesOverview(int $tenantId, int $year, int $month): ?array
    {
        $stat = StatSalesMonthly::where('tenant_id', $tenantId)
            ->where('stat_year', $year)
            ->where('stat_month', $month)
            ->first();

        return $stat?->toArray();
    }

    private function getActiveAlerts(int $tenantId): array
    {
        return StatAlert::where('tenant_id', $tenantId)
            ->where('is_read', false)
            ->where('is_resolved', false)
            ->orderByDesc('created_at')
            ->limit(10)
            ->get()
            ->toArray();
    }

    private function getDailyModel(string $domain): ?string
    {
        return match ($domain) {
            'sales' => StatSalesDaily::class,
            'finance' => StatFinanceDaily::class,
            'production' => StatProductionDaily::class,
            'inventory' => StatInventoryDaily::class,
            'quote' => StatQuotePipelineDaily::class,
            'hr' => StatHrAttendanceDaily::class,
            'system' => StatSystemDaily::class,
            default => null,
        };
    }

    private function getMonthlyModel(string $domain): ?string
    {
        return match ($domain) {
            'sales' => StatSalesMonthly::class,
            'finance' => StatFinanceMonthly::class,
            'production' => StatProductionMonthly::class,
            'project' => StatProjectMonthly::class,
            default => null,
        };
    }
}
