<?php
namespace App\Services;

use App\Models\AutomationRule;
use App\Models\AutomationLog;
use App\Models\NexusNotification;
use App\Models\Ticket;
use App\Models\User;
use Carbon\Carbon;

class AutomationEngine
{
    public function run(string $trigger, Ticket $ticket): int
    {
        $rules   = AutomationRule::forTrigger($trigger)->get();
        $count   = 0;
        $ticket->load(['priority','category','status','type','department','assignee','requester']);

        foreach ($rules as $rule) {
            if ($this->matchesConditions($rule, $ticket)) {
                $executed = $this->executeActions($rule, $ticket);
                if (!empty($executed)) {
                    AutomationLog::create([
                        'rule_id'          => $rule->id,
                        'ticket_id'        => $ticket->id,
                        'actions_executed' => $executed,
                        'result'           => 'success',
                        'executed_at'      => now(),
                    ]);
                    $rule->increment('executions');
                    $rule->update(['last_executed_at' => now()]);
                    $count++;
                }
            }
        }
        return $count;
    }

    private function matchesConditions(AutomationRule $rule, Ticket $ticket): bool
    {
        if (empty($rule->conditions)) return true;

        foreach ($rule->conditions as $condition) {
            ['field' => $field, 'operator' => $op, 'value' => $val] = $condition;

            $ticketVal = match($field) {
                'priority'    => (string) $ticket->priority_id,
                'category'    => (string) $ticket->category_id,
                'status'      => (string) $ticket->status_id,
                'type'        => (string) $ticket->type_id,
                'department'  => (string) $ticket->department_id,
                'requester'   => $ticket->requester?->getRoleNames()->first() ?? '',
                'has_assignee'=> $ticket->assignee_id ? 'true' : 'false',
                default       => '',
            };

            $match = match($op) {
                'equals'       => $ticketVal === (string) $val,
                'not_equals'   => $ticketVal !== (string) $val,
                'contains'     => str_contains(strtolower($ticketVal), strtolower((string)$val)),
                'is_empty'     => empty($ticketVal),
                'is_not_empty' => !empty($ticketVal),
                default        => false,
            };

            if (!$match) return false;
        }
        return true;
    }

    private function executeActions(AutomationRule $rule, Ticket $ticket): array
    {
        $executed = [];

        foreach ($rule->actions as $action) {
            ['type' => $type, 'params' => $params] = $action;

            try {
                match($type) {
                    'assign_agent' => $this->assignAgent($ticket, $params),
                    'assign_group' => $this->assignGroup($ticket, $params),
                    'change_priority' => $ticket->update(['priority_id' => $params['priority_id']]),
                    'change_status'   => $ticket->update(['status_id'   => $params['status_id']]),
                    'add_comment'     => $ticket->comments()->create([
                        'user_id'     => null,
                        'body'        => $this->renderTemplate($params['body'] ?? '', $ticket),
                        'is_internal' => true,
                    ]),
                    'send_notification' => $this->sendNotification($ticket, $params),
                    'escalate'          => $this->escalate($ticket, $params),
                    default             => null,
                };
                $executed[] = ['type' => $type, 'status' => 'ok'];
            } catch (\Throwable $e) {
                $executed[] = ['type' => $type, 'status' => 'error', 'error' => $e->getMessage()];
            }
        }
        return $executed;
    }

    private function assignAgent(Ticket $ticket, array $params): void
    {
        // Asignación round-robin al grupo o agente específico
        if (!empty($params['agent_id'])) {
            $ticket->update(['assignee_id' => $params['agent_id']]);
        } elseif (!empty($params['group_id'])) {
            $agent = User::whereHas('groups', fn($q) => $q->where('groups.id', $params['group_id']))
                ->withCount(['assignedTickets' => fn($q) => $q->open()])
                ->orderBy('assigned_tickets_count')
                ->first();
            if ($agent) $ticket->update(['assignee_id' => $agent->id]);
        }
    }

    private function assignGroup(Ticket $ticket, array $params): void
    {
        if (!empty($params['group_id'])) {
            $ticket->update(['group_id' => $params['group_id']]);
        }
    }

    private function sendNotification(Ticket $ticket, array $params): void
    {
        $recipients = match($params['recipient'] ?? 'assignee') {
            'assignee'  => $ticket->assignee_id ? [$ticket->assignee_id] : [],
            'requester' => [$ticket->requester_id],
            'admins'    => User::role(['admin','superadmin'])->pluck('id')->toArray(),
            default     => [],
        };
        foreach ($recipients as $uid) {
            NexusNotification::send(
                $uid,
                $params['type'] ?? 'ticket_updated',
                $this->renderTemplate($params['title'] ?? 'Automatización ejecutada', $ticket),
                $this->renderTemplate($params['body']  ?? $ticket->title, $ticket),
                route('tickets.show', $ticket)
            );
        }
    }

    private function escalate(Ticket $ticket, array $params): void
    {
        $supervisors = User::role(['admin','superadmin','jefe_soporte'])->get();
        foreach ($supervisors as $sup) {
            NexusNotification::send(
                $sup->id, 'sla_breached',
                "Ticket escalado: {$ticket->number}",
                "El ticket requiere atención urgente: {$ticket->title}",
                route('tickets.show', $ticket)
            );
        }
    }

    private function renderTemplate(string $text, Ticket $ticket): string
    {
        return str_replace(
            ['{{ticket}}', '{{titulo}}', '{{solicitante}}', '{{agente}}', '{{prioridad}}'],
            [$ticket->number, $ticket->title, $ticket->requester->name,
             $ticket->assignee?->name ?? 'Sin asignar', $ticket->priority->name],
            $text
        );
    }
}
