<?php

namespace ZenoChatbot\Support;

use ZenoChatbot\App;
use ZenoChatbot\Framework\Exceptions\ValidationException;
use ZenoChatbot\Framework\Support\Arr;
use ZenoChatbot\Framework\Validation\Validator;
use ZenoChatbot\Helper\Helper;
use ZenoChatbot\Helper\Settings;


if (!defined('ABSPATH')) {
    exit;
}

class Conversation
{

    public static function fallbackErrorResponse()
    {
        $default = 'I apologize, but I encountered an issue processing your request. Please try again or contact our support team if the problem persists.';
        $stored = Settings::get('general.on_error_response', $default);

        // A field saved empty must never yield a blank chat message.
        if (!is_string($stored) || trim($stored) === '') {
            $stored = $default;
        }

        return Hooks::applyFilters(Hooks::CHAT_ERROR_RESPONSE, $stored);
    }

    /**
     * @param \Throwable $e
     */
    public static function categoriseError(\Throwable $e)
    {
        $categories = [
            'SAFETY_FILTER'  => 'safety',
            'RATE_LIMIT'     => 'rate limit',
            'AUTH_ERROR'     => 'api key',
            'EMPTY_RESPONSE' => 'empty',
            'TIMEOUT'        => 'timeout',
        ];

        foreach ($categories as $category => $keyword) {
            if (str_contains(strtolower($e->getMessage()), $keyword)) {
                return $category;
            }
        }

        if ($e instanceof \RuntimeException) {
            return 'CONFIG_ERROR';
        }

        return 'UNKNOWN';
    }

    public static function hasExistingSession()
    {
        $sessionData = Helper::getSessionData();

        if (!is_array($sessionData)) {
            return false;
        }

        return !empty($sessionData['session_id'])
            && !empty($sessionData['conversation_id'])
            && !empty($sessionData['customer_id'])
            && !empty($sessionData['created_at']);
    }

    public static function getActiveConversation()
    {
        $sessionData = Helper::getSessionData();
        $conversationId = (int) Arr::get($sessionData, 'conversation_id');
        $customerId = (int) Arr::get($sessionData, 'customer_id');

        if (!$conversationId || !$customerId) {
            return null;
        }

        return \ZenoChatbot\Model\Conversation::query()
            ->where('status', 'open')
            ->where('id', $conversationId)
            ->where('customer_id', $customerId)
            ->first()
        ;
    }

    public static function getConversationHistory()
    {
        $conversation = static::getActiveConversation();

        if (!$conversation) {
            return [];
        }

        $messages = $conversation->messages()->orderBy('created_at', 'asc')->get();

        $history = [];

        foreach ($messages as $message) {
            $history[] = [
                'id'          => $message->id,
                'text'        => $message->message,
                'isUser'      => $message->sender_type === 'customer',
                'time'        => Helper::formatTimeHM($message->created_at),
                'sender_type' => $message->sender_type
            ];
        }

        return [
            'history'      => $history,
            'conversation' => $conversation
        ];
    }

    public static function getContext()
    {

        if ($conversation = static::getActiveConversation()) {

            $message = $conversation->messages()->orderBy('created_at', 'asc')->get();
            $context = [];

            foreach ($message as $msg) {
                $context[] = [
                    'sender_type' => $msg->sender_type,
                    'message'     => $msg->message
                ];
            }

            return $context;
        }

        return [];
    }

    public static function validateChatRequest($chatService)
    {
        $request = App::request();
        $sessionUserContext = Helper::getSessionUserContext();

        $data = array_merge($sessionUserContext, [
            'message' => $request->getSafe('message', 'sanitize_textarea_field')
        ]);

        $rules = [
            'message' => 'required|string|min:1|max:2000'
        ];

        if (!$chatService->hasExistingSession()) {
            $rules['name'] = 'required|string|min:2|max:100';
            $rules['email'] = 'required|email';
        }

        $validator = Validator::make($data, $rules);

        if ($validator->fails()) {
            // check the error reason
            $errors = $validator->errors();
            $errorMessage = 'Validation failed';

            if (Arr::has($errors, 'message')) {
                $errorMessage = 'Please enter a message';
            }

            if (Arr::has($errors, 'name')) {
                $errorMessage = 'Name is required';
            }

            if (Arr::has($errors, 'email')) {
                $errorMessage = 'Email is required';
            }

            // 🔒 PHPCS: Validator is not directly output, it's passed to an exception.
            // Any later output must be explicitly escaped.
            // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
            throw new ValidationException($errorMessage, $validator->errors());
        }
    }
}
