<?php

namespace App\Repositories;

use App\Models\AnalyticsProductVisit;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

class AnalyticsProductVisitRepository
{
    /**
     * Get all product visits with optional filtering
     */
    public function getAll(array $filters = []): Collection
    {
        $query = AnalyticsProductVisit::query();

        // Filter by product ID
        if (isset($filters['item_id'])) {
            $query->where('item_id', $filters['item_id']);
        }

        // Filter by user ID
        if (isset($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }

        // Filter by date range
        if (isset($filters['date_from'])) {
            $query->where('started_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->where('started_at', '<=', $filters['date_to']);
        }

        // Filter by IP address
        if (isset($filters['ip_address'])) {
            $query->where('ip_address', $filters['ip_address']);
        }

        return $query->orderBy('started_at', 'desc')->get();
    }

    /**
     * Get product visits with pagination
     */
    public function getPaginated(array $filters = [], int $perPage = 20): LengthAwarePaginator
    {
        $query = AnalyticsProductVisit::query();

        // Apply same filters as getAll method
        if (isset($filters['item_id'])) {
            $query->where('item_id', $filters['item_id']);
        }

        if (isset($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }

        if (isset($filters['date_from'])) {
            $query->where('started_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->where('started_at', '<=', $filters['date_to']);
        }

        return $query->orderBy('started_at', 'desc')
            ->paginate($perPage);
    }

    /**
     * Create a new product visit record
     */
    public function create(array $data): AnalyticsProductVisit
    {
        return AnalyticsProductVisit::create($data);
    }

    /**
     * Update existing product visit
     */
    public function update(int $id, array $data): bool
    {
        $visit = AnalyticsProductVisit::find($id);
        
        if (!$visit) {
            return false;
        }

        return $visit->update($data);
    }

    /**
     * Delete a product visit record
     */
    public function delete(int $id): bool
    {
        $visit = AnalyticsProductVisit::find($id);
        
        if (!$visit) {
            return false;
        }

        return $visit->delete();
    }

    /**
     * Get visit statistics
     */
    public function getStatistics(array $filters = []): array
    {
        $query = AnalyticsProductVisit::query();

        // Apply date filters
        if (isset($filters['date_from'])) {
            $query->where('started_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->where('started_at', '<=', $filters['date_to']);
        }

        $totalVisits = $query->count();
        
        $uniqueVisitors = $query->distinct('user_id')->count('user_id');
        
        $averageDuration = $query->avg('duration_seconds');
        
        $totalDuration = $query->sum('duration_seconds');

        return [
            'total_visits' => $totalVisits,
            'unique_visitors' => $uniqueVisitors,
            'average_duration_seconds' => round($averageDuration, 2),
            'total_duration_seconds' => $totalDuration,
            'average_duration_formatted' => $this->formatDuration($averageDuration),
            'total_duration_formatted' => $this->formatDuration($totalDuration),
        ];
    }

    /**
     * Get most visited products
     */
    public function getMostVisitedProducts(int $limit = 10): array
    {
        return AnalyticsProductVisit::query()
            ->selectRaw('item_id, COUNT(*) as visit_count, AVG(duration_seconds) as avg_duration')
            ->groupBy('item_id')
            ->orderBy('visit_count', 'desc')
            ->limit($limit)
            ->get()
            ->toArray();
    }

    /**
     * Get visits by device type
     */
    public function getVisitsByDeviceType(array $filters = []): array
    {
        $query = AnalyticsProductVisit::query();

        if (isset($filters['date_from'])) {
            $query->where('started_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->where('started_at', '<=', $filters['date_to']);
        }

        return $query->selectRaw('device_type, COUNT(*) as count')
            ->groupBy('device_type')
            ->orderBy('count', 'desc')
            ->get()
            ->toArray();
    }

    /**
     * Get daily visit statistics
     */
    public function getDailyStatistics(array $filters = []): array
    {
        $query = AnalyticsProductVisit::query();

        if (isset($filters['date_from'])) {
            $query->where('started_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->where('started_at', '<=', $filters['date_to']);
        }

        return $query->selectRaw('DATE(started_at) as date, COUNT(*) as visits, COUNT(DISTINCT user_id) as unique_visitors')
            ->groupBy('date')
            ->orderBy('date', 'desc')
            ->get()
            ->toArray();
    }

    /**
     * Format duration in human readable format
     */
    private function formatDuration(float $seconds): string
    {
        if ($seconds < 60) {
            return round($seconds) . 's';
        }

        if ($seconds < 3600) {
            $minutes = floor($seconds / 60);
            $remainingSeconds = $seconds % 60;
            return $minutes . 'm ' . round($remainingSeconds) . 's';
        }

        $hours = floor($seconds / 3600);
        $remainingSeconds = $seconds % 3600;
        $minutes = floor($remainingSeconds / 60);
        $remainingSeconds = $remainingSeconds % 60;

        return $hours . 'h ' . $minutes . 'm ' . round($remainingSeconds) . 's';
    }

    /**
     * Get product visit by ID
     */
    public function findById(int $id): ?AnalyticsProductVisit
    {
        return AnalyticsProductVisit::find($id);
    }

    /**
     * Get visits by session ID
     */
    public function getBySessionId(string $sessionId): Collection
    {
        return AnalyticsProductVisit::where('session_id', $sessionId)
            ->orderBy('started_at', 'desc')
            ->get();
    }

    /**
     * Bulk insert visits
     */
    public function bulkInsert(array $visits): bool
    {
        try {
            AnalyticsProductVisit::insert($visits);
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }
}
