<?php
declare(strict_types=1);

namespace App\Modules\Achievements\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Achievements\Models\AchievementDefinition;
use App\Modules\Achievements\Models\PlayerAchievement;
use App\Modules\Achievements\Services\AchievementEngine;

class AchievementController extends Controller
{
    /**
     * Show achievements for a player.
     */
    public function index(Request $request): Response
    {
        $this->authorize('achievement.view');

        $playerId = $request->get('player_id', '') !== '' ? (int) $request->get('player_id') : null;

        $db = App::getInstance()->db();
        $players = $db->select(
            "SELECT id, full_name_ar, registration_serial FROM players WHERE is_archived = 0 ORDER BY full_name_ar ASC"
        );

        $achievements = [];
        $totalPoints = 0;
        $player = null;

        if ($playerId) {
            $achievements = PlayerAchievement::getForPlayer($playerId);
            $totalPoints = PlayerAchievement::getTotalPoints($playerId);
            $player = $db->selectOne("SELECT * FROM players WHERE id = ?", [$playerId]);
        }

        // Group by category
        $grouped = [];
        foreach ($achievements as $ach) {
            $cat = $ach['category'] ?? 'special';
            $grouped[$cat][] = $ach;
        }

        return $this->view('Achievements.Views.player_achievements', [
            'achievements'  => $achievements,
            'grouped'       => $grouped,
            'totalPoints'   => $totalPoints,
            'player'        => $player,
            'playerId'      => $playerId,
            'players'       => $players,
            'categories'    => AchievementDefinition::getCategories(),
        ]);
    }

    /**
     * Show the leaderboard.
     */
    public function leaderboard(Request $request): Response
    {
        $this->authorize('achievement.view');

        $disciplineId = $request->get('discipline_id', '') !== '' ? (int) $request->get('discipline_id') : null;
        $limit = min(100, max(10, (int) $request->get('limit', 50)));

        $leaderboard = AchievementEngine::getLeaderboard($disciplineId, $limit);

        $db = App::getInstance()->db();
        $disciplines = $db->select(
            "SELECT id, name_ar FROM sport_disciplines WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('Achievements.Views.leaderboard', [
            'leaderboard'   => $leaderboard,
            'disciplines'   => $disciplines,
            'disciplineId'  => $disciplineId,
        ]);
    }

    /**
     * Admin: List all achievement definitions.
     */
    public function adminIndex(Request $request): Response
    {
        $this->authorize('achievement.manage');

        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'category'      => trim((string) $request->get('category', '')),
            'is_active'     => $request->get('is_active', ''),
            'discipline_id' => $request->get('discipline_id', '') !== '' ? (int) $request->get('discipline_id') : null,
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = AchievementDefinition::search($filters, 25, $page);

        $db = App::getInstance()->db();
        $disciplines = $db->select(
            "SELECT id, name_ar FROM sport_disciplines WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('Achievements.Views.admin_index', [
            'definitions'  => $result['data'],
            'pagination'   => $result['pagination'],
            'filters'      => $filters,
            'categories'   => AchievementDefinition::getCategories(),
            'disciplines'  => $disciplines,
        ]);
    }

    /**
     * Admin: Show form to create a new achievement definition.
     */
    public function adminCreate(Request $request): Response
    {
        $this->authorize('achievement.manage');

        $db = App::getInstance()->db();
        $disciplines = $db->select(
            "SELECT id, name_ar FROM sport_disciplines WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('Achievements.Views.admin_create', [
            'categories'  => AchievementDefinition::getCategories(),
            'badgeColors' => AchievementDefinition::getBadgeColors(),
            'disciplines' => $disciplines,
        ]);
    }

    /**
     * Admin: Store a new achievement definition.
     */
    public function adminStore(Request $request): Response
    {
        $this->authorize('achievement.manage');

        $data = [
            'code'          => trim((string) $request->post('code', '')),
            'name_ar'       => trim((string) $request->post('name_ar', '')),
            'name_en'       => trim((string) $request->post('name_en', '')) ?: null,
            'description_ar'=> trim((string) $request->post('description_ar', '')) ?: null,
            'category'      => trim((string) $request->post('category', '')),
            'icon'          => trim((string) $request->post('icon', '')) ?: 'award',
            'badge_color'   => trim((string) $request->post('badge_color', '')) ?: 'gold',
            'discipline_id' => $request->post('discipline_id', '') !== '' ? (int) $request->post('discipline_id') : null,
            'points'        => (int) $request->post('points', 10),
            'is_active'     => (int) $request->post('is_active', 1),
        ];

        // Build criteria JSON
        $criteriaType = trim((string) $request->post('criteria_type', ''));
        $criteria = ['type' => $criteriaType];

        $trigger = trim((string) $request->post('criteria_trigger', ''));
        if ($trigger !== '') {
            $criteria['trigger'] = $trigger;
        }

        $criteriaCount = $request->post('criteria_count', '');
        if ($criteriaCount !== '') {
            $criteria['count'] = (int) $criteriaCount;
        }

        $criteriaMonths = $request->post('criteria_months', '');
        if ($criteriaMonths !== '') {
            $criteria['months'] = (int) $criteriaMonths;
        }

        $criteriaMinScore = $request->post('criteria_min_score', '');
        if ($criteriaMinScore !== '') {
            $criteria['min_score'] = (float) $criteriaMinScore;
        }

        $data['criteria_json'] = json_encode($criteria, JSON_UNESCAPED_UNICODE);

        // Validation
        $errors = [];
        if (empty($data['code'])) $errors[] = 'يجب تحديد كود الإنجاز';
        if (empty($data['name_ar'])) $errors[] = 'يجب تحديد اسم الإنجاز';
        if (empty($data['category'])) $errors[] = 'يجب تحديد التصنيف';

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_old_input', $request->all());
            $alerts = array_map(fn($msg) => ['type' => 'error', 'message' => $msg], $errors);
            $session->flash('_alerts', $alerts);
            return $this->redirect('/achievements/admin/create');
        }

        try {
            AchievementDefinition::create($data);
            return $this->redirect('/achievements/admin')->withSuccess('تم إنشاء الإنجاز بنجاح');
        } catch (\Throwable $e) {
            return $this->redirect('/achievements/admin/create')->withError('حدث خطأ: ' . $e->getMessage());
        }
    }

    /**
     * Admin: Toggle an achievement definition active/inactive.
     */
    public function adminToggle(Request $request, int $id): Response
    {
        $this->authorize('achievement.manage');

        $definition = AchievementDefinition::findOrFail($id);
        $newState = (int) $definition->is_active === 1 ? 0 : 1;
        $definition->update(['is_active' => $newState]);

        $label = $newState ? 'تفعيل' : 'تعطيل';
        return $this->redirect('/achievements/admin')->withSuccess("تم {$label} الإنجاز بنجاح");
    }
}
