<?php

namespace App\Services\Care;

use App\Models\Device;
use App\Models\Organization;
use Illuminate\Support\Str;

class DeviceService
{
    public function generateToken(): string
    {
        return Str::random(48);
    }

    public function hashToken(string $token): string
    {
        return hash('sha256', $token);
    }

    public function findByToken(string $token): ?Device
    {
        if ($token === '') {
            return null;
        }

        return Device::query()
            ->where('device_token_hash', $this->hashToken($token))
            ->where('status', '!=', Device::STATUS_DISABLED)
            ->first();
    }

    public function issueToken(Device $device): string
    {
        $plain = $this->generateToken();
        $meta = $device->metadata ?? [];
        if ($this->isQueueDeviceType($device->type)) {
            $meta['access_token'] = $plain;
        }

        $device->update([
            'device_token_hash' => $this->hashToken($plain),
            'metadata' => $meta,
        ]);

        return $plain;
    }

    public function revokeToken(Device $device): Device
    {
        $meta = $device->metadata ?? [];
        unset($meta['access_token']);

        $device->update([
            'device_token_hash' => null,
            'metadata' => $meta,
        ]);

        return $device->fresh();
    }

    public function recordHeartbeat(Device $device, ?array $metadata = null): Device
    {
        $payload = [
            'status' => Device::STATUS_ACTIVE,
            'last_seen_at' => now(),
        ];

        if ($metadata !== null) {
            $payload['metadata'] = array_merge($device->metadata ?? [], [
                'agent' => $metadata,
            ]);
        }

        $device->update($payload);

        return $device->fresh();
    }

    public function defaultConnectionMode(string $type): string
    {
        return match ($type) {
            'kiosk', 'display' => Device::MODE_MANUAL,
            'barcode_scanner', 'qr_scanner' => Device::MODE_BROWSER_WEDGE,
            'badge_printer' => Device::MODE_MANUAL,
            'thermometer', 'bp_monitor', 'pulse_ox', 'weight_scale', 'lab_analyzer', 'agent' => Device::MODE_AGENT,
            default => Device::MODE_MANUAL,
        };
    }

    public function isQueueDeviceType(string $type): bool
    {
        return in_array($type, config('care.queue_device_types', []), true);
    }

    public function typeRequiresPro(string $type): bool
    {
        return in_array($type, config('care.device_agent_types', []), true);
    }

    public function canRegisterType(Organization $organization, string $type, PlanService $plans): bool
    {
        if ($this->isQueueDeviceType($type)) {
            return $plans->hasPaidPlan($organization);
        }

        if (! $this->typeRequiresPro($type)) {
            return true;
        }

        return $plans->hasPaidPlan($organization);
    }

    public function publicAccessToken(Device $device): ?string
    {
        $token = $device->metadata['access_token'] ?? null;

        return is_string($token) && $token !== '' ? $token : null;
    }

    public function connectionHint(string $type, string $mode): string
    {
        if ($type === 'kiosk') {
            return 'Walk-up ticket kiosk. Open the public kiosk URL on a tablet in kiosk mode.';
        }

        if ($type === 'display') {
            return 'Waiting-room / counter display. Opens the linked TV board URL on a screen or tablet.';
        }

        return match ($mode) {
            Device::MODE_BROWSER_WEDGE => 'Works in the browser today as a USB keyboard wedge (scan into the focused field). No local agent required.',
            Device::MODE_AGENT => 'Needs the Care Device Agent on a local machine (serial / BLE / vendor SDK). Browser alone cannot talk to this hardware.',
            Device::MODE_WEB_BLUETOOTH => 'Experimental Web Bluetooth path — not broadly supported; prefer the local agent for clinical devices.',
            default => 'Manual / inventory only — no automated capture path configured.',
        };
    }
}
