<?php
namespace App\Services;

use App\Models\Ticket;
use App\Models\TicketPriority;
use App\Models\TicketStatus;
use Carbon\Carbon;

class TicketService
{
    public function __construct(
        private NotificationService $notif,
        private AutomationEngine    $automation,
        private AiClassifierService $ai,
        private AiResponseService    $aiResponse
    ) {}

    public function create(array $data, int $requesterId): Ticket
    {
        $priority = TicketPriority::findOrFail($data['priority_id']);
        $status   = TicketStatus::where('is_initial', true)->firstOrFail();
        $now      = Carbon::now();

        $ticket = Ticket::create([
            'number'             => Ticket::generateNumber(),
            'title'              => $data['title'],
            'description'        => $data['description'],
            'status_id'          => $status->id,
            'priority_id'        => $data['priority_id'],
            'category_id'        => $data['category_id'] ?? null,
            'type_id'            => $data['type_id'] ?? null,
            'requester_id'       => $requesterId,
            'assignee_id'        => $data['assignee_id'] ?? null,
            'department_id'      => $data['department_id'] ?? null,
            'asset_id'           => $data['asset_id'] ?? null,
            'sla_response_due'   => $now->copy()->addHours($priority->sla_response_hours),
            'sla_resolution_due' => $now->copy()->addHours($priority->sla_resolution_hours),
        ]);

        $ticket->addHistory('created', "Ticket {$ticket->number} creado", $requesterId);
        $this->notif->onTicketCreated($ticket);
        $this->automation->run('ticket_created', $ticket->fresh());

        try { $this->ai->classify($ticket->fresh()); } catch (\Throwable $e) { \Log::warning('AI: ' . $e->getMessage()); }

        return $ticket;
    }

    public function changeStatus(Ticket $ticket, int $newStatusId, ?string $comment = null): void
    {
        $oldStatus = $ticket->status;
        $newStatus = TicketStatus::findOrFail($newStatusId);

        $ticket->update([
            'status_id'   => $newStatusId,
            'resolved_at' => $newStatus->is_final && !$ticket->resolved_at ? now() : $ticket->resolved_at,
            'closed_at'   => $newStatus->is_final ? now() : $ticket->closed_at,
        ]);
        // Fase 4: generar borrador KB al cerrar
        if ($newStatus->is_final) {
            try { $this->aiResponse->generateKbDraft($ticket->fresh()); } catch (\Throwable $e) { \Log::warning('AI KB: ' . $e->getMessage()); }
        }

        $ticket->addHistory('status_changed',
            "Estado cambiado de '{$oldStatus->name}' a '{$newStatus->name}'",
            auth()->id(), 'status', $oldStatus->name, $newStatus->name);

        if ($comment) {
            $ticket->comments()->create([
                'user_id'     => auth()->id(),
                'body'        => $comment,
                'is_internal' => true,
            ]);
        }

        $this->notif->onStatusChanged($ticket->fresh(), $oldStatus->name, $newStatus->name);
        $this->automation->run('status_changed', $ticket->fresh());
    }

    public function assign(Ticket $ticket, ?int $assigneeId): void
    {
        $oldId       = $ticket->assignee_id;
        $oldAssignee = $ticket->assignee?->name ?? 'Sin asignar';
        $ticket->update(['assignee_id' => $assigneeId]);
        $newAssignee = $ticket->fresh()->assignee?->name ?? 'Sin asignar';
        $ticket->addHistory('assigned', "Asignado a: {$newAssignee}", auth()->id(), 'assignee', $oldAssignee, $newAssignee);
        $this->notif->onAssigned($ticket->fresh(), $oldId);
    }

    public function checkSlaBreaches(): int
    {
        $count = 0;
        Ticket::open()
            ->where('sla_resolution_breached', false)
            ->whereNotNull('sla_resolution_due')
            ->where('sla_resolution_due', '<', now())
            ->each(function ($ticket) use (&$count) {
                $ticket->update(['sla_resolution_breached' => true]);
                $ticket->addHistory('sla_breached', 'SLA de resolución incumplido', null);
                $this->automation->run('sla_breached', $ticket->fresh());
                $count++;
            });
        return $count;
    }

    public function checkIdleTickets(): int
    {
        $count = 0;
        Ticket::open()
            ->where('updated_at', '<', now()->subHours(24))
            ->each(function ($ticket) use (&$count) {
                $this->automation->run('ticket_idle', $ticket->fresh());
                $count++;
            });
        return $count;
    }
}
