<?php

namespace App\Controllers\Administrator;

use App\Controllers\BaseController;
use App\Models\SchoolYearModel;
use App\Support\SchoolYear\SchoolYearStatus;
use Throwable;

class SchoolYearController extends BaseController
{
    private SchoolYearModel $schoolYearModel;

    public function __construct()
    {
        $this->schoolYearModel = new SchoolYearModel();
    }

    public function index()
    {
        $schoolYears = $this->schoolYearModel
            ->orderBy('name', 'DESC')
            ->findAll();

        $activeYear = null;
        $nextDraftYear = null;
        $closingYear = null;
        $archivedCount = 0;

        foreach ($schoolYears as $year) {
            $status = (string) ($year['status'] ?? '');
            if ($status === SchoolYearStatus::ACTIVE && $activeYear === null) {
                $activeYear = $year;
            }
            if ($status === SchoolYearStatus::DRAFT && $nextDraftYear === null) {
                $nextDraftYear = $year;
            }
            if ($status === SchoolYearStatus::CLOSING && $closingYear === null) {
                $closingYear = $year;
            }
            if ($status === SchoolYearStatus::ARCHIVED) {
                $archivedCount++;
            }
        }

        return view('school_years/index', [
            'schoolYears' => $schoolYears,
            'statuses' => SchoolYearStatus::ALL,
            'activeYear' => $activeYear,
            'nextDraftYear' => $nextDraftYear,
            'closingYear' => $closingYear,
            'archivedCount' => $archivedCount,
            'latestTransitions' => service('schoolYearManagement')->latestTransitionByYear(),
            'yearVerification' => $this->verificationByYear($schoolYears),
            'schoolYearNamesById' => array_column($schoolYears, 'name', 'id'),
        ]);
    }

    public function store()
    {
        try {
            service('schoolYearManagement')->createDraft($this->request->getPost(), $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'Draft school year created.');
        } catch (Throwable $e) {
            return redirect()->back()->withInput()->with('error', $e->getMessage());
        }
    }

    public function update(int $id)
    {
        try {
            service('schoolYearManagement')->updateMetadata($id, $this->request->getPost(), $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'School year metadata updated.');
        } catch (Throwable $e) {
            return redirect()->back()->withInput()->with('error', $e->getMessage());
        }
    }

    public function activate(int $id)
    {
        try {
            if ($this->request->getPost('confirm_activation') !== '1') {
                return redirect()->to('/administrator/school-years')->with('error', 'Activation confirmation is required.');
            }

            service('schoolYearManagement')->activate($id, $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'School year activated. Any previous active year is now in closing.');
        } catch (Throwable $e) {
            return redirect()->to('/administrator/school-years')->with('error', $e->getMessage());
        }
    }

    public function deleteDraft(int $id)
    {
        try {
            service('schoolYearManagement')->deleteDraft($id, $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'Draft school year deleted.');
        } catch (Throwable $e) {
            return redirect()->to('/administrator/school-years')->with('error', $e->getMessage());
        }
    }

    public function archive(int $id)
    {
        try {
            service('schoolYearManagement')->archive($id, $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'School year archived.');
        } catch (Throwable $e) {
            return redirect()->to('/administrator/school-years')->with('error', $e->getMessage());
        }
    }

    public function reopen(int $id)
    {
        try {
            service('schoolYearManagement')->reopen($id, (string) $this->request->getPost('reason'), $this->userId());
            return redirect()->to('/administrator/school-years')->with('success', 'School year reopened.');
        } catch (Throwable $e) {
            return redirect()->to('/administrator/school-years')->with('error', $e->getMessage());
        }
    }

    private function userId(): ?int
    {
        $id = session('user_id') ?? session('id');

        return is_numeric($id) ? (int) $id : null;
    }

    private function verificationByYear(array $schoolYears): array
    {
        $db = db_connect();
        $verification = [];

        $hasStudentClass = $db->tableExists('student_class');
        $hasStudentDecisions = $db->tableExists('student_decisions');
        $hasPromotionQueue = $db->tableExists('promotion_queue');
        $hasInvoices = $db->tableExists('invoices');
        $hasClosingBatches = $db->tableExists('school_year_closing_batches');

        foreach ($schoolYears as $year) {
            $id = (int) ($year['id'] ?? 0);
            $name = (string) ($year['name'] ?? '');
            if ($id <= 0 || $name === '') {
                continue;
            }

            $summary = [
                'students' => 0,
                'decisions' => 0,
                'promoted' => 0,
                'queued' => 0,
                'carry_forward_balance' => 0.0,
                'positive_balance' => 0.0,
                'credit_balance' => 0.0,
                'closing_status' => '',
            ];

            if ($hasStudentClass && $db->fieldExists('school_year', 'student_class')) {
                $row = $db->table('student_class')
                    ->select('COUNT(DISTINCT student_id) AS total', false)
                    ->where('school_year', $name)
                    ->get()
                    ->getRowArray();
                $summary['students'] = (int) ($row['total'] ?? 0);
            }

            if ($hasStudentDecisions && $db->fieldExists('school_year', 'student_decisions')) {
                $row = $db->table('student_decisions')
                    ->select('COUNT(DISTINCT student_id) AS decisions', false)
                    ->select("COUNT(DISTINCT CASE WHEN LOWER(decision) = 'pass' THEN student_id END) AS promoted", false)
                    ->where('school_year', $name)
                    ->get()
                    ->getRowArray();
                $summary['decisions'] = (int) ($row['decisions'] ?? 0);
                $summary['promoted'] = (int) ($row['promoted'] ?? 0);
            }

            if ($hasPromotionQueue && $db->fieldExists('school_year_from', 'promotion_queue')) {
                $row = $db->table('promotion_queue')
                    ->select('COUNT(DISTINCT student_id) AS total', false)
                    ->where('school_year_from', $name)
                    ->get()
                    ->getRowArray();
                $summary['queued'] = (int) ($row['total'] ?? 0);
            }

            if ($hasInvoices && $db->fieldExists('school_year', 'invoices')) {
                $row = $db->table('invoices')
                    ->select('COALESCE(SUM(balance), 0) AS carry_forward_balance')
                    ->select('COALESCE(SUM(CASE WHEN balance > 0 THEN balance ELSE 0 END), 0) AS positive_balance', false)
                    ->select('COALESCE(SUM(CASE WHEN balance < 0 THEN ABS(balance) ELSE 0 END), 0) AS credit_balance', false)
                    ->where('school_year', $name)
                    ->get()
                    ->getRowArray();
                $summary['carry_forward_balance'] = round((float) ($row['carry_forward_balance'] ?? 0), 2);
                $summary['positive_balance'] = round((float) ($row['positive_balance'] ?? 0), 2);
                $summary['credit_balance'] = round((float) ($row['credit_balance'] ?? 0), 2);
            }

            if ($hasClosingBatches) {
                $batch = $db->table('school_year_closing_batches')
                    ->select('status')
                    ->where('source_school_year_id', $id)
                    ->orderBy('id', 'DESC')
                    ->get(1)
                    ->getRowArray();
                $summary['closing_status'] = (string) ($batch['status'] ?? '');
            }

            $verification[$id] = $summary;
        }

        return $verification;
    }
}
