<?php

namespace App\Http\Controllers\SelfPaced\Dashboard;

use App\Http\Controllers\Controller;
use App\Models\SelfPaced\Course;
use App\Models\SelfPaced\ExamResult;
use App\Models\SelfPaced\SelfPacedCertificate;
use App\Services\SelfPacedCertificateService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Response;

class CertificateController extends Controller
{
    public function __construct(protected SelfPacedCertificateService $certificateService)
    {
        //
    }

    // =========================================================================
    // LIST
    // =========================================================================

    public function index(Request $request)
    {
        $query = SelfPacedCertificate::with(['user', 'course', 'enrollment']);

        // Real-time search by holder name, course, or certificate number
        if ($search = $request->get('search')) {
            $query->where(function ($q) use ($search) {
                $q->where('certificate_number', 'like', "%{$search}%")
                  ->orWhere('verification_code', 'like', "%{$search}%")
                  ->orWhereHas('user', fn ($u) => $u->where('name', 'like', "%{$search}%"))
                  ->orWhereHas('course', fn ($c) => $c->where('title', 'like', "%{$search}%"));
            });
        }

        // Filter by course
        if ($courseId = $request->get('course_id')) {
            $query->where('course_id', $courseId);
        }

        // Filter by revocation status
        if ($request->has('is_revoked') && $request->get('is_revoked') !== '') {
            $query->where('is_revoked', (bool) $request->get('is_revoked'));
        }

        // Filter by date range
        if ($from = $request->get('date_from')) {
            $query->whereDate('issue_date', '>=', $from);
        }
        if ($to = $request->get('date_to')) {
            $query->whereDate('issue_date', '<=', $to);
        }

        $certificates = $query->latest()->paginate(20)->withQueryString();
        $courses      = Course::orderBy('title')->get(['id', 'title']);

        if ($request->ajax()) {
            return response()->json([
                'html' => view('self-paced.dashboard.certificates.partials.table', compact('certificates'))->render(),
            ]);
        }

        return view('self-paced.dashboard.certificates.index', compact('certificates', 'courses'));
    }

    // =========================================================================
    // DETAIL
    // =========================================================================

    public function show(SelfPacedCertificate $certificate)
    {
        $certificate->load(['user', 'course', 'enrollment', 'result', 'generator', 'revoker']);

        return view('self-paced.dashboard.certificates.show', compact('certificate'));
    }

    // =========================================================================
    // REVOKE
    // =========================================================================

    public function revoke(Request $request, SelfPacedCertificate $certificate)
    {
        $request->validate([
            'revocation_reason' => 'required|string|max:1000',
        ]);

        if ($certificate->isRevoked()) {
            return back()->with('error', 'Certificate is already revoked.');
        }

        $certificate->revoke(Auth::id(), $request->input('revocation_reason'));

        return back()->with('success', "Certificate {$certificate->certificate_number} has been revoked.");
    }

    // =========================================================================
    // REGENERATE PDF
    // =========================================================================

    public function regenerate(Request $request, SelfPacedCertificate $certificate)
    {
        $format = $request->input('format', 'portrait');

        try {
            $this->certificateService->regeneratePdf($certificate, $format);
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', 'Certificate PDF regenerated successfully.');
    }

    // =========================================================================
    // DOWNLOAD PDF
    // =========================================================================

    public function download(Request $request, SelfPacedCertificate $certificate)
    {
        $format = $request->input('format', 'portrait');

        try {
            $pdfContent = $this->certificateService->streamPdf($certificate, $format);
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }

        $filename = 'certificate-' . $certificate->certificate_number . '.pdf';

        return Response::make($pdfContent, 200, [
            'Content-Type'        => 'application/pdf',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ]);
    }

    // =========================================================================
    // MANUAL GENERATE (for a passed result that has no certificate yet)
    // =========================================================================

    public function generate(Request $request, ExamResult $result)
    {
        if (!$result->passed) {
            return back()->with('error', 'Cannot issue a certificate for a failed exam result.');
        }

        $existing = SelfPacedCertificate::where('result_id', $result->id)->first();
        if ($existing) {
            return redirect()
                ->route('self-paced.dashboard.certificates.show', $existing)
                ->with('info', 'Certificate already exists for this result.');
        }

        try {
            $certificate = $this->certificateService->generate(
                result: $result,
                generatedBy: Auth::id(),
                format: $request->input('format', 'portrait')
            );
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('self-paced.dashboard.certificates.show', $certificate)
            ->with('success', "Certificate {$certificate->certificate_number} issued successfully.");
    }

    // =========================================================================
    // EXPORT
    // =========================================================================

    public function export(Request $request)
    {
        $query = SelfPacedCertificate::with(['user', 'course']);

        if ($courseId = $request->get('course_id')) {
            $query->where('course_id', $courseId);
        }
        if ($request->has('is_revoked') && $request->get('is_revoked') !== '') {
            $query->where('is_revoked', (bool) $request->get('is_revoked'));
        }
        if ($from = $request->get('date_from')) {
            $query->whereDate('issue_date', '>=', $from);
        }
        if ($to = $request->get('date_to')) {
            $query->whereDate('issue_date', '<=', $to);
        }

        $certificates = $query->latest()->get();
        $filename     = 'certificates-' . now()->format('Y-m-d') . '.csv';

        $headers = [
            'Content-Type'        => 'text/csv',
            'Content-Disposition' => "attachment; filename=\"{$filename}\"",
        ];

        $callback = function () use ($certificates) {
            $handle = fopen('php://output', 'w');

            fputcsv($handle, [
                'ID', 'Certificate Number', 'Verification Code', 'Holder Name',
                'Holder Email', 'Course', 'Issue Date', 'Status',
                'Revoked At', 'Revocation Reason', 'Verification Count',
            ]);

            foreach ($certificates as $cert) {
                fputcsv($handle, [
                    $cert->id,
                    $cert->certificate_number,
                    $cert->verification_code,
                    $cert->user->name ?? 'N/A',
                    $cert->user->email ?? 'N/A',
                    $cert->course->title ?? 'N/A',
                    $cert->issue_date->format('Y-m-d'),
                    $cert->getStatusText(),
                    $cert->revoked_at?->format('Y-m-d H:i:s') ?? '',
                    $cert->revocation_reason ?? '',
                    $cert->verification_count,
                ]);
            }

            fclose($handle);
        };

        return Response::stream($callback, 200, $headers);
    }
}
