<?php

namespace App\Services;

use Illuminate\Support\Facades\Route;

/**
 * Laravel named routes (`route()`), cookie-session URLs, SPA paths, and absolute URLs for `public/` paths.
 */
final class ApplicationUrlService
{
    /** Absolute URL for a path under `public/` (e.g. `/docs/openapi_*.yaml`). */
    public function absolutePublicPathUrl(string $path): string
    {
        $path = trim($path);
        if ($path === '') {
            return url('/');
        }
        if (! str_starts_with($path, '/')) {
            $path = '/'.$path;
        }

        return url($path);
    }

    /** Named route `docs.swagger.catalog`. */
    public function docsSwaggerCatalogUrl(bool $absolute = true): string
    {
        return route('docs.swagger.catalog', [], $absolute);
    }

    /** Named route `docs.swagger-json`; SPA bootstrap often passes `$absolute = false`. */
    public function docsSwaggerMergedJsonUrl(bool $absolute = true): string
    {
        return route('docs.swagger-json', [], $absolute);
    }

    /** Named route `api-docs.public`. */
    public function apiDocsPublicBootstrapUrl(bool $absolute = true): string
    {
        return route('api-docs.public', [], $absolute);
    }

    /** Named route `api-docs.index`. */
    public function apiDocsAdminBootstrapUrl(bool $absolute = true): string
    {
        return route('api-docs.index', [], $absolute);
    }

    /** Named route `docs.home` (GET `/`; usually redirects to the docs client). */
    public function docsHomeUrl(bool $absolute = true): string
    {
        if (Route::has('docs.home')) {
            return route('docs.home', [], $absolute);
        }

        return $absolute ? url('/app/home') : '/app/home';
    }

    /** Cookie-session SPA paths from `routes/web.php`. Named route `login`. */
    public function webLoginUrl(bool $absolute = true): string
    {
        return route('login', [], $absolute);
    }

    /** Named route `auth.session.logout`. */
    public function webLogoutUrl(bool $absolute = true): string
    {
        return route('auth.session.logout', [], $absolute);
    }

    /** Named route `auth.session.ping` (POST). */
    public function webSessionPingUrl(bool $absolute = true): string
    {
        return route('auth.session.ping', [], $absolute);
    }

    /** Named route `auth.session.check-timeout`. */
    public function webSessionCheckTimeoutUrl(bool $absolute = true): string
    {
        return route('auth.session.check-timeout', [], $absolute);
    }

    /** Named route `auth.session.select-role` (GET). */
    public function webSelectRoleUrl(bool $absolute = true): string
    {
        return route('auth.session.select-role', [], $absolute);
    }

    /** SPA registration confirmation email (`/user/confirm/{token}`). */
    public function spaRegistrationConfirmUrl(string $token): string
    {
        return url('/user/confirm/'.$token);
    }

    /** Parent portal invoice (`parent/invoices/{id}`). */
    public function spaParentInvoiceDetailUrl(int|string $invoiceId): string
    {
        return url('parent/invoices/'.$invoiceId);
    }

    /** Parent portal invoice view (`parent/invoices/view/{id}`). */
    public function spaParentInvoiceViewUrl(int|string $invoiceId): string
    {
        return url('parent/invoices/view/'.$invoiceId);
    }

    public function spaParentInvoicesIndexUrl(): string
    {
        return url('parent/invoices');
    }

    public function spaAdminPrintRequestsUrl(): string
    {
        return url('/admin/print-requests');
    }

    public function spaAdministratorCalendarViewUrl(): string
    {
        return url('/administrator/calendar_view');
    }

    public function inviteConfirmUrl(string $plainToken): string
    {
        return route('api.invite.confirm', ['token' => $plainToken]);
    }

    public function inviteSetPasswordFormUrl(int $authorizedUserId, string $token): string
    {
        return route('api.invite.set-password-form', [
            'authorizedUserId' => $authorizedUserId,
            'token' => $token,
        ]);
    }

    public function timeoffNotifyUrl(string $token): string
    {
        return route('api.timeoff.notify', ['token' => $token]);
    }

    /** Served by {@see \App\Http\Controllers\Api\Reports\FilesController::receipt} (uploads/receipts). */
    public function forReceiptStorage(?string $filename): ?string
    {
        if (!$filename) {
            return null;
        }
        $safe = basename(trim($filename));

        return $safe !== '' ? route('api.v1.files.receipt', ['name' => $safe]) : null;
    }

    /** Served by {@see \App\Http\Controllers\Api\Reports\FilesController::reimb} (uploads/reimbursements). */
    public function forReimbursementStorage(?string $filename): ?string
    {
        if (!$filename) {
            return null;
        }
        $safe = basename(trim($filename));

        return $safe !== '' ? route('api.v1.files.reimbursement', ['name' => $safe]) : null;
    }

    public function forReimbursementAdminCheckFile(string $filename, string $mode = 'inline'): string
    {
        return route('api.v1.finance.reimbursements.admin-file', [
            'name' => $filename,
            'mode' => $mode,
        ]);
    }

    public function paypalExecuteReturnUrl(): string
    {
        return route('api.v1.finance.paypal.execute');
    }

    public function paypalCancelUrl(): string
    {
        return route('api.v1.finance.paypal.cancel');
    }

    public function studentReportCardUrl(int $studentId): string
    {
        return route('api.v1.students.report-card', ['studentId' => $studentId]);
    }

    public function forClassProgressAttachment(int|string $attachmentId): string
    {
        return route('api.v1.class-progress.attachment', ['attachment' => $attachmentId]);
    }

    /**
     * @return array{template_endpoint: string, list_endpoint: string, rest_prefix: string, list_data_endpoint: string}
     */
    public function attendanceCommentTemplateBootstrapData(): array
    {
        return [
            'template_endpoint' => route('api.v1.attendance-templates.legacy'),
            'list_endpoint' => route('api.v1.attendance-templates.legacy'),
            'rest_prefix' => route('api.v1.attendance-comment-templates.index'),
            'list_data_endpoint' => route('api.v1.attendance-comment-templates.list-data'),
        ];
    }
}
