<?php

namespace App\Services;

use App\Enums\ConsultationStatus;
use App\Enums\ConsultationType;
use App\Enums\PostStatus;
use App\Enums\TimelineStatus;
use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\Consultation;
use App\Models\Post;
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Symfony\Component\HttpFoundation\StreamedResponse;

class MonthlyReportService
{
    public function generate(int $year, int $month): StreamedResponse
    {
        $startDate = Carbon::create($year, $month, 1)->startOfMonth();
        $endDate = $startDate->copy()->endOfMonth();
        $locale = Auth::user()->preferred_language ?? 'en';

        $data = [
            'period' => $startDate->translatedFormat('F Y'),
            'periodMonth' => $startDate->translatedFormat('F'),
            'periodYear' => $year,
            'generatedAt' => now()->translatedFormat('d M Y H:i'),
            'locale' => $locale,
            'userStats' => $this->getUserStats($startDate, $endDate),
            'consultationStats' => $this->getConsultationStats($startDate, $endDate),
            'timelineStats' => $this->getTimelineStats($startDate, $endDate),
            'postStats' => $this->getPostStats($startDate, $endDate),
            'charts' => $this->renderChartsAsImages($startDate, $endDate, $locale),
            'previousMonth' => $this->getPreviousMonthComparison($startDate),
            'executiveSummary' => $this->generateExecutiveSummary($startDate, $endDate, $locale),
        ];

        $pdf = Pdf::loadView('pdf.monthly-report', $data)
            ->setPaper('a4', 'portrait');

        $pdf->setOption('isHtml5ParserEnabled', true);
        $pdf->setOption('defaultFont', 'DejaVu Sans');

        $filename = "monthly-report-{$year}-{$month}.pdf";

        return response()->streamDownload(
            fn () => print ($pdf->output()),
            $filename
        );
    }

    public function getUserStats(Carbon $start, Carbon $end): array
    {
        $newClients = User::query()
            ->whereBetween('created_at', [$start, $end])
            ->whereIn('user_type', [UserType::Individual, UserType::Company])
            ->count();

        $totalActive = User::query()
            ->where('status', UserStatus::Active)
            ->where('created_at', '<=', $end)
            ->whereIn('user_type', [UserType::Individual, UserType::Company])
            ->count();

        $individual = User::query()
            ->where('user_type', UserType::Individual)
            ->where('status', UserStatus::Active)
            ->where('created_at', '<=', $end)
            ->count();

        $company = User::query()
            ->where('user_type', UserType::Company)
            ->where('status', UserStatus::Active)
            ->where('created_at', '<=', $end)
            ->count();

        return [
            'new_clients' => $newClients,
            'total_active' => $totalActive,
            'individual' => $individual,
            'company' => $company,
        ];
    }

    public function getConsultationStats(Carbon $start, Carbon $end): array
    {
        $total = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->count();

        $completed = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->whereIn('status', [ConsultationStatus::Completed, ConsultationStatus::NoShow])
            ->count();

        $noShows = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->where('status', ConsultationStatus::NoShow)
            ->count();

        $free = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->where('consultation_type', ConsultationType::Free)
            ->count();

        $paid = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->where('consultation_type', ConsultationType::Paid)
            ->count();

        return [
            'total' => $total,
            'approved' => Consultation::query()
                ->whereBetween('booking_date', [$start, $end])
                ->where('status', ConsultationStatus::Approved)
                ->count(),
            'completed' => Consultation::query()
                ->whereBetween('booking_date', [$start, $end])
                ->where('status', ConsultationStatus::Completed)
                ->count(),
            'cancelled' => Consultation::query()
                ->whereBetween('booking_date', [$start, $end])
                ->where('status', ConsultationStatus::Cancelled)
                ->count(),
            'no_show' => $noShows,
            'free' => $free,
            'paid' => $paid,
            'no_show_rate' => $completed > 0 ? round(($noShows / $completed) * 100, 1) : 0,
        ];
    }

    public function getTimelineStats(Carbon $start, Carbon $end): array
    {
        return [
            'active' => Timeline::query()
                ->where('status', TimelineStatus::Active)
                ->where('created_at', '<=', $end)
                ->count(),
            'new' => Timeline::query()
                ->whereBetween('created_at', [$start, $end])
                ->count(),
            'updates' => TimelineUpdate::query()
                ->whereBetween('created_at', [$start, $end])
                ->count(),
            'archived' => Timeline::query()
                ->where('status', TimelineStatus::Archived)
                ->whereBetween('updated_at', [$start, $end])
                ->count(),
        ];
    }

    public function getPostStats(Carbon $start, Carbon $end): array
    {
        return [
            'this_month' => Post::query()
                ->where('status', PostStatus::Published)
                ->whereBetween('published_at', [$start, $end])
                ->count(),
            'total' => Post::query()
                ->where('status', PostStatus::Published)
                ->where('published_at', '<=', $end)
                ->count(),
        ];
    }

    private function renderChartsAsImages(Carbon $start, Carbon $end, string $locale): array
    {
        $free = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->where('consultation_type', ConsultationType::Free)
            ->count();

        $paid = Consultation::query()
            ->whereBetween('booking_date', [$start, $end])
            ->where('consultation_type', ConsultationType::Paid)
            ->count();

        $consultationPieChart = $this->generateQuickChart([
            'type' => 'pie',
            'data' => [
                'labels' => [
                    __('report.free', [], $locale),
                    __('report.paid', [], $locale),
                ],
                'datasets' => [[
                    'data' => [$free, $paid],
                    'backgroundColor' => ['#A68966', '#C4A882'],
                ]],
            ],
            'options' => [
                'plugins' => [
                    'legend' => [
                        'position' => 'bottom',
                    ],
                ],
            ],
        ]);

        $trendChart = $this->generateTrendChart($start, $locale);

        return [
            'consultation_pie' => $consultationPieChart,
            'trend_line' => $trendChart,
        ];
    }

    private function generateQuickChart(array $config): string
    {
        $url = 'https://quickchart.io/chart?c='.urlencode(json_encode($config)).'&w=400&h=300&bkg=white';

        try {
            $response = Http::timeout(10)->get($url);

            if ($response->successful()) {
                return 'data:image/png;base64,'.base64_encode($response->body());
            }

            return '';
        } catch (\Exception $e) {
            return '';
        }
    }

    private function generateTrendChart(Carbon $endMonth, string $locale): string
    {
        $labels = [];
        $data = [];

        for ($i = 5; $i >= 0; $i--) {
            $month = $endMonth->copy()->subMonths($i);
            $labels[] = $month->translatedFormat('M Y');
            $data[] = Consultation::query()
                ->whereMonth('booking_date', $month->month)
                ->whereYear('booking_date', $month->year)
                ->count();
        }

        return $this->generateQuickChart([
            'type' => 'line',
            'data' => [
                'labels' => $labels,
                'datasets' => [[
                    'label' => __('report.consultations', [], $locale),
                    'data' => $data,
                    'borderColor' => '#A68966',
                    'backgroundColor' => 'rgba(166, 137, 102, 0.1)',
                    'fill' => true,
                    'tension' => 0.3,
                ]],
            ],
            'options' => [
                'plugins' => [
                    'legend' => [
                        'position' => 'bottom',
                    ],
                ],
                'scales' => [
                    'y' => [
                        'beginAtZero' => true,
                        'ticks' => [
                            'precision' => 0,
                        ],
                    ],
                ],
            ],
        ]);
    }

    public function getPreviousMonthComparison(Carbon $currentStart): ?array
    {
        $prevStart = $currentStart->copy()->subMonth()->startOfMonth();
        $prevEnd = $prevStart->copy()->endOfMonth();

        $prevConsultations = Consultation::query()
            ->whereBetween('booking_date', [$prevStart, $prevEnd])
            ->count();

        $prevClients = User::query()
            ->whereBetween('created_at', [$prevStart, $prevEnd])
            ->whereIn('user_type', [UserType::Individual, UserType::Company])
            ->count();

        if ($prevConsultations === 0 && $prevClients === 0) {
            return null;
        }

        return [
            'consultations' => $prevConsultations,
            'clients' => $prevClients,
        ];
    }

    private function generateExecutiveSummary(Carbon $start, Carbon $end, string $locale): array
    {
        $userStats = $this->getUserStats($start, $end);
        $consultationStats = $this->getConsultationStats($start, $end);
        $previousMonth = $this->getPreviousMonthComparison($start);

        $highlights = [];

        // New clients highlight
        if ($userStats['new_clients'] > 0) {
            $highlights[] = __('report.highlight_new_clients', ['count' => $userStats['new_clients']], $locale);
        }

        // Consultations highlight
        if ($consultationStats['total'] > 0) {
            $highlights[] = __('report.highlight_consultations', ['count' => $consultationStats['total']], $locale);
        }

        // Month-over-month comparison
        if ($previousMonth) {
            $consultationChange = $consultationStats['total'] - $previousMonth['consultations'];
            if ($consultationChange > 0) {
                $highlights[] = __('report.highlight_growth', ['count' => $consultationChange], $locale);
            } elseif ($consultationChange < 0) {
                $highlights[] = __('report.highlight_decrease', ['count' => abs($consultationChange)], $locale);
            }
        }

        // No-show rate alert
        if ($consultationStats['no_show_rate'] > 20) {
            $highlights[] = __('report.highlight_noshow_alert', ['rate' => $consultationStats['no_show_rate']], $locale);
        }

        return $highlights;
    }
}
