<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Core\Configure;
use Cake\Http\Client;
use Cake\Http\Response;
use Cake\Log\Log;
use Throwable;

class ChatController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        // Disable CSRF + form protection for the JSON API endpoint.
        // The endpoint still requires an AJAX header from the chat widget for a thin layer of CSRF protection.
        $this->FormProtection->setConfig('validate', false);
    }

    public function send(): Response
    {
        $this->request->allowMethod(['post']);

        if (strtolower((string)$this->request->getHeaderLine('X-Requested-With')) !== 'xmlhttprequest') {
            return $this->jsonError('Bad request.', 400);
        }

        $payload = $this->request->getData();
        if (!is_array($payload) || empty($payload['messages']) || !is_array($payload['messages'])) {
            return $this->jsonError('No messages provided.', 400);
        }

        // Sanitize message history (cap length, validate roles, trim content)
        $messages = [];
        foreach (array_slice($payload['messages'], -16) as $m) {
            if (!isset($m['role'], $m['content'])) continue;
            $role = $m['role'] === 'assistant' ? 'assistant' : 'user';
            $content = trim(mb_substr((string)$m['content'], 0, 4000));
            if ($content === '') continue;
            $messages[] = ['role' => $role, 'content' => $content];
        }

        if (empty($messages)) {
            return $this->jsonError('No valid messages.', 400);
        }

        $apiKey = (string)Configure::read('Anthropic.apiKey');
        if ($apiKey === '') {
            // Friendly fallback so the widget remains useful even without an API key.
            return $this->jsonReply($this->fallbackReply($messages));
        }

        try {
            $http = new Client(['timeout' => 30]);
            $resp = $http->post('https://api.anthropic.com/v1/messages', json_encode([
                'model' => Configure::read('Anthropic.model', 'claude-haiku-4-5'),
                'max_tokens' => 600,
                'system' => $this->systemPrompt(),
                'messages' => $messages,
            ]), [
                'headers' => [
                    'x-api-key' => $apiKey,
                    'anthropic-version' => '2023-06-01',
                    'content-type' => 'application/json',
                ],
            ]);
        } catch (Throwable $e) {
            Log::warning('Anthropic API call threw: ' . $e->getMessage());
            return $this->jsonReply($this->fallbackReply($messages));
        }

        if (!$resp->isOk()) {
            Log::warning('Anthropic API non-OK: ' . $resp->getStatusCode() . ' — ' . $resp->getStringBody());
            return $this->jsonReply($this->fallbackReply($messages));
        }

        $data = $resp->getJson();
        if (!is_array($data) || empty($data['content'][0]['text'])) {
            return $this->jsonReply($this->fallbackReply($messages));
        }

        return $this->jsonReply((string)$data['content'][0]['text']);
    }

    private function systemPrompt(): string
    {
        return <<<TXT
You are the friendly assistant for CandleCraft Academy, a small Melbourne-based pottery and knitting tutoring studio.

Tone: warm, plain-language, slightly understated. Never pushy. Short replies (2-4 sentences) unless the user asks for detail.

What you know:
- Classes are 90 minutes, 1-on-1, in our Melbourne studio.
- Crafts offered: pottery (wheel throwing, hand-building, glazing) and knitting (beginners through cables/lace).
- Teachers: Ishani Patel (pottery, wheel), Marcus O'Shea (pottery, hand-building), Lena Koh (knitting, beginners), Tomás Rivera (knitting, advanced).
- Pricing starts at A\$60–75 per class depending on teacher.
- People can browse open times and book + pay online at /book.
- Anyone with a question can send an enquiry at /contact (gets a reply within 2 working days).
- Beginners are welcome — most learners arrive with no experience.
- Refunds/reschedules: free up to 24h before the class.
- No address shared in chat — sent with the booking confirmation email.

If the user asks about something outside this scope, gently steer them to the enquiry form.
Never invent prices, schedules, or addresses you don't know.
TXT;
    }

    private function fallbackReply(array $messages): string
    {
        $last = strtolower(end($messages)['content'] ?? '');
        if (str_contains($last, 'price') || str_contains($last, 'cost') || str_contains($last, 'how much')) {
            return "Classes start at around A\$60–75 each (90 min, 1-on-1). You can see live pricing per teacher on the booking page.";
        }
        if (str_contains($last, 'book') || str_contains($last, 'time')) {
            return "You can pick a teacher and time over on the Book page. Choose Pottery or Knitting and you'll see open slots for the next two weeks.";
        }
        if (str_contains($last, 'beginner') || str_contains($last, 'never')) {
            return "Most of our learners arrive with no experience — every class is structured for beginners. You don't need anything except clothes you don't mind getting dusty.";
        }
        return "Happy to help. You can browse classes at /book or send a quick enquiry at /contact and a real person will reply within two working days.";
    }

    private function jsonReply(string $text): Response
    {
        return $this->response
            ->withType('application/json')
            ->withStringBody(json_encode(['reply' => $text]));
    }

    private function jsonError(string $message, int $code): Response
    {
        return $this->response
            ->withType('application/json')
            ->withStatus($code)
            ->withStringBody(json_encode(['error' => $message]));
    }
}
