<?php

namespace App\Controllers\Api;

use App\Libraries\AuditLogger;
use App\Libraries\ChurchContext;
use App\Libraries\PermissionService;
use App\Libraries\ResponseHelper;
use App\Libraries\TokenService;
use App\Models\ApiTokenModel;
use App\Models\PlatformAdminModel;
use App\Models\RoleModel;
use App\Models\UserModel;
use CodeIgniter\Controller;

class AuthController extends Controller
{
    public function login()
    {
        $data  = $this->request->getJSON(true) ?? [];
        $email = trim($data['email'] ?? '');
        $pass  = $data['password'] ?? '';

        if (!$email || !$pass) {
            return ResponseHelper::error('Email and password are required', 422);
        }

        // Check platform admin first
        $adminModel = new PlatformAdminModel();
        $admin      = $adminModel->findByEmail($email);
        if ($admin && password_verify($pass, $admin['password_hash'])) {
            if (!$admin['is_active']) {
                return ResponseHelper::error('Account is inactive', 403);
            }

            $tokenService = new TokenService();
            $raw          = $tokenService->issue(0, 0, true, $admin['id']);

            $adminModel->update($admin['id'], ['last_login_at' => date('Y-m-d H:i:s')]);

            return ResponseHelper::success([
                'token'          => $raw,
                'type'           => 'platform_admin',
                'platform_admin' => $this->formatAdmin($admin),
            ]);
        }

        // Regular user — need church_id. Accept church_uuid or church_id in body.
        $db        = \Config\Database::connect();
        $churchRef = $data['church_uuid'] ?? null;

        if (!$churchRef) {
            return ResponseHelper::error('church_uuid is required for user login', 422);
        }

        $church = $db->table('churches')->where('uuid', $churchRef)->where('deleted_at IS NULL')->get()->getRowArray();
        if (!$church) {
            return ResponseHelper::error('Church not found', 404);
        }

        $userModel = new UserModel();
        $user      = $userModel->where('email', $email)
                               ->where('church_id', $church['id'])
                               ->where('deleted_at IS NULL')
                               ->first();

        if (!$user || !password_verify($pass, $user['password_hash'])) {
            return ResponseHelper::error('Invalid credentials', 401);
        }

        if (!$user['is_active']) {
            return ResponseHelper::error('Account is inactive', 403);
        }

        $tokenService = new TokenService();
        $raw          = $tokenService->issue($user['id'], $user['church_id']);

        $userModel->update($user['id'], ['last_login_at' => date('Y-m-d H:i:s')]);

        $roleModel = new RoleModel();
        $role      = $roleModel->find($user['role_id']);

        $perms = PermissionService::resolve($user['id'], $user['role_id']);

        return ResponseHelper::success([
            'token' => $raw,
            'type'  => 'user',
            'user'  => $this->formatUser($user, $role, $perms),
        ]);
    }

    public function logout()
    {
        $raw = $this->getBearerToken();
        if ($raw) {
            (new TokenService())->revoke($raw);
        }
        return ResponseHelper::success(null);
    }

    public function me()
    {
        $ctx = ChurchContext::getInstance();

        if ($ctx->isPlatformAdmin()) {
            return ResponseHelper::success([
                'type'           => 'platform_admin',
                'platform_admin' => $this->formatAdmin($ctx->getPlatformAdmin()),
            ]);
        }

        $user = $ctx->getUser();
        $roleModel = new RoleModel();
        $role      = $roleModel->find($user['role_id']);
        $perms     = PermissionService::resolve($user['id'], $user['role_id']);

        return ResponseHelper::success([
            'type' => 'user',
            'user' => $this->formatUser($user, $role, $perms),
        ]);
    }

    public function refresh()
    {
        $raw = $this->getBearerToken();
        if (!$raw) {
            return ResponseHelper::unauthorized();
        }

        $tokenModel  = new ApiTokenModel();
        $hash        = hash('sha256', $raw);
        $currentRow  = $tokenModel->where('token_hash', $hash)->first();

        if (!$currentRow) {
            return ResponseHelper::unauthorized('Token not found');
        }

        $ctx     = ChurchContext::getInstance();
        $service = new TokenService();

        if ($ctx->isPlatformAdmin()) {
            $admin  = $ctx->getPlatformAdmin();
            $newRaw = $service->issue(0, 0, true, $admin['id']);
        } else {
            $user   = $ctx->getUser();
            $newRaw = $service->issue($user['id'], $user['church_id']);
        }

        $service->revokeById($currentRow['id']);

        return ResponseHelper::success(['token' => $newRaw]);
    }

    // ----------------------------------------------------------------

    private function getBearerToken(): ?string
    {
        $header = $this->request->getHeaderLine('Authorization');
        if ($header && str_starts_with($header, 'Bearer ')) {
            return substr($header, 7);
        }
        return null;
    }

    private function formatUser(array $user, ?array $role, array $perms): array
    {
        return [
            'uuid'        => $user['uuid'],
            'name'        => $user['name'],
            'email'       => $user['email'],
            'phone'       => $user['phone'],
            'is_active'   => (bool) $user['is_active'],
            'church_id'   => $user['church_id'],
            'role'        => $role ? ['id' => $role['id'], 'name' => $role['name']] : null,
            'permissions' => $perms,
            'last_login'  => $user['last_login_at'],
        ];
    }

    private function formatAdmin(array $admin): array
    {
        return [
            'uuid'       => $admin['uuid'],
            'name'       => $admin['name'],
            'email'      => $admin['email'],
            'is_active'  => (bool) $admin['is_active'],
            'last_login' => $admin['last_login_at'],
        ];
    }
}
