<?php

namespace App\Services;

use App\Models\Audit;
use App\Models\Contact;
use App\Models\Media;
use App\Models\Page;
use App\Models\Service;
use App\Models\Visit;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema;

class DashboardMetricsService
{
    public function getOverview(): array
    {
        $today = Carbon::today();
        $weekStart = Carbon::now()->subDays(6)->startOfDay();
        $lateThreshold = Carbon::now()->subHours(24);

        $recentVisits = Visit::query()
            ->where('visited_at', '>=', $weekStart)
            ->orderBy('visited_at')
            ->get();

        $todayVisits = $recentVisits->filter(fn (Visit $visit) => $visit->visited_at?->isSameDay($today))->count();
        $uniqueVisitors = $this->countUniqueVisitors($recentVisits);
        $newContacts = Contact::query()->where('status', 'new')->count();
        $lateContacts = Contact::query()
            ->whereIn('status', ['new', 'read'])
            ->where('created_at', '<=', $lateThreshold)
            ->count();
        $repliedContacts = Contact::query()->where('status', 'replied')->count();
        $responseRate = $this->responseRate();
        $profileStrength = $this->profileStrength();

        return [
            'stats' => [
                [
                    'label' => 'Visitors Today',
                    'value' => number_format($todayVisits),
                    'meta' => 'Public pages tracked automatically',
                ],
                [
                    'label' => 'Unique Visitors',
                    'value' => number_format($uniqueVisitors),
                    'meta' => 'Last 7 days',
                ],
                [
                    'label' => 'Unread Leads',
                    'value' => number_format($newContacts),
                    'meta' => 'Waiting for response',
                ],
                [
                    'label' => 'Late Replies',
                    'value' => number_format($lateContacts),
                    'meta' => 'Open for more than 24 hours',
                ],
                [
                    'label' => 'Reply Rate',
                    'value' => $responseRate . '%',
                    'meta' => 'Contacts marked replied',
                ],
                [
                    'label' => 'Site Assets',
                    'value' => number_format(Media::query()->count()),
                    'meta' => 'Media in the library',
                ],
            ],
            'recent_contacts' => Contact::query()->latest()->limit(6)->get(),
            'recent_activity' => Audit::query()->with('user')->latest()->limit(8)->get(),
            'response_statuses' => [
                [
                    'label' => 'New',
                    'value' => Contact::query()->where('status', 'new')->count(),
                    'class' => 'new',
                ],
                [
                    'label' => 'In Review',
                    'value' => Contact::query()->where('status', 'read')->count(),
                    'class' => 'read',
                ],
                [
                    'label' => 'Late',
                    'value' => $lateContacts,
                    'class' => 'late',
                ],
                [
                    'label' => 'Replied',
                    'value' => $repliedContacts,
                    'class' => 'replied',
                ],
            ],
            'profile_strength' => $profileStrength,
            'site_totals' => [
                [
                    'label' => 'Pages',
                    'value' => number_format(Page::query()->count()),
                ],
                [
                    'label' => 'Services',
                    'value' => number_format(Service::query()->count()),
                ],
                [
                    'label' => 'Media',
                    'value' => number_format(Media::query()->count()),
                ],
            ],
            'top_pages' => $recentVisits
                ->groupBy('path')
                ->map(fn (Collection $group, string $path): array => [
                    'path' => $path,
                    'visits' => $group->count(),
                    'unique' => $this->countUniqueVisitors($group),
                ])
                ->sortByDesc('visits')
                ->take(6)
                ->values()
                ->all(),
            'top_countries' => $recentVisits
                ->groupBy(fn (Visit $visit): string => $visit->country_name ?: 'Unknown')
                ->map(fn (Collection $group, string $country): array => [
                    'country' => $country,
                    'visits' => $group->count(),
                    'unique' => $this->countUniqueVisitors($group),
                ])
                ->sortByDesc('visits')
                ->take(6)
                ->values()
                ->all(),
            'top_sources' => $recentVisits
                ->groupBy(fn (Visit $visit): string => ($visit->traffic_source ?: 'direct') . '|' . ($visit->traffic_medium ?: 'direct'))
                ->map(function (Collection $group, string $key): array {
                    [$source, $medium] = explode('|', $key);

                    return [
                        'source' => $source,
                        'medium' => $medium,
                        'visits' => $group->count(),
                        'unique' => $this->countUniqueVisitors($group),
                    ];
                })
                ->sortByDesc('visits')
                ->take(6)
                ->values()
                ->all(),
            'visits_chart' => $this->buildVisitsChart($recentVisits),
        ];
    }

    protected function buildVisitsChart(Collection $recentVisits): array
    {
        $labels = [];
        $visits = [];
        $unique = [];

        foreach (CarbonPeriod::create(Carbon::now()->subDays(6)->startOfDay(), '1 day', Carbon::today()) as $date) {
            $dayVisits = $recentVisits->filter(fn (Visit $visit) => $visit->visited_at?->isSameDay($date));
            $labels[] = $date->format('M j');
            $visits[] = $dayVisits->count();
            $unique[] = $this->countUniqueVisitors($dayVisits);
        }

        return [
            'labels' => $labels,
            'datasets' => [
                [
                    'label' => 'Visits',
                    'data' => $visits,
                ],
                [
                    'label' => 'Unique Visitors',
                    'data' => $unique,
                ],
            ],
        ];
    }

    protected function countUniqueVisitors(Collection $visits): int
    {
        return $visits
            ->map(fn (Visit $visit): string => (string) ($visit->session_id ?: $visit->ip_hash ?: $visit->id))
            ->filter()
            ->unique()
            ->count();
    }

    protected function responseRate(): string
    {
        $total = Contact::query()->count();

        if ($total === 0) {
            return '0';
        }

        $replied = Contact::query()->where('status', 'replied')->count();

        return number_format(($replied / $total) * 100, 0);
    }

    protected function profileStrength(): array
    {
        $user = Auth::user();
        $settings = Schema::hasTable('settings')
            ? \App\Models\Setting::query()->with(['logoMedia'])->first()
            : null;

        $checks = [
            'Brand name set' => filled($settings?->site_name),
            'Logo uploaded' => filled($settings?->logo_media_id) || filled($settings?->logo),
            'Contact email added' => filled($settings?->contact_email),
            'Contact phone added' => filled($settings?->contact_phone),
            'Header CTA ready' => filled($settings?->header_cta_label) && filled($settings?->header_cta_url),
            'Profile name set' => filled($user?->name),
            'Profile email set' => filled($user?->email),
            'Reply emails enabled' => (bool) ($settings?->user_contact_auto_reply_enabled),
        ];

        $completed = collect($checks)->filter()->count();
        $total = count($checks);

        return [
            'completed' => $completed,
            'total' => $total,
            'percent' => (int) round(($completed / max($total, 1)) * 100),
            'items' => $checks,
        ];
    }
}
