<?php

namespace App\Http\Controllers\Panel;

use App\Http\Controllers\Controller;
use App\Mixins\Certificate\MakeCertificate;
use App\Models\Certificate;
use App\Models\Reward;
use App\Models\RewardAccounting;
use App\Models\Webinar;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;

class WebinarCertificateController extends Controller
{

    public function index(Request $request)
    {
        $user = auth()->user();

        $webinars = Webinar::where('status', 'active')
            ->whereHas('sales', function ($query) use ($user) {
                $query->where('buyer_id', $user->id);
                $query->whereNull('refund_at');
                $query->where('access_to_purchased_item', true);
            })
            ->get();

        $this->calculateCertificates($user, $webinars);

        $certificateFiltersActive =
            !empty($request->get('from'))
            || !empty($request->get('to'))
            || ((!empty($request->get('webinar_id')) && $request->get('webinar_id') !== 'all'));

        $allUnified = $user->getAllCertificates();
        $sortedFiltered = $allUnified->filter(fn ($cert) => $this->certificateMatchesRequestFilters($cert, $request))
            ->sortByDesc(fn ($cert) => $this->certificateSortTimestamp($cert))
            ->values();

        $filteredOutAllCerts = $certificateFiltersActive && $allUnified->isNotEmpty() && $sortedFiltered->isEmpty();

        $perPage = 15;
        $currentPage = LengthAwarePaginator::resolveCurrentPage();
        $paginatorItems = $sortedFiltered->slice(($currentPage - 1) * $perPage, $perPage)->values();

        $allCertificates = new LengthAwarePaginator(
            $paginatorItems,
            $sortedFiltered->count(),
            $perPage,
            $currentPage,
            ['path' => LengthAwarePaginator::resolveCurrentPath(), 'query' => $request->query()]
        );

        $data = [
            'pageTitle' => trans('quiz.my_certificates'),
            'allCertificates' => $allCertificates,
            'userWebinars' => $webinars,
            'filteredOutAllCerts' => $filteredOutAllCerts,
        ];

        return view('web.default.panel.certificates.webinar_certificates', $data);
    }

    private function certificateSortTimestamp($cert): int
    {
        if ($cert->certificate_type === 'old') {
            return is_numeric($cert->created_at) ? (int) $cert->created_at : strtotime((string) $cert->created_at);
        }

        if ($cert->certificate_type === 'new') {
            if (!empty($cert->completion_date)) {
                return $cert->completion_date instanceof Carbon
                    ? $cert->completion_date->startOfDay()->timestamp
                    : strtotime((string) $cert->completion_date);
            }

            foreach (['updated_at', 'created_at'] as $field) {
                if (!empty($cert->{$field})) {
                    $v = $cert->{$field};

                    return $v instanceof Carbon ? $v->timestamp : strtotime((string) $v);
                }
            }

            return 0;
        }

        if ($cert->certificate_type === 'last') {
            if (!empty($cert->generated_at)) {
                $g = $cert->generated_at;

                return $g instanceof Carbon ? $g->timestamp : strtotime((string) $g);
            }
            foreach (['updated_at', 'created_at'] as $field) {
                if (!empty($cert->{$field})) {
                    $v = $cert->{$field};

                    return $v instanceof Carbon ? $v->timestamp : (is_numeric($v) ? (int) $v : strtotime((string) $v));
                }
            }
        }

        return 0;
    }

    private function certificatePassesDateFilters($cert, Request $request): bool
    {
        $from = $request->get('from');
        $to = $request->get('to');

        if (empty($from) && empty($to)) {
            return true;
        }

        $ts = $this->certificateSortTimestamp($cert);

        if ($from && $to) {
            $fromTs = strtotime($from);
            $toTs = strtotime($to);

            return $ts >= $fromTs && $ts <= $toTs;
        }

        if ($from && strtotime($from) > $ts) {
            return false;
        }

        if ($to && !($ts < strtotime($to))) {
            return false;
        }

        return true;
    }

    private function certificatePassesWebinarFilter($cert, Request $request): bool
    {
        $webinar_id = $request->get('webinar_id');

        if (empty($webinar_id) || $webinar_id === 'all') {
            return true;
        }

        $wid = (int) $webinar_id;

        if ($cert->certificate_type !== 'old') {
            return true;
        }

        if ($cert->type === 'course' && !empty($cert->webinar_id)) {
            return (int) $cert->webinar_id === $wid;
        }

        if ($cert->type === 'quiz') {
            $webinarQuizId = optional(optional($cert->quiz)->webinar)->id;

            return (int) $webinarQuizId === $wid;
        }

        return true;
    }

    private function certificateMatchesRequestFilters($cert, Request $request): bool
    {
        if (!$this->certificatePassesDateFilters($cert, $request)) {
            return false;
        }

        return $this->certificatePassesWebinarFilter($cert, $request);
    }

    public function ensureCourseCertificatesForUser($user, $webinars): void
    {
        $this->calculateCertificates($user, $webinars);
    }

    private function calculateCertificates($user, $webinars)
    {
        $makeCertificate = new MakeCertificate();

        foreach ($webinars as $webinar) {
            if ($webinar->certificate and $webinar->getProgress() >= 100) {
                $check = Certificate::where('type', 'course')
                    ->where('student_id', $user->id)
                    ->where('webinar_id', $webinar->id)
                    ->first();

                if (empty($check)) {
                    $userCertificate = $makeCertificate->saveCourseCertificate($user, $webinar);

                    $certificateReward = RewardAccounting::calculateScore(Reward::CERTIFICATE);
                    RewardAccounting::makeRewardAccounting($userCertificate->student_id, $certificateReward, Reward::CERTIFICATE, $userCertificate->id, true);
                }
            }
        }
    }

    public function makeCertificate($certificateId)
    {
        $user = auth()->user();

        $certificate = Certificate::where('id', $certificateId)
            ->where('student_id', $user->id)
            ->whereNotNull('webinar_id')
            ->first();

        if (!empty($certificate)) {
            $makeCertificate = new MakeCertificate();

            return $makeCertificate->makeCourseCertificate($certificate);
        }

        abort(404);
    }
}
