<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Support\AdminUserStore;
use App\Support\AreaContentStore;
use App\Support\QuestionStore;
use App\Support\RecommendationStore;
use App\Support\ReportStore;

final class AdminController
{
    private ReportStore $reportStore;
    private AdminUserStore $adminUserStore;
    private AreaContentStore $areaContentStore;
    private QuestionStore $questionStore;
    private RecommendationStore $recommendationStore;

    public function __construct()
    {
        $this->reportStore = new ReportStore();
        $this->adminUserStore = new AdminUserStore();
        $this->areaContentStore = new AreaContentStore();
        $this->questionStore = new QuestionStore();
        $this->recommendationStore = new RecommendationStore();
    }

    public function loginForm(): void
    {
        $locale = current_locale();

        render('admin.login', [
            'title' => trans('page_titles.administrator_login', [], $locale),
        ]);
    }

    public function login(): void
    {
        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/login');
        }

        $email = trim((string) ($_POST['email'] ?? ''));
        $password = (string) ($_POST['password'] ?? '');
        $matchedUser = $this->adminUserStore->findByEmail($email);

        if ($matchedUser === null || !password_verify($password, (string) $matchedUser['password_hash'])) {
            flash('error', trans('alerts.invalid_admin_credentials'));
            redirect('/admin/login');
        }

        $_SESSION['admin_user'] = [
            'name' => $matchedUser['name'],
            'email' => $matchedUser['email'],
        ];

        redirect('/admin/reports');
    }

    public function logout(): void
    {
        if (verify_csrf($_POST['_csrf'] ?? null)) {
            unset($_SESSION['admin_user']);
            flash('success', trans('alerts.signed_out', [], current_locale()));
        }

        redirect('/admin/login');
    }

    public function registrationForm(): void
    {
        require_admin();

        $locale = current_locale();

        render('admin.register', [
            'title' => trans('page_titles.administrator_registration', [], $locale),
        ]);
    }

    public function saveRegistration(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/register');
        }

        $payload = [
            'full_name' => trim((string) ($_POST['full_name'] ?? '')),
            'email' => trim((string) ($_POST['email'] ?? '')),
            'password' => (string) ($_POST['password'] ?? ''),
            'confirm_password' => (string) ($_POST['confirm_password'] ?? ''),
        ];

        set_old_input([
            'full_name' => $payload['full_name'],
            'email' => $payload['email'],
        ]);

        if ($payload['full_name'] === '') {
            flash('error', trans('alerts.admin_full_name_required'));
            redirect('/admin/register');
        }

        if (!filter_var($payload['email'], FILTER_VALIDATE_EMAIL)) {
            flash('error', trans('alerts.valid_email_required'));
            redirect('/admin/register');
        }

        if (strlen($payload['password']) < 8) {
            flash('error', trans('alerts.admin_password_minimum'));
            redirect('/admin/register');
        }

        if ($payload['password'] !== $payload['confirm_password']) {
            flash('error', trans('alerts.admin_password_mismatch'));
            redirect('/admin/register');
        }

        if ($this->adminUserStore->existsByEmail($payload['email'])) {
            flash('error', trans('alerts.admin_email_exists'));
            redirect('/admin/register');
        }

        try {
            $this->adminUserStore->create($payload['full_name'], $payload['email'], $payload['password']);
        } catch (\RuntimeException $exception) {
            flash('error', $exception->getMessage());
            redirect('/admin/register');
        }

        clear_old_input();
        flash('success', trans('alerts.admin_created'));
        redirect('/admin/reports');
    }

    public function reports(): void
    {
        require_admin();

        $reports = $this->reportStore->all();
        $search = trim((string) ($_GET['search'] ?? ''));

        if ($search !== '') {
            $reports = array_values(array_filter($reports, static function (array $report) use ($search): bool {
                $haystack = implode(' ', [
                    $report['reference'] ?? '',
                    $report['participant']['full_name'] ?? '',
                    $report['participant']['email'] ?? '',
                    $report['participant']['phone'] ?? '',
                ]);

                return stripos($haystack, $search) !== false;
            }));
        }

        render('admin.reports', [
            'title' => trans('page_titles.participant_reports'),
            'reports' => $reports,
            'search' => $search,
            'languages' => config('supported_languages', []),
            'activeSection' => 'reports',
        ]);
    }

    public function viewReport(): void
    {
        require_admin();

        $reference = trim((string) ($_GET['ref'] ?? ''));
        $report = $this->reportStore->find($reference);

        if ($report === null) {
            flash('error', trans('alerts.report_not_found'));
            redirect('/admin/reports');
        }

        $localizedReport = (new \App\Support\ReportBuilder())->localize($report, current_locale());

        render('participant.report', [
            'title' => trans('page_titles.participant_report'),
            'report' => $localizedReport,
            'adminMode' => true,
        ]);
    }

    public function deleteReport(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/reports');
        }

        $reference = trim((string) ($_POST['reference'] ?? ''));

        if ($reference !== '') {
            $this->reportStore->delete($reference);
            flash('success', trans('alerts.report_deleted'));
        }

        redirect('/admin/reports');
    }

    public function areas(): void
    {
        require_admin();

        $filters = [
            'search' => trim((string) ($_GET['search'] ?? '')),
        ];

        render('admin.areas', [
            'title' => trans('page_titles.manage_interest_areas'),
            'items' => $this->areaContentStore->all(current_locale(), $filters['search']),
            'filters' => $filters,
            'areas' => config('riasec_areas', []),
            'languages' => config('supported_languages', []),
            'activeSection' => 'areas',
        ]);
    }

    public function editArea(): void
    {
        require_admin();

        $areaCode = trim((string) ($_GET['area'] ?? ''));
        $item = $this->areaContentStore->find($areaCode);

        if ($item === null) {
            flash('error', trans('alerts.area_not_found'));
            redirect('/admin/areas');
        }

        render('admin.area-form', [
            'title' => trans('page_titles.edit_interest_area'),
            'item' => $item,
            'areas' => config('riasec_areas', []),
            'activeSection' => 'areas',
        ]);
    }

    public function saveArea(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/areas');
        }

        $areaCode = trim((string) ($_POST['area_code'] ?? ''));
        $description = trim((string) ($_POST['description'] ?? ''));

        if (!array_key_exists($areaCode, (array) config('riasec_areas', []))) {
            flash('error', trans('alerts.valid_interest_area_required'));
            redirect('/admin/areas');
        }

        if ($description === '') {
            flash('error', trans('alerts.interest_area_required'));
            redirect('/admin/areas/edit?area=' . urlencode($areaCode));
        }

        $this->areaContentStore->save($areaCode, $description);
        flash('success', trans('alerts.interest_area_saved'));
        redirect('/admin/areas');
    }

    public function downloadReport(): void
    {
        require_admin();

        $reference = trim((string) ($_GET['ref'] ?? ''));
        $report = $this->reportStore->find($reference);

        if ($report === null) {
            flash('error', trans('alerts.report_not_found'));
            redirect('/admin/reports');
        }

        $localizedReport = (new \App\Support\ReportBuilder())->localize($report, current_locale());
        $pdfPath = $this->reportStore->refreshPdf($localizedReport);

        if ($pdfPath === null || !is_file($pdfPath)) {
            flash('error', trans('alerts.pdf_not_found'));
            redirect('/admin/reports');
        }

        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment; filename="' . basename($pdfPath) . '"');
        header('Content-Length: ' . filesize($pdfPath));
        readfile($pdfPath);
        exit;
    }

    public function questions(): void
    {
        require_admin();

        $filters = [
            'area' => trim((string) ($_GET['area'] ?? '')),
            'search' => trim((string) ($_GET['search'] ?? '')),
        ];

        render('admin.questions', [
            'title' => trans('page_titles.manage_questions'),
            'questions' => $this->questionStore->all(current_locale(), $filters['area'] ?: null, $filters['search']),
            'filters' => $filters,
            'areas' => config('riasec_areas', []),
            'languages' => config('supported_languages', []),
            'activeSection' => 'questions',
        ]);
    }

    public function createQuestion(): void
    {
        require_admin();

        render('admin.question-form', [
            'title' => trans('page_titles.add_question'),
            'question' => [
                'id' => null,
                'source_key' => '',
                'area_code' => 'R',
                'sort_order' => 1,
                'is_active' => 1,
                'statement' => '',
            ],
            'areas' => config('riasec_areas', []),
            'activeSection' => 'questions',
        ]);
    }

    public function editQuestion(): void
    {
        require_admin();

        $id = (int) ($_GET['id'] ?? 0);
        $question = $this->questionStore->find($id);

        if ($question === null) {
            flash('error', trans('alerts.question_not_found'));
            redirect('/admin/questions');
        }

        render('admin.question-form', [
            'title' => trans('page_titles.edit_question'),
            'question' => $question,
            'areas' => config('riasec_areas', []),
            'activeSection' => 'questions',
        ]);
    }

    public function saveQuestion(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/questions');
        }

        $payload = [
            'id' => (int) ($_POST['id'] ?? 0),
            'source_key' => trim((string) ($_POST['source_key'] ?? '')),
            'area_code' => trim((string) ($_POST['area_code'] ?? 'R')),
            'sort_order' => (int) ($_POST['sort_order'] ?? 1),
            'is_active' => (int) ($_POST['is_active'] ?? 0),
            'statement' => trim((string) ($_POST['statement'] ?? '')),
        ];

        if (!array_key_exists($payload['area_code'], (array) config('riasec_areas', []))) {
            flash('error', trans('alerts.valid_riasec_area_required'));
            redirect('/admin/questions');
        }

        if ($payload['statement'] === '') {
            flash('error', trans('admin.english_required'));
            redirect($payload['id'] > 0 ? '/admin/questions/edit?id=' . $payload['id'] : '/admin/questions/create');
        }

        $this->questionStore->save($payload);
        flash('success', trans('alerts.question_saved'));
        redirect('/admin/questions');
    }

    public function deleteQuestion(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/questions');
        }

        $id = (int) ($_POST['id'] ?? 0);

        if ($id > 0) {
            $result = $this->questionStore->delete($id);
            flash('success', $result === 'deactivated' ? trans('alerts.question_deactivated') : trans('alerts.question_deleted'));
        }

        redirect('/admin/questions');
    }

    public function careers(): void
    {
        require_admin();

        $filters = [
            'area' => trim((string) ($_GET['area'] ?? '')),
            'search' => trim((string) ($_GET['search'] ?? '')),
        ];

        render('admin.careers', [
            'title' => trans('page_titles.manage_careers'),
            'items' => $this->recommendationStore->allCareers($filters['area'] ?: null, current_locale(), $filters['search']),
            'filters' => $filters,
            'areas' => config('riasec_areas', []),
            'languages' => config('supported_languages', []),
            'activeSection' => 'careers',
        ]);
    }

    public function createCareer(): void
    {
        require_admin();

        render('admin.career-form', [
            'title' => trans('page_titles.add_career'),
            'item' => [
                'id' => null,
                'area_code' => 'R',
                'title' => '',
                'description' => '',
                'sort_order' => 1,
                'is_active' => 1,
            ],
            'areas' => config('riasec_areas', []),
            'activeSection' => 'careers',
        ]);
    }

    public function editCareer(): void
    {
        require_admin();

        $id = (int) ($_GET['id'] ?? 0);
        $item = $this->recommendationStore->findCareer($id);

        if ($item === null) {
            flash('error', trans('alerts.career_not_found'));
            redirect('/admin/careers');
        }

        render('admin.career-form', [
            'title' => trans('page_titles.edit_career'),
            'item' => $item,
            'areas' => config('riasec_areas', []),
            'activeSection' => 'careers',
        ]);
    }

    public function saveCareer(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/careers');
        }

        $payload = [
            'id' => (int) ($_POST['id'] ?? 0),
            'area_code' => trim((string) ($_POST['area_code'] ?? 'R')),
            'title' => trim((string) ($_POST['title'] ?? '')),
            'description' => trim((string) ($_POST['description'] ?? '')),
            'sort_order' => (int) ($_POST['sort_order'] ?? 1),
            'is_active' => (int) ($_POST['is_active'] ?? 0),
        ];

        if ($payload['title'] === '') {
            flash('error', trans('alerts.career_title_required'));
            redirect($payload['id'] > 0 ? '/admin/careers/edit?id=' . $payload['id'] : '/admin/careers/create');
        }

        $this->recommendationStore->saveCareer($payload);
        flash('success', trans('alerts.career_saved'));
        redirect('/admin/careers');
    }

    public function deleteCareer(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/careers');
        }

        $id = (int) ($_POST['id'] ?? 0);

        if ($id > 0) {
            $this->recommendationStore->deleteCareer($id);
            flash('success', trans('alerts.career_deleted'));
        }

        redirect('/admin/careers');
    }

    public function programmes(): void
    {
        require_admin();

        $filters = [
            'area' => trim((string) ($_GET['area'] ?? '')),
            'search' => trim((string) ($_GET['search'] ?? '')),
        ];

        render('admin.programmes', [
            'title' => trans('page_titles.manage_programmes'),
            'items' => $this->recommendationStore->allProgrammes($filters['area'] ?: null, current_locale(), $filters['search']),
            'filters' => $filters,
            'areas' => config('riasec_areas', []),
            'languages' => config('supported_languages', []),
            'activeSection' => 'programmes',
        ]);
    }

    public function createProgramme(): void
    {
        require_admin();

        render('admin.programme-form', [
            'title' => trans('page_titles.add_programme'),
            'item' => [
                'id' => null,
                'area_code' => 'R',
                'programme_code' => '',
                'programme_name' => '',
                'description' => '',
                'sort_order' => 1,
                'is_active' => 1,
            ],
            'areas' => config('riasec_areas', []),
            'activeSection' => 'programmes',
        ]);
    }

    public function editProgramme(): void
    {
        require_admin();

        $id = (int) ($_GET['id'] ?? 0);
        $item = $this->recommendationStore->findProgramme($id);

        if ($item === null) {
            flash('error', trans('alerts.programme_not_found'));
            redirect('/admin/programmes');
        }

        render('admin.programme-form', [
            'title' => trans('page_titles.edit_programme'),
            'item' => $item,
            'areas' => config('riasec_areas', []),
            'activeSection' => 'programmes',
        ]);
    }

    public function saveProgramme(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/programmes');
        }

        $payload = [
            'id' => (int) ($_POST['id'] ?? 0),
            'area_code' => trim((string) ($_POST['area_code'] ?? 'R')),
            'programme_code' => trim((string) ($_POST['programme_code'] ?? '')),
            'title' => trim((string) ($_POST['programme_name'] ?? '')),
            'description' => trim((string) ($_POST['description'] ?? '')),
            'sort_order' => (int) ($_POST['sort_order'] ?? 1),
            'is_active' => (int) ($_POST['is_active'] ?? 0),
        ];

        if ($payload['title'] === '') {
            flash('error', trans('alerts.programme_name_required'));
            redirect($payload['id'] > 0 ? '/admin/programmes/edit?id=' . $payload['id'] : '/admin/programmes/create');
        }

        $this->recommendationStore->saveProgramme($payload);
        flash('success', trans('alerts.programme_saved'));
        redirect('/admin/programmes');
    }

    public function deleteProgramme(): void
    {
        require_admin();

        if (!verify_csrf($_POST['_csrf'] ?? null)) {
            flash('error', trans('alerts.session_expired'));
            redirect('/admin/programmes');
        }

        $id = (int) ($_POST['id'] ?? 0);

        if ($id > 0) {
            $this->recommendationStore->deleteProgramme($id);
            flash('success', trans('alerts.programme_deleted'));
        }

        redirect('/admin/programmes');
    }
}