<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Services\SchoolYears\SchoolYearClosureService;
use App\Services\SchoolYears\SchoolYearResolver;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;

class SchoolYearAdminPageController extends Controller
{
    public function __construct(
        private SchoolYearClosureService $service,
        private SchoolYearResolver $resolver
    ) {
    }

    public function show(Request $request): View
    {
        $years = $this->service->list();
        $selectedId = (int) ($request->query('year') ?? 0);
        $activeYear = collect($years)->firstWhere('is_current', true);

        $defaultNext = $activeYear
            ? ($this->resolver->suggestNextName((string) $activeYear['name']) ?? '')
            : '';
        [$defaultStart, $defaultEnd] = $defaultNext !== ''
            ? $this->resolver->inferDatesFromName($defaultNext)
            : ['', ''];

        return view('admin.school-years', [
            'pageConfig' => [
                'jwt' => JWTAuth::fromUser($request->user()),
                'selected_year_id' => $selectedId,
                'docs_url' => url('/docs'),
                'default_draft' => [
                    'name' => $defaultNext,
                    'start_date' => $defaultStart,
                    'end_date' => $defaultEnd,
                ],
                'api' => [
                    'index' => url('/api/v1/school-years'),
                    'store' => url('/api/v1/school-years'),
                    'update' => url('/api/v1/school-years/__ID__'),
                    'summary' => url('/api/v1/school-years/__ID__/summary'),
                    'validate_close' => url('/api/v1/school-years/__ID__/validate-close'),
                    'preview_close' => url('/api/v1/school-years/__ID__/preview-close'),
                    'close' => url('/api/v1/school-years/__ID__/close'),
                    'reopen' => url('/api/v1/school-years/__ID__/reopen'),
                    'parent_balances' => url('/api/v1/school-years/__ID__/parent-balances'),
                    'promotion_preview' => url('/api/v1/school-years/__ID__/promotion-preview'),
                ],
            ],
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $payload = $request->validate([
            'name' => ['required', 'string', 'max:50'],
            'start_date' => ['required', 'date'],
            'end_date' => ['required', 'date', 'after:start_date'],
        ]);

        try {
            $year = $this->service->createYear($payload, optional($request->user())->id);
        } catch (ValidationException $e) {
            throw $e;
        }

        return redirect()
            ->route('admin.school-years', ['year' => $year['id']])
            ->with('status', sprintf('Draft school year %s created.', $year['name']));
    }

    public function update(Request $request, int $schoolYear): RedirectResponse
    {
        $payload = $request->validate([
            'name' => ['required', 'string', 'max:50'],
            'start_date' => ['required', 'date'],
            'end_date' => ['required', 'date', 'after:start_date'],
        ]);

        $updated = $this->service->updateYear($schoolYear, $payload, optional($request->user())->id);

        return redirect()
            ->route('admin.school-years', ['year' => $updated['id']])
            ->with('status', sprintf('School year %s updated.', $updated['name']));
    }

    public function validateClose(Request $request, int $schoolYear): JsonResponse
    {
        return response()->json([
            'ok' => true,
            'validation' => $this->service->validateClose($schoolYear, $this->validatedClosePayload($request)),
        ]);
    }

    public function previewClose(Request $request, int $schoolYear): JsonResponse
    {
        return response()->json([
            'ok' => true,
            'data' => $this->service->previewClose($schoolYear, $this->validatedClosePayload($request)),
        ]);
    }

    public function close(Request $request, int $schoolYear): RedirectResponse
    {
        $payload = $this->validatedClosePayload($request);
        $payload['confirmation'] = (string) $request->validate([
            'confirmation' => ['required', 'string', 'max:80'],
        ])['confirmation'];

        $result = $this->service->close($schoolYear, $payload, optional($request->user())->id);

        return redirect()
            ->route('admin.school-years', ['year' => $result['new_school_year']['id']])
            ->with('status', sprintf(
                'Closed %s and opened %s.',
                $result['closed_school_year']['name'],
                $result['new_school_year']['name']
            ));
    }

    public function reopen(Request $request, int $schoolYear): RedirectResponse
    {
        $year = $this->service->reopen($schoolYear, optional($request->user())->id);

        return redirect()
            ->route('admin.school-years', ['year' => $year['id']])
            ->with('status', sprintf('School year %s is now active.', $year['name']));
    }

    private function validatedClosePayload(Request $request): array
    {
        return $request->validate([
            'new_school_year' => ['required', 'array'],
            'new_school_year.name' => ['required', 'string', 'max:50'],
            'new_school_year.start_date' => ['required', 'date'],
            'new_school_year.end_date' => ['required', 'date', 'after:new_school_year.start_date'],
            'transfer_unpaid_balances' => ['nullable', 'boolean'],
        ]);
    }
}
