<?php

namespace App\Http\Controllers\Training;

use App\Http\Controllers\Controller;
use App\Models\TrainingCertificate;
use App\Models\TrainingRegistration;
use App\Services\CertificationService;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\JsonResponse;

/**
 * CertificateController
 *
 * Handles training certificate management for authenticated users.
 *
 * @package App\Http\Controllers\Training
 */
class CertificateController extends Controller
{
    /**
     * CertificationService instance.
     *
     * @var \App\Services\CertificationService
     */
    protected CertificationService $certificationService;

    /**
     * Create a new CertificateController instance.
     *
     * @param \App\Services\CertificationService $certificationService
     */
    public function __construct(CertificationService $certificationService)
    {
        $this->certificationService = $certificationService;
    }

    /**
     * Display a listing of all certificates.
     *
     * @return \Illuminate\View\View
     */
    public function index(): View
    {
        abort_unless(auth()->user()->can('view training certificates'), 403);

        $certificates = TrainingCertificate::with(['user', 'trainingPackage'])
            ->when(request('search'), function ($query, $search) {
                $query->where('certificate_number', 'like', "%{$search}%")
                    ->orWhereHas('user', function ($q) use ($search) {
                        $q->where('name', 'like', "%{$search}%");
                    });
            })
            ->when(request('status'), function ($query, $status) {
                if ($status === 'valid') {
                    $query->where('is_revoked', false);
                } elseif ($status === 'revoked') {
                    $query->where('is_revoked', true);
                }
            })
            ->latest('issue_date')
            ->paginate(20);

        $statistics = $this->getStatistics();

        return view('training.certificates.index', compact('certificates', 'statistics'));
    }

    /**
     * Display current user's certificates.
     *
     * @return \Illuminate\View\View
     */
    public function myCertificates(): View
    {
        // Any authenticated user can view their own certificates
        abort_unless(auth()->check(), 403);

        $certificates = TrainingCertificate::with(['trainingPackage'])
            ->where('user_id', auth()->id())
            ->latest('issue_date')
            ->paginate(10);

        return view('training.certificates.my', compact('certificates'));
    }

    /**
     * Display the specified certificate.
     *
     * @param \App\Models\TrainingCertificate $certificate
     * @return \Illuminate\View\View
     */
    public function show(TrainingCertificate $certificate): View
    {
        abort_unless(
            auth()->user()->can('view training certificates') ||
            $certificate->user_id === auth()->id(),
            403
        );

        $certificate->load(['user', 'trainingPackage', 'registration']);

        return view('training.certificates.show', compact('certificate'));
    }

    /**
     * Download a certificate.
     *
     * @param \App\Models\TrainingCertificate $certificate
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse|\Illuminate\Http\RedirectResponse
     */
    public function download(TrainingCertificate $certificate)
    {
        abort_unless(
            auth()->user()->can('download training certificates') ||
            $certificate->user_id === auth()->id(),
            403
        );

        if ($certificate->is_revoked) {
            return back()->with('error', 'This certificate has been revoked and cannot be downloaded.');
        }

        try {
            return $this->certificationService->downloadCertificate(
                $certificate,
                request('format', 'pdf')
            );
        } catch (\Exception $e) {
            return back()->with('error', 'Failed to download certificate: ' . $e->getMessage());
        }
    }

    /**
     * Generate a certificate for a registration.
     *
     * @param \App\Models\TrainingRegistration $registration
     * @return \Illuminate\Http\RedirectResponse
     */
    public function generate(TrainingRegistration $registration): RedirectResponse
    {
        abort_unless(auth()->user()->can('generate training certificates'), 403);

        if ($registration->status !== 'completed') {
            return back()->with('error', 'Registration must be completed before generating a certificate.');
        }

        try {
            $certificate = $this->certificationService->generateCertificate($registration);

            if (!$certificate) {
                return back()->with('error', 'Certificate could not be generated. The training package may not support certificates.');
            }

            return redirect()
                ->route('training.certificates.show', $certificate)
                ->with('success', 'Certificate generated successfully!');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to generate certificate: ' . $e->getMessage());
        }
    }

    /**
     * Regenerate a certificate.
     *
     * @param \App\Models\TrainingCertificate $certificate
     * @return \Illuminate\Http\RedirectResponse
     */
    public function regenerate(TrainingCertificate $certificate): RedirectResponse
    {
        abort_unless(auth()->user()->can('generate training certificates'), 403);

        try {
            $success = $this->certificationService->regenerateCertificate($certificate);

            if ($success) {
                return back()->with('success', 'Certificate regenerated successfully!');
            }

            return back()->with('error', 'Failed to regenerate certificate.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to regenerate certificate: ' . $e->getMessage());
        }
    }

    /**
     * Revoke a certificate.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Models\TrainingCertificate $certificate
     * @return \Illuminate\Http\RedirectResponse
     */
    public function revoke(Request $request, TrainingCertificate $certificate): RedirectResponse
    {
        abort_unless(auth()->user()->can('revoke training certificates'), 403);

        $validated = $request->validate([
            'revoke_reason' => 'required|string|max:500',
        ]);

        try {
            $this->certificationService->revokeCertificate(
                $certificate,
                auth()->id(),
                $validated['revoke_reason']
            );

            return back()->with('success', 'Certificate revoked successfully.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to revoke certificate: ' . $e->getMessage());
        }
    }

    /**
     * Restore a revoked certificate.
     *
     * @param \App\Models\TrainingCertificate $certificate
     * @return \Illuminate\Http\RedirectResponse
     */
    public function restore(TrainingCertificate $certificate): RedirectResponse
    {
        abort_unless(auth()->user()->can('revoke training certificates'), 403);

        try {
            $this->certificationService->restoreCertificate($certificate);

            return back()->with('success', 'Certificate restored successfully.');

        } catch (\Exception $e) {
            return back()->with('error', 'Failed to restore certificate: ' . $e->getMessage());
        }
    }

    /**
     * API endpoint for certificate verification.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function apiVerify(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'verification_code' => 'required|string',
        ]);

        $result = $this->certificationService->verifyCertificate($validated['verification_code']);

        return response()->json($result);
    }

    /**
     * Get certificate statistics.
     *
     * @return array
     */
    protected function getStatistics(): array
    {
        return [
            'total' => TrainingCertificate::count(),
            'valid' => TrainingCertificate::where('is_revoked', false)->count(),
            'revoked' => TrainingCertificate::where('is_revoked', true)->count(),
            'this_month' => TrainingCertificate::whereMonth('issue_date', now()->month)
                ->whereYear('issue_date', now()->year)
                ->count(),
            'verifications' => TrainingCertificate::sum('verification_count'),
        ];
    }
}
