<?php
declare(strict_types=1);

namespace App\Middleware;

use App\Core\Middleware\MiddlewareInterface;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Users\Models\Employee;
use App\Shared\Services\BranchScopeService;

final class AuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, callable $next): Response
    {
        $app = App::getInstance();
        $session = $app->session();

        $employeeId = $session->get('employee_id');
        if (!$employeeId) {
            return (new Response())->redirect('/login');
        }

        $employee = Employee::find((int) $employeeId);
        if (!$employee || !$employee->is_active || $employee->is_archived) {
            $session->destroy();
            return (new Response())->redirect('/login');
        }

        $timeout = (int) config('auth.session_lifetime', 30) * 60;
        $lastActivity = $session->get('last_activity_at', 0);
        if ($lastActivity && (time() - $lastActivity) > $timeout) {
            $session->destroy();
            return (new Response())->redirect('/login')->withError('انتهت الجلسة. يرجى تسجيل الدخول مجدداً.');
        }
        $session->set('last_activity_at', time());

        $app->setCurrentEmployee($employee);
        BranchScopeService::reset();

        if ($employee->branch_id) {
            $branch = $app->db()->selectOne("SELECT * FROM branches WHERE id = ?", [$employee->branch_id]);
            if ($branch) {
                $app->setCurrentBranch($branch);
            }
        }

        $this->updateActiveSession($app, $employee, $request);

        $currentPath = $request->path();
        if ($employee->force_password_change && $currentPath !== '/change-password' && $currentPath !== '/logout') {
            return (new Response())->redirect('/change-password');
        }

        $requiredPermission = $request->getAttribute('_permission');
        if ($requiredPermission && !$employee->hasPermission($requiredPermission)) {
            return (new Response())->html(
                $this->render403(),
                403
            );
        }

        return $next($request);
    }

    private function updateActiveSession(App $app, Employee $employee, Request $request): void
    {
        try {
            $sessionId = $app->session()->id();
            if (!$sessionId) {
                return;
            }
            $db = $app->db();
            $existing = $db->selectOne(
                "SELECT id FROM active_sessions WHERE employee_id = ? AND session_id = ? AND is_active = 1",
                [$employee->id, $sessionId]
            );
            if ($existing) {
                $db->update('active_sessions', [
                    'last_activity_at' => date('Y-m-d H:i:s'),
                    'ip_address'       => $request->ip(),
                ], '`id` = ?', [$existing['id']]);
            }
        } catch (\Throwable $e) {
            // Non-critical, don't break the request
        }
    }

    private function render403(): string
    {
        return '<html dir="rtl" lang="ar"><head><meta charset="utf-8"><title>غير مصرح</title>'
            . '<style>body{font-family:Cairo,Tahoma,sans-serif;text-align:center;padding:80px;background:#f9fafb;}'
            . 'h1{color:#DC2626;font-size:64px;margin-bottom:10px;}p{color:#6B7280;font-size:18px;}'
            . 'a{color:#0D7377;text-decoration:none;font-size:16px;}</style></head>'
            . '<body><h1>403</h1><p>غير مصرح لك بالوصول لهذه الصفحة</p>'
            . '<a href="/">← العودة للرئيسية</a></body></html>';
    }
}