<?php

declare(strict_types=1);

namespace App\Filters;

use App\Models\MemberModel;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;

/**
 * 중복 로그인 방지(나중 로그인 우선).
 * 로그인 시 발급한 세션 토큰(session_token)을 회원 행(mb_session_token)과 매 요청마다 대조해,
 * 다른 곳에서 로그인해 토큰이 바뀌면 이 세션을 무효화하고 로그인으로 보낸다.
 * (DB를 공유하므로 로컬·운영 등 서로 다른 서버 간에도 동작)
 */
class SessionGuardFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        $session = session();
        if (! $session->get('logged_in')) {
            return null; // 비로그인 요청은 통과
        }

        $mbIdx = (int) ($session->get('mb_idx') ?? 0);
        if ($mbIdx <= 0) {
            return null;
        }

        $member = model(MemberModel::class)->find($mbIdx);
        if ($member === null) {
            return null;
        }

        $dbToken = (string) ($member->mb_session_token ?? '');
        $myToken = (string) ($session->get('session_token') ?? '');

        // DB에 토큰이 있고 내 세션 토큰과 다르면 → 다른 곳에서 더 늦게 로그인한 것
        if ($dbToken !== '' && $dbToken !== $myToken) {
            $session->destroy();

            // AJAX/JSON 요청은 401, 일반 요청은 로그인으로
            if (strtolower((string) $request->getHeaderLine('X-Requested-With')) === 'xmlhttprequest'
                || str_contains(strtolower((string) $request->getHeaderLine('Accept')), 'application/json')) {
                return service('response')->setStatusCode(401)->setJSON([
                    'ok' => false, 'message' => '다른 곳에서 로그인되어 로그아웃되었습니다.',
                ]);
            }

            return redirect()->to(site_url('login'))->with('error', '다른 곳에서 로그인되어 자동 로그아웃되었습니다.');
        }

        return null;
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // no-op
    }
}
