<?php

namespace App\Providers;

use App\Services\Attendance\AttendancePolicyService;
use App\Services\Attendance\AttendanceRecordSyncService;
use App\Services\Attendance\SemesterRangeService;
use App\Services\Attendance\StudentAttendanceWriterService;
use App\Services\Attendance\TeacherAttendanceSubmissionService;
use App\Services\Attendance\AttendanceAutoPublishService;
use App\Services\Invoices\InvoiceConfigService;
use App\Services\Invoices\InvoiceGradeService;
use App\Services\Invoices\InvoiceTuitionService;
use App\Services\Staff\StaffTimeOffLinkService;
use App\Models\NavItem;
use App\Models\ClassSection;
use App\Models\IpAttempt;
use App\Models\LateSlipLog;
use App\Models\Message;
use App\Models\Preferences;
use App\Models\Staff;
use App\Models\SupportRequest;
use App\Models\Setting;
use App\Models\ClassProgressReport;
use App\Policies\NavItemPolicy;
use App\Policies\ClassSectionPolicy;
use App\Policies\IpAttemptPolicy;
use App\Policies\LateSlipLogPolicy;
use App\Policies\MessagePolicy;
use App\Policies\PreferencesPolicy;
use App\Policies\StaffPolicy;
use App\Policies\SupportRequestPolicy;
use App\Policies\SettingPolicy;
use App\Policies\ClassProgressReportPolicy;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Routing\Redirector;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(AttendancePolicyService::class);
        $this->app->singleton(SemesterRangeService::class);
        $this->app->singleton(AttendanceRecordSyncService::class);
        $this->app->singleton(StudentAttendanceWriterService::class);
        $this->app->singleton(TeacherAttendanceSubmissionService::class);
        $this->app->singleton(AttendanceAutoPublishService::class);
        $this->app->singleton(StaffTimeOffLinkService::class);

        $this->app->singleton(InvoiceConfigService::class);
        $this->app->bind(InvoiceGradeService::class, function ($app) {
            $config = $app->make(InvoiceConfigService::class);
            return new InvoiceGradeService($config->getGradeFee());
        });
        $this->app->bind(InvoiceTuitionService::class, function ($app) {
            $config = $app->make(InvoiceConfigService::class);
            return new InvoiceTuitionService(
                $app->make(InvoiceGradeService::class),
                $config->getGradeFee(),
                $config->getFirstStudentFee(),
                $config->getSecondStudentFee(),
                $config->getYouthFee(),
                $config->getTimezone()
            );
        });
    }

    public function boot(): void
    {
        Gate::policy(NavItem::class, NavItemPolicy::class);
        Gate::policy(ClassSection::class, ClassSectionPolicy::class);
        Gate::policy(IpAttempt::class, IpAttemptPolicy::class);
        Gate::policy(LateSlipLog::class, LateSlipLogPolicy::class);
        Gate::policy(Message::class, MessagePolicy::class);
        Gate::policy(Preferences::class, PreferencesPolicy::class);
        Gate::policy(Staff::class, StaffPolicy::class);
        Gate::policy(SupportRequest::class, SupportRequestPolicy::class);
        Gate::policy(Setting::class, SettingPolicy::class);
        Gate::policy(ClassProgressReport::class, ClassProgressReportPolicy::class);

        $this->app->resolving(FormRequest::class, function (FormRequest $request, $app): void {
            $request->setContainer($app)->setRedirector($app->make(Redirector::class));
        });
    }
}
