<?php

namespace app\controller\Api;

use app\service\AdminAuthService;
use InvalidArgumentException;
use JsonException;
use support\Request;
use support\Response;
use Throwable;

class AdminAuthController
{
    public function login(Request $request): Response
    {
        try {
            $payload = $this->payload($request);
            $username = trim((string) ($payload['username'] ?? ''));
            $password = (string) ($payload['password'] ?? '');

            if ($username === '' || $password === '') {
                throw new InvalidArgumentException('username and password are required.');
            }

            $auth = new AdminAuthService();
            $user = $auth->authenticate($username, $password);
            if ($user === null) {
                return $this->jsonResponse([
                    'code' => 401,
                    'message' => 'Admin login failed.',
                    'errors' => ['auth' => 'invalid username or password.'],
                ], 401);
            }

            $auth->login($request, $user);
        } catch (JsonException $exception) {
            return $this->jsonResponse([
                'code' => 400,
                'message' => 'Invalid JSON body.',
                'errors' => ['body' => $exception->getMessage()],
            ], 400);
        } catch (InvalidArgumentException $exception) {
            return $this->jsonResponse([
                'code' => 422,
                'message' => 'Admin login validation failed.',
                'errors' => ['auth' => $exception->getMessage()],
            ], 422);
        } catch (Throwable $exception) {
            return $this->jsonResponse([
                'code' => 500,
                'message' => 'Admin login failed.',
                'errors' => ['auth' => $exception->getMessage()],
            ], 500);
        }

        return $this->jsonResponse([
            'code' => 0,
            'message' => 'Admin login completed.',
            'data' => ['admin' => $user],
        ], 200);
    }

    public function logout(Request $request): Response
    {
        try {
            (new AdminAuthService())->logout($request);
        } catch (Throwable $exception) {
            return $this->jsonResponse([
                'code' => 500,
                'message' => 'Admin logout failed.',
                'errors' => ['auth' => $exception->getMessage()],
            ], 500);
        }

        return $this->jsonResponse([
            'code' => 0,
            'message' => 'Admin logout completed.',
        ], 200);
    }

    public function me(Request $request): Response
    {
        try {
            $admin = (new AdminAuthService())->current($request);
        } catch (Throwable $exception) {
            return $this->jsonResponse([
                'code' => 500,
                'message' => 'Admin session lookup failed.',
                'errors' => ['auth' => $exception->getMessage()],
            ], 500);
        }

        if ($admin === null) {
            return $this->jsonResponse([
                'code' => 401,
                'message' => 'Admin session not found.',
            ], 401);
        }

        return $this->jsonResponse([
            'code' => 0,
            'message' => 'Admin session loaded.',
            'data' => ['admin' => $admin],
        ], 200);
    }

    /**
     * @throws JsonException
     */
    private function payload(Request $request): array
    {
        $rawBody = trim($request->rawBody());
        if ($rawBody === '') {
            return $request->post();
        }

        $payload = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
        return is_array($payload) ? $payload : [];
    }

    private function jsonResponse(array $data, int $status): Response
    {
        return response(
            json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR),
            $status,
            ['Content-Type' => 'application/json']
        );
    }
}
