<?php

namespace App\Services\Afia;

use Illuminate\Support\Facades\Http;
use RuntimeException;

/**
 * Afia — Ladill in-app AI assistant scoped to Ladill Care.
 */
class AfiaService
{
    public function enabled(): bool
    {
        if (! (bool) config('afia.enabled', true)) {
            return false;
        }

        return $this->hasLocalKey() || $this->hasPlatformRelay();
    }

    /**
     * @param  array<int, array{role: string, text: string}>  $history
     * @param  array<string, mixed>  $context
     */
    public function chat(string $message, array $history, array $context): string
    {
        if (! $this->enabled()) {
            throw new RuntimeException('Afia is not configured.');
        }

        if ($this->hasLocalKey()) {
            return $this->chatLocally($message, $history, $context);
        }

        return $this->chatViaPlatform($message, $history, $context);
    }

    /**
     * @param  array<int, array{role: string, text: string}>  $history
     * @param  array<string, mixed>  $context
     */
    private function chatLocally(string $message, array $history, array $context): string
    {
        $provider = (string) config('afia.provider', 'openai');
        $model = (string) config('afia.model', 'gpt-4o-mini');
        $apiKey = (string) config('afia.api_key');

        $messages = [['role' => 'system', 'content' => $this->systemPrompt($context)]];
        foreach (array_slice($history, -8) as $turn) {
            $role = ($turn['role'] ?? 'user') === 'assistant' ? 'assistant' : 'user';
            $text = trim((string) ($turn['text'] ?? ''));
            if ($text !== '') {
                $messages[] = ['role' => $role, 'content' => $text];
            }
        }
        $messages[] = ['role' => 'user', 'content' => $message];

        return $provider === 'anthropic'
            ? $this->viaAnthropic($model, $apiKey, $messages)
            : $this->viaOpenAi($model, $apiKey, $messages);
    }

    /**
     * @param  array<int, array{role: string, text: string}>  $history
     * @param  array<string, mixed>  $context
     */
    private function chatViaPlatform(string $message, array $history, array $context): string
    {
        $base = rtrim((string) config('afia.platform_api_url', ''), '/');
        $token = (string) config('afia.platform_api_key', '');

        $res = Http::withToken($token)->acceptJson()->timeout(50)->post($base.'/afia/chat', [
            'product' => (string) config('afia.product', 'care'),
            'message' => $message,
            'history' => $history,
            'system_prompt' => $this->systemPrompt($context),
        ]);

        if ($res->status() === 503) {
            throw new RuntimeException('Afia is not configured on the platform.');
        }

        if ($res->failed()) {
            throw new RuntimeException('Platform Afia relay failed: '.$res->status());
        }

        $reply = trim((string) $res->json('reply', ''));
        if ($reply === '') {
            throw new RuntimeException('Platform Afia relay returned an empty response.');
        }

        return $reply;
    }

    private function hasLocalKey(): bool
    {
        return (string) config('afia.api_key', '') !== '';
    }

    private function hasPlatformRelay(): bool
    {
        return rtrim((string) config('afia.platform_api_url', ''), '/') !== ''
            && (string) config('afia.platform_api_key', '') !== '';
    }

    private function viaOpenAi(string $model, string $apiKey, array $messages): string
    {
        $res = Http::withToken($apiKey)->acceptJson()->timeout(45)
            ->post('https://api.openai.com/v1/chat/completions', [
                'model' => $model,
                'temperature' => 0.3,
                'max_tokens' => 600,
                'messages' => $messages,
            ]);

        if ($res->failed()) {
            throw new RuntimeException('OpenAI request failed: '.$res->status());
        }

        return trim((string) $res->json('choices.0.message.content', ''));
    }

    private function viaAnthropic(string $model, string $apiKey, array $messages): string
    {
        $system = $messages[0]['content'] ?? '';
        $turns = array_values(array_filter($messages, fn ($m) => $m['role'] !== 'system'));

        $res = Http::withHeaders([
            'x-api-key' => $apiKey,
            'anthropic-version' => '2023-06-01',
        ])->acceptJson()->timeout(45)->post('https://api.anthropic.com/v1/messages', [
            'model' => $model,
            'max_tokens' => 600,
            'system' => $system,
            'messages' => array_map(fn ($m) => ['role' => $m['role'], 'content' => $m['content']], $turns),
        ]);

        if ($res->failed()) {
            throw new RuntimeException('Anthropic request failed: '.$res->status());
        }

        return trim((string) $res->json('content.0.text', ''));
    }

    /** @param  array<string, mixed>  $context */
    private function systemPrompt(array $context): string
    {
        $ctx = collect($context)->map(fn ($v, $k) => "- {$k}: {$v}")->implode("\n");

        return <<<PROMPT
        You are Afia, the assistant inside Ladill Care (care.ladill.com).
        Help clinical and administrative staff manage patients, appointments, consultations, laboratory, pharmacy, and billing. Be concise, friendly, and actionable: short numbered steps and name the screen or section to use.

        What Ladill Care does and where things live:
        - Dashboard: today's activity and quick links for the facility.
        - Patients: register patients, view demographics, history, consultations, prescriptions, and bills.
        - Appointments: schedule visits and manage walk-ins.
        - Queue: waiting patients and active consultations — doctors start consultations from here.
        - Consultations: record vitals, symptoms, clinical notes, diagnoses, lab requests, and prescriptions; complete the encounter when done.
        - Laboratory: sample collection, results entry, and approval from the lab queue. Admins manage the investigation catalog and test prices in Settings / Lab catalog.
        - Prescriptions & pharmacy queue: prescribe during consultations; pharmacists dispense from the queue.
        - Billing: generate bills from completed visits, record payments, and print receipts.
        - Settings & admin: branches, departments, members, practitioners, lab catalog pricing, and audit logs.

        Rules:
        - Only answer questions about Ladill Care — patients, appointments, queue, consultations, lab, pharmacy, and billing.
        - If asked about CRM, visitor management, domains, or email mailboxes, briefly say those live in other Ladill apps and suggest the app launcher.
        - Never invent patient names, counts, or clinical results — use the user context below or tell them where to check.

        Current user context:
        {$ctx}
        PROMPT;
    }
}
