<?php

namespace App\Filament\Pages;

use App\Models\Clasa;
use App\Models\Corigenta;
use App\Models\Elev;
use App\Models\Medie;
use App\Models\NotaPurtare;
use App\Models\Nota;
use App\Models\Perioada;
use App\Models\SemnaturaCatalog;
use App\Models\SituatieScolara;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;

class IncheiereaSituatiei extends Page
{
    protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-check';
    protected static ?string $navigationLabel = 'Încheierea situației';
    protected static ?string $title = 'Încheierea situației școlare';
    protected static ?string $navigationGroup = 'Catalog';
    protected static ?int $navigationSort = 10;
    protected static string $view = 'filament.pages.incheierea-situatiei';

    public ?int $clasaId = null;
    public ?int $perioadaId = null;

    public static function canAccess(): bool
    {
        $user = Auth::user();
        return $user && $user->hasAnyRole(['admin', 'director', 'secretariat', 'diriginte', 'profesor']);
    }

    public function getClase(): \Illuminate\Support\Collection
    {
        $user = Auth::user();
        $query = Clasa::with('perioade');

        if ($user->hasAnyRole(['admin', 'director', 'secretariat'])) {
            return $query->get();
        }

        if ($user->hasRole('diriginte')) {
            return $query->where('diriginte_user_id', $user->id)->get();
        }

        if ($user->hasRole('profesor')) {
            $clasaIds = $user->materii()->pluck('clasa_id')->unique();
            return $query->whereIn('id', $clasaIds)->get();
        }

        return collect();
    }

    public function getPerioade(): \Illuminate\Support\Collection
    {
        if (!$this->clasaId) return collect();
        return Perioada::where('clasa_id', $this->clasaId)->orderBy('ordine')->get();
    }

    public function getTableData(): array
    {
        if (!$this->clasaId || !$this->perioadaId) return [];

        $user = Auth::user();
        $clasa = Clasa::with('materii')->find($this->clasaId);
        $perioada = Perioada::find($this->perioadaId);
        if (!$clasa || !$perioada) return [];

        $materii = $clasa->materii;
        $elevi = Elev::where('clasa_id', $clasa->id)->orderBy('nume')->orderBy('prenume')->get();

        $isDiriginte = $user->hasRole('diriginte') && $clasa->diriginte_user_id === $user->id;
        $isStaff = $user->hasAnyRole(['admin', 'director', 'secretariat']);

        $rows = [];
        foreach ($elevi as $elev) {
            $row = [
                'elev_id' => $elev->id,
                'nume' => $elev->nume . ' ' . $elev->prenume,
                'materii' => [],
                'nota_purtare' => null,
                'media_generala' => null,
                'status' => null,
                'situatie_incheiat' => false,
            ];

            foreach ($materii as $materie) {
                $noteCurente = Nota::withoutGlobalScopes()
                    ->where('elev_id', $elev->id)
                    ->where('materie_id', $materie->id)
                    ->where('perioada_id', $perioada->id)
                    ->whereNotIn('tip', ['final', 'teza'])
                    ->pluck('valoare');

                $note = Nota::withoutGlobalScopes()
                    ->where('elev_id', $elev->id)
                    ->where('materie_id', $materie->id)
                    ->where('perioada_id', $perioada->id)
                    ->where('tip', '!=', 'final')
                    ->pluck('valoare');

                $mediaCalculata = null;
                if ($noteCurente->count() > 0) {
                    $mediaAritmetica = $noteCurente->avg();
                    if ($clasa->cu_teze) {
                        $teza = Nota::withoutGlobalScopes()
                            ->where('elev_id', $elev->id)
                            ->where('materie_id', $materie->id)
                            ->where('perioada_id', $perioada->id)
                            ->where('tip', 'teza')
                            ->value('valoare');
                        if ($teza !== null) {
                            $mediaCalculata = round((3 * $mediaAritmetica + $teza) / 4, 2);
                        } else {
                            $mediaCalculata = round($mediaAritmetica, 2);
                        }
                    } else {
                        $mediaCalculata = round($mediaAritmetica, 2);
                    }
                }
                $mediaFinala = $mediaCalculata !== null ? (int) round($mediaCalculata) : null;

                $medie = Medie::withoutGlobalScopes()
                    ->where('elev_id', $elev->id)
                    ->where('materie_id', $materie->id)
                    ->where('perioada_id', $perioada->id)
                    ->first();

                $canClose = ($user->hasAnyRole(['admin', 'director', 'secretariat']) ||
                    ($materie->user_id && $materie->user_id === $user->id) ||
                    $isDiriginte);

                $row['materii'][$materie->id] = [
                    'materie_nume' => $materie->nume,
                    'note' => $note->implode(', '),
                    'media_calculata' => $mediaCalculata,
                    'media_finala' => $medie?->media_finala ?? $mediaFinala,
                    'incheiat' => $medie?->incheiat ?? false,
                    'can_close' => $canClose && $mediaCalculata !== null,
                ];
            }

            $np = NotaPurtare::withoutGlobalScopes()
                ->where('elev_id', $elev->id)
                ->where('perioada_id', $perioada->id)
                ->first();
            $row['nota_purtare'] = $np?->valoare ?? 10;
            $row['nota_purtare_obs'] = $np?->observatii;

            $sit = SituatieScolara::withoutGlobalScopes()
                ->where('elev_id', $elev->id)
                ->where('perioada_id', $perioada->id)
                ->first();
            $row['media_generala'] = $sit?->media_generala;
            $row['status'] = $sit?->status ?? 'in_curs';
            $row['situatie_incheiat'] = $sit?->incheiat ?? false;

            $rows[] = $row;
        }

        $semnaturi = SemnaturaCatalog::where('clasa_id', $this->clasaId)
            ->where('perioada_id', $this->perioadaId)
            ->with('user')
            ->get();

        return [
            'materii' => $materii,
            'rows' => $rows,
            'can_incheie' => $isDiriginte || $isStaff,
            'semnaturi' => $semnaturi,
        ];
    }

    public function incheieMedia(int $elevId, int $materieId, int $mediaFinala): void
    {
        $user = Auth::user();

        Medie::withoutGlobalScopes()->updateOrCreate(
            ['elev_id' => $elevId, 'materie_id' => $materieId, 'perioada_id' => $this->perioadaId],
            [
                'media_calculata' => Nota::withoutGlobalScopes()
                    ->where('elev_id', $elevId)
                    ->where('materie_id', $materieId)
                    ->where('perioada_id', $this->perioadaId)
                    ->where('tip', '!=', 'final')
                    ->avg('valoare') ?? 0,
                'media_finala' => $mediaFinala,
                'incheiat' => true,
                'incheiat_de' => $user->id,
                'incheiat_la' => now(),
            ]
        );

        SemnaturaCatalog::updateOrCreate(
            [
                'user_id' => $user->id,
                'clasa_id' => $this->clasaId,
                'perioada_id' => $this->perioadaId,
                'materie_id' => $materieId,
                'tip' => 'incheiere_medie',
            ],
            [
                'ip_address' => request()->ip(),
                'detalii' => "Media {$mediaFinala} pentru elevul #{$elevId}",
                'semnat_la' => now(),
            ]
        );
    }

    public function salveazaNotaPurtare(int $elevId, int $valoare, ?string $observatii): void
    {
        $user = Auth::user();

        NotaPurtare::withoutGlobalScopes()->updateOrCreate(
            ['elev_id' => $elevId, 'perioada_id' => $this->perioadaId],
            [
                'valoare' => $valoare,
                'observatii' => $observatii,
                'adaugat_de' => $user->id,
                'adaugat_la' => now(),
            ]
        );
    }

    public function incheieSituatia(int $elevId): void
    {
        $user = Auth::user();
        $perioada = Perioada::find($this->perioadaId);
        $clasa = Clasa::with('materii')->find($this->clasaId);
        if (!$perioada || !$clasa) return;

        $medii = Medie::withoutGlobalScopes()
            ->where('elev_id', $elevId)
            ->where('perioada_id', $this->perioadaId)
            ->where('incheiat', true)
            ->get();

        $mediiFinale = $medii->pluck('media_finala');
        $mediaGenerala = $mediiFinale->count() > 0 ? round($mediiFinale->avg(), 2) : null;

        $np = NotaPurtare::withoutGlobalScopes()
            ->where('elev_id', $elevId)
            ->where('perioada_id', $this->perioadaId)
            ->first();
        $notaPurtare = $np?->valoare ?? 10;

        $corigente = $mediiFinale->filter(fn ($m) => $m < 5)->count();

        $absTotal = \App\Models\Absenta::withoutGlobalScopes()
            ->where('elev_id', $elevId)
            ->where('perioada_id', $this->perioadaId)
            ->count();
        $absNemot = \App\Models\Absenta::withoutGlobalScopes()
            ->where('elev_id', $elevId)
            ->where('perioada_id', $this->perioadaId)
            ->where('motivata', false)
            ->count();

        if ($corigente >= 3 || $notaPurtare < 6) {
            $status = 'repetent';
        } elseif ($corigente > 0) {
            $status = 'corigent';
        } elseif ($medii->count() < $clasa->materii->count()) {
            $status = 'in_curs';
        } else {
            $status = 'promovat';
        }

        if ($corigente > 0) {
            foreach ($medii->where('media_finala', '<', 5) as $medie) {
                Corigenta::withoutGlobalScopes()->updateOrCreate(
                    ['elev_id' => $elevId, 'materie_id' => $medie->materie_id, 'perioada_id' => $this->perioadaId],
                    [
                        'media_inainte' => $medie->media_calculata,
                        'status' => 'programat',
                    ]
                );
            }
        }

        SituatieScolara::withoutGlobalScopes()->updateOrCreate(
            ['elev_id' => $elevId, 'perioada_id' => $this->perioadaId],
            [
                'media_generala' => $mediaGenerala,
                'nota_purtare' => $notaPurtare,
                'status' => $status,
                'total_absente' => $absTotal,
                'absente_nemotivate' => $absNemot,
                'nr_corigente' => $corigente,
                'incheiat' => true,
                'incheiat_de' => $user->id,
                'incheiat_la' => now(),
            ]
        );

        SemnaturaCatalog::updateOrCreate(
            [
                'user_id' => $user->id,
                'clasa_id' => $this->clasaId,
                'perioada_id' => $this->perioadaId,
                'materie_id' => null,
                'tip' => 'incheiere_situatie',
            ],
            [
                'ip_address' => request()->ip(),
                'detalii' => "Situația elevului #{$elevId}: {$status}, media {$mediaGenerala}",
                'semnat_la' => now(),
            ]
        );
    }

    public function incheieToate(): void
    {
        $clasa = Clasa::find($this->clasaId);
        if (!$clasa) return;

        $elevi = Elev::where('clasa_id', $clasa->id)->get();
        foreach ($elevi as $elev) {
            $this->incheieSituatia($elev->id);
        }
    }
}
