<?php

namespace App\Http\Controllers;

use App\Models\LearningMaterial;
use App\Models\SchoolClass;
use App\Models\Section;
use App\Models\Subject;
use App\Support\BranchContext;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class LearningMaterialController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [
            new Middleware('can:lms.view', only: ['index', 'show']),
            new Middleware('can:lms.create', only: ['create', 'store']),
            new Middleware('can:lms.update', only: ['edit', 'update']),
            new Middleware('can:lms.delete', only: ['destroy']),
        ];
    }

    public function index(Request $request): View
    {
        $filters = $request->only(['class_id', 'type']);

        $materials = LearningMaterial::with(['schoolClass', 'subject', 'teacher'])
            ->withCount('submissions')
            ->when($filters['class_id'] ?? null, fn ($q, $v) => $q->where('class_id', $v))
            ->when($filters['type'] ?? null, fn ($q, $v) => $q->where('type', $v))
            ->latest()->paginate(20)->withQueryString();

        return view('lms.index', [
            'materials' => $materials,
            'classes' => SchoolClass::active()->orderBy('level')->get(),
            'filters' => $filters,
        ]);
    }

    public function create(): View
    {
        return view('lms.create', $this->formData(new LearningMaterial()));
    }

    public function store(Request $request, BranchContext $context): RedirectResponse
    {
        $data = $this->validateData($request);
        // Branch follows the chosen class (Super Admin may be on "All Branches").
        $data['branch_id'] = SchoolClass::findOrFail($data['class_id'])->branch_id;
        $data['posted_by'] = auth()->id();
        $data['attachment'] = $this->storeFile($request, $data['branch_id']);

        LearningMaterial::create($data);

        return redirect()->route('materials.index')->with('success', ucfirst($data['type']).' posted.');
    }

    public function show(LearningMaterial $material): View
    {
        $material->load(['schoolClass', 'section', 'subject', 'teacher', 'submissions.student']);

        return view('lms.show', compact('material'));
    }

    public function edit(LearningMaterial $material): View
    {
        return view('lms.edit', $this->formData($material));
    }

    public function update(Request $request, LearningMaterial $material): RedirectResponse
    {
        $data = $this->validateData($request);
        if ($request->hasFile('attachment')) {
            $this->deleteFile($material->attachment);
            $data['attachment'] = $this->storeFile($request, $material->branch_id);
        } else {
            unset($data['attachment']);
        }

        $material->update($data);

        return redirect()->route('materials.show', $material)->with('success', 'Updated.');
    }

    public function destroy(LearningMaterial $material): RedirectResponse
    {
        $this->deleteFile($material->attachment);
        $material->delete();

        return redirect()->route('materials.index')->with('success', 'Deleted.');
    }

    private function formData(LearningMaterial $material): array
    {
        return [
            'material' => $material,
            'classes' => SchoolClass::active()->orderBy('level')->get(),
            'sections' => Section::active()->get(['id', 'class_id', 'name']),
            'subjects' => Subject::active()->orderBy('name')->get(['id', 'name', 'branch_id']),
        ];
    }

    private function validateData(Request $request): array
    {
        return $request->validate([
            'class_id' => ['required', 'exists:classes,id'],
            'section_id' => ['nullable', 'exists:sections,id'],
            'subject_id' => ['nullable', 'exists:subjects,id'],
            'type' => ['required', Rule::in(array_keys(LearningMaterial::TYPES))],
            'title' => ['required', 'string', 'max:200'],
            'description' => ['nullable', 'string'],
            'due_date' => ['nullable', 'date'],
            'attachment' => ['nullable', 'file', 'mimes:pdf,doc,docx,jpg,jpeg,png,zip', 'max:8192'],
            'is_published' => ['nullable', 'boolean'],
        ]) + ['is_published' => $request->boolean('is_published', true)];
    }

    private function storeFile(Request $request, int $branchId): ?string
    {
        return $request->hasFile('attachment')
            ? $request->file('attachment')->store("branches/{$branchId}/lms", 'public')
            : null;
    }

    private function deleteFile(?string $path): void
    {
        if ($path && Storage::disk('public')->exists($path)) {
            Storage::disk('public')->delete($path);
        }
    }
}
