<?php

namespace App\Http\Controllers;

use App\Models\Ticket;
use App\Models\Project;
use App\Models\Comment;
use App\Models\Attachment;
use App\Models\TicketActivity;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;

class TicketController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index(Request $request)
    {
        $query = Ticket::with(['project', 'requester', 'assignedUser']);

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('priority')) {
            $query->where('priority', $request->priority);
        }

        if ($request->filled('project_id')) {
            $query->where('project_id', $request->project_id);
        }

        if ($request->filled('search')) {
            $query->where(function($q) use ($request) {
                $q->where('title', 'like', '%' . $request->search . '%')
                  ->orWhere('description', 'like', '%' . $request->search . '%')
                  ->orWhere('ticket_number', 'like', '%' . $request->search . '%');
            });
        }

        $user = Auth::user();
        if ($user->role === 'solicitante') {
            // Clientes solo ven sus tickets creados
            $query->where('requester_id', $user->id);
        } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor'])) {
            // Técnicos, Ingenieros y Supervisores solo ven tickets asignados directamente a ellos
            $query->where('assigned_to', $user->id);
        }
        // Administradores ven todos los tickets (no se filtra)

        $tickets = $query->orderBy('created_at', 'desc')->paginate(15);
        
        // Agregar información de comentarios no leídos
        foreach ($tickets as $ticket) {
            if ($user->role === 'solicitante' && $ticket->requester_id === $user->id) {
                $ticket->unreadCount = $ticket->getUnreadCommentsForRequester();
            } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor']) && $ticket->assigned_to === $user->id) {
                $ticket->unreadCount = $ticket->getUnreadCommentsForAssigned();
            } else {
                $ticket->unreadCount = 0;
            }
        }
        
        $projects = Project::where('status', 'activo')->get();

        return view('tickets.index', compact('tickets', 'projects'));
    }

    public function create()
    {
        $user = Auth::user();
        
        // Filtrar proyectos disponibles según el rol del usuario
        if ($user->role === 'solicitante') {
            // Clientes solo ven sus proyectos asignados
            $projects = $user->projects()->where('status', 'activo')->get();
        } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor'])) {
            // Técnicos/Ingenieros/Supervisores solo ven sus proyectos asignados
            $projects = $user->projects()->where('status', 'activo')->get();
        } else {
            // Administradores ven todos los proyectos activos
            $projects = Project::where('status', 'activo')->get();
        }
        
        return view('tickets.create', compact('projects'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'required|string',
            'project_id' => 'nullable|exists:projects,id',
            'priority' => 'required|in:baja,media,alta,critica',
            'due_date' => 'nullable|date',
            'attachments.*' => 'nullable|file|max:10240',
        ]);
        
        $user = Auth::user();
        
        // Validar que el cliente solo pueda crear tickets en sus proyectos asignados
        if ($user->role === 'solicitante' && $request->project_id) {
            if (!$user->hasProject($request->project_id)) {
                return back()->with('error', 'No tienes permiso para crear tickets en este proyecto')->withInput();
            }
        }
        
        // Validar que técnicos solo creen tickets en sus proyectos
        if (in_array($user->role, ['responsable', 'ingeniero', 'supervisor']) && $request->project_id) {
            if (!$user->hasProject($request->project_id)) {
                return back()->with('error', 'No tienes permiso para crear tickets en este proyecto')->withInput();
            }
        }

        // Calcular fecha límite automática basada en SLA del proyecto
        $dueDate = null;
        if ($request->project_id && $request->priority) {
            $project = Project::find($request->project_id);
            if ($project) {
                // Siempre calcular automáticamente según el SLA
                $dueDate = $project->calculateDueDate($request->priority, now());
            }
        }

        // Crear ticket
        $ticket = Ticket::create([
            'title' => $request->title,
            'description' => $request->description,
            'project_id' => $request->project_id,
            'requester_id' => Auth::id(),
            'priority' => $request->priority,
            'due_date' => $dueDate,
            'status' => 'abierto',
        ]);

        // Asignación automática si el proyecto tiene configuración
        if ($request->project_id) {
            $project = Project::find($request->project_id);
            if ($project && $project->auto_assign) {
                if ($project->default_technician_id) {
                    $ticket->assigned_to = $project->default_technician_id;
                    $ticket->save();

                    TicketActivity::create([
                        'ticket_id' => $ticket->id,
                        'user_id' => Auth::id(),
                        'action' => 'assigned',
                        'description' => "Ticket asignado automáticamente a {$project->defaultTechnician->name}",
                    ]);
                }
            }
        }

        if ($request->hasFile('attachments')) {
            foreach ($request->file('attachments') as $file) {
                $path = $file->store('attachments', 'public');
                
                Attachment::create([
                    'ticket_id' => $ticket->id,
                    'file_name' => $file->getClientOriginalName(),
                    'file_path' => $path,
                    'file_type' => $file->getClientMimeType(),
                    'file_size' => $file->getSize(),
                    'uploaded_by' => Auth::id(),
                ]);
            }
        }

        TicketActivity::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'action' => 'created',
            'description' => 'Ticket creado',
        ]);

        return redirect()->route('tickets.show', $ticket)->with('success', 'Ticket creado exitosamente');
    }

    public function show(Ticket $ticket)
    {
        $ticket->load(['project', 'requester', 'assignedUser', 'comments.user', 'comments.attachments', 'attachments', 'activities.user', 'workSessions.user']);
        
        // Marcar comentarios como leídos para el usuario actual
        $ticket->markCommentsAsReadFor(Auth::id());
        
        $user = Auth::user();
        
        // Iniciar sesión de trabajo automáticamente si el usuario es técnico/ingeniero/supervisor/administrador
        // y el ticket está abierto o en progreso
        if (in_array($user->role, ['responsable', 'ingeniero', 'supervisor', 'administrador']) && 
            in_array($ticket->status, ['abierto', 'en_progreso'])) {
            
            // Verificar si ya tiene una sesión activa para este ticket
            $activeSession = \App\Models\TicketWorkSession::where('ticket_id', $ticket->id)
                ->where('user_id', $user->id)
                ->whereNull('ended_at')
                ->first();
            
            // Si no hay sesión activa, crear una nueva
            if (!$activeSession) {
                \App\Models\TicketWorkSession::create([
                    'ticket_id' => $ticket->id,
                    'user_id' => $user->id,
                    'started_at' => now(),
                    'session_type' => 'view',
                ]);
            }
        }
        
        return view('tickets.show', compact('ticket'));
    }

    public function edit(Ticket $ticket)
    {
        $user = Auth::user();
        if (!$user->hasRole(['administrador', 'supervisor']) && $ticket->requester_id !== $user->id) {
            abort(403, 'No autorizado');
        }

        $projects = Project::where('status', 'activo')->get();
        $technicians = \App\Models\User::whereIn('role', ['responsable', 'ingeniero', 'supervisor', 'administrador'])->get();

        return view('tickets.edit', compact('ticket', 'projects', 'technicians'));
    }

    public function update(Request $request, Ticket $ticket)
    {
        $user = Auth::user();
        
        // Verificar permisos para actualizar el ticket
        $canUpdate = false;
        
        if ($user->role === 'administrador') {
            $canUpdate = true;
        } elseif ($user->role === 'solicitante') {
            // Clientes solo pueden editar sus propios tickets (campos limitados)
            $canUpdate = ($ticket->requester_id === $user->id);
        } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor'])) {
            // Técnicos/Ingenieros/Supervisores pueden actualizar si tienen acceso
            $assignedProjectIds = $user->getAssignedProjectIds();
            $canUpdate = ($ticket->assigned_to === $user->id) ||
                        ($ticket->requester_id === $user->id) ||
                        (in_array($ticket->project_id, $assignedProjectIds));
        }
        
        if (!$canUpdate) {
            abort(403, 'No tienes permisos para actualizar este ticket');
        }
        
        $request->validate([
            'title' => 'nullable|string|max:255',
            'description' => 'nullable|string',
            'status' => 'nullable|in:abierto,en_progreso,resuelto,cerrado',
            'priority' => 'nullable|in:baja,media,alta,critica',
            'assigned_to' => 'nullable|exists:users,id',
            'project_id' => 'nullable|exists:projects,id',
            'due_date' => 'nullable|date',
            'resolution_notes' => 'nullable|string',
        ]);

        $oldStatus = $ticket->status;
        $oldAssignee = $ticket->assigned_to;
        
        $ticket->update($request->only(['title', 'description', 'status', 'priority', 'assigned_to', 'project_id', 'due_date', 'resolution_notes']));

        // Log assignment change
        if ($request->filled('assigned_to') && $oldAssignee !== $request->assigned_to) {
            $assignedUser = \App\Models\User::find($request->assigned_to);
            TicketActivity::create([
                'ticket_id' => $ticket->id,
                'user_id' => Auth::id(),
                'action' => 'assigned',
                'description' => "Ticket asignado a {$assignedUser->name}",
            ]);
        }

        if ($request->filled('status') && $oldStatus !== $request->status) {
            if ($request->status === 'resuelto') {
                $ticket->resolved_at = now();
                $ticket->save();
            } elseif ($request->status === 'cerrado') {
                $ticket->closed_at = now();
                $ticket->save();
            }

            TicketActivity::create([
                'ticket_id' => $ticket->id,
                'user_id' => Auth::id(),
                'action' => 'status_changed',
                'description' => "Estado cambiado de {$oldStatus} a {$request->status}",
            ]);
        }

        return redirect()->route('tickets.show', $ticket)->with('success', 'Ticket actualizado');
    }

    public function addComment(Request $request, Ticket $ticket)
    {
        $user = Auth::user();
        
        // Verificar permisos: solo pueden comentar si tienen acceso al ticket
        $canComment = false;
        
        if ($user->role === 'administrador') {
            // Administradores pueden comentar en cualquier ticket
            $canComment = true;
        } elseif ($user->role === 'solicitante') {
            // Clientes solo pueden comentar en sus propios tickets
            $canComment = ($ticket->requester_id === $user->id);
        } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor'])) {
            // Técnicos/Ingenieros/Supervisores pueden comentar si:
            // 1. El ticket les está asignado
            // 2. El ticket es de un proyecto que tienen asignado
            // 3. Son el solicitante del ticket
            
            $assignedProjectIds = $user->getAssignedProjectIds();
            
            $canComment = ($ticket->assigned_to === $user->id) ||
                          ($ticket->requester_id === $user->id) ||
                          (in_array($ticket->project_id, $assignedProjectIds));
        }
        
        if (!$canComment) {
            return back()->with('error', 'No tienes permisos para comentar en este ticket');
        }
        
        $request->validate([
            'comment' => 'required|string',
            'attachments.*' => 'nullable|file|max:10240', // 10MB máximo por archivo
        ]);

        // Determinar el estado de lectura del comentario
        $readByRequester = false;
        $readByAssigned = false;
        
        // Si el que comenta es el solicitante, marcar como leído por él
        if (Auth::id() === $ticket->requester_id) {
            $readByRequester = true;
        }
        
        // Si el que comenta es el técnico asignado, marcar como leído por él
        if (Auth::id() === $ticket->assigned_to) {
            $readByAssigned = true;
        }

        $comment = Comment::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'content' => $request->comment,
            'read_by_requester' => $readByRequester,
            'read_by_assigned' => $readByAssigned,
        ]);

        // Procesar archivos adjuntos si existen
        if ($request->hasFile('attachments')) {
            foreach ($request->file('attachments') as $file) {
                $path = $file->store('attachments', 'public');
                
                Attachment::create([
                    'ticket_id' => $ticket->id,
                    'comment_id' => $comment->id, // Asociar al comentario
                    'user_id' => Auth::id(),
                    'filename' => basename($path),
                    'original_name' => $file->getClientOriginalName(),
                    'file_path' => $path,
                    'file_size' => $file->getSize(),
                    'mime_type' => $file->getMimeType(),
                ]);
            }
            
            // Registrar actividad de archivos adjuntos
            TicketActivity::create([
                'ticket_id' => $ticket->id,
                'user_id' => Auth::id(),
                'action' => 'attachment_added',
                'description' => 'Adjuntó ' . count($request->file('attachments')) . ' archivo(s) en un comentario',
            ]);
        }

        TicketActivity::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'action' => 'commented',
            'description' => 'Agregó un comentario',
        ]);

        return back()->with('success', 'Comentario agregado exitosamente');
    }

    /**
     * Reabrir un ticket cerrado
     */
    public function reopen(Request $request, Ticket $ticket)
    {
        // Verificar que el ticket esté cerrado
        if ($ticket->status !== 'cerrado') {
            return back()->with('error', 'Solo se pueden reabrir tickets cerrados');
        }
        
        $user = Auth::user();
        
        // Verificar permisos para reabrir
        $canReopen = false;
        
        if ($user->role === 'administrador') {
            $canReopen = true;
        } elseif ($user->role === 'solicitante') {
            // Los clientes pueden reabrir sus propios tickets
            $canReopen = ($ticket->requester_id === $user->id);
        } elseif (in_array($user->role, ['responsable', 'ingeniero', 'supervisor'])) {
            // Técnicos/Ingenieros/Supervisores pueden reabrir tickets de sus proyectos
            $assignedProjectIds = $user->getAssignedProjectIds();
            $canReopen = ($ticket->assigned_to === $user->id) ||
                        ($ticket->requester_id === $user->id) ||
                        (in_array($ticket->project_id, $assignedProjectIds));
        }
        
        if (!$canReopen) {
            return back()->with('error', 'No tienes permisos para reabrir este ticket');
        }
        
        // Validar motivo de reapertura
        $request->validate([
            'reopen_reason' => 'required|string|min:10|max:500',
        ], [
            'reopen_reason.required' => 'El motivo de reapertura es obligatorio',
            'reopen_reason.min' => 'El motivo debe tener al menos 10 caracteres',
            'reopen_reason.max' => 'El motivo no puede exceder 500 caracteres',
        ]);
        
        // Reabrir ticket
        $ticket->status = 'abierto';
        $ticket->resolved_at = null;
        $ticket->closed_at = null;
        $ticket->save();
        
        // Registrar actividad de reapertura
        TicketActivity::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'action' => 'reopened',
            'description' => 'Ticket reabierto. Motivo: ' . $request->reopen_reason,
        ]);
        
        // Agregar comentario con el motivo
        $readByRequester = false;
        $readByAssigned = false;
        
        // Si el que reabre es el solicitante, marcar como leído por él
        if (Auth::id() === $ticket->requester_id) {
            $readByRequester = true;
        }
        
        // Si el que reabre es el técnico asignado, marcar como leído por él
        if (Auth::id() === $ticket->assigned_to) {
            $readByAssigned = true;
        }
        
        Comment::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'content' => '🔄 **Ticket Reabierto**' . "\n\n" . 
                        '**Motivo:** ' . $request->reopen_reason . "\n\n" .
                        '_El ticket ha sido reabierto y requiere atención nuevamente._',
            'read_by_requester' => $readByRequester,
            'read_by_assigned' => $readByAssigned,
        ]);
        
        return back()->with('success', 'Ticket reabierto exitosamente. Se notificará al equipo técnico.');
    }

    /**
     * Cerrar un ticket (solo el solicitante puede cerrar cuando está resuelto)
     */
    public function close(Request $request, Ticket $ticket)
    {
        // Validar que solo el solicitante pueda cerrar
        if (Auth::id() !== $ticket->requester_id) {
            return back()->with('error', 'Solo el solicitante puede cerrar el ticket.');
        }
        
        // Validar que el ticket esté en estado "resuelto"
        if ($ticket->status !== 'resuelto') {
            return back()->with('error', 'Solo se pueden cerrar tickets que estén en estado "Resuelto".');
        }
        
        // Cambiar estado a cerrado
        $ticket->update([
            'status' => 'cerrado',
            'closed_at' => now(),
        ]);
        
        // Registrar actividad
        TicketActivity::create([
            'ticket_id' => $ticket->id,
            'user_id' => Auth::id(),
            'action' => 'closed',
            'description' => 'Ticket cerrado por el solicitante - Problema confirmado como resuelto',
        ]);
        
        // Si el cliente agregó un comentario de cierre, guardarlo
        if ($request->filled('close_comment')) {
            Comment::create([
                'ticket_id' => $ticket->id,
                'user_id' => Auth::id(),
                'content' => '✅ **Ticket Cerrado**' . "\n\n" . 
                            '**Comentario:** ' . $request->close_comment . "\n\n" .
                            '_El cliente confirma que el problema fue resuelto satisfactoriamente._',
                'read_by_requester' => true,
                'read_by_assigned' => false,
            ]);
        } else {
            Comment::create([
                'ticket_id' => $ticket->id,
                'user_id' => Auth::id(),
                'content' => '✅ **Ticket Cerrado**' . "\n\n" . 
                            '_El cliente confirma que el problema fue resuelto satisfactoriamente._',
                'read_by_requester' => true,
                'read_by_assigned' => false,
            ]);
        }
        
        return back()->with('success', '¡Ticket cerrado exitosamente! Gracias por confirmar la resolución.');
    }

    /**
     * Cerrar sesión de trabajo manualmente
     */
    public function endWorkSession(Ticket $ticket)
    {
        $user = Auth::user();
        
        // Buscar sesión activa del usuario para este ticket
        $activeSession = \App\Models\TicketWorkSession::where('ticket_id', $ticket->id)
            ->where('user_id', $user->id)
            ->whereNull('ended_at')
            ->first();
        
        if ($activeSession) {
            $activeSession->endSession();
            
            return response()->json([
                'success' => true,
                'message' => 'Sesión de trabajo finalizada',
                'duration' => $activeSession->formatted_duration,
            ]);
        }
        
        return response()->json([
            'success' => false,
            'message' => 'No hay sesión activa',
        ]);
    }

    /**
     * Mantener viva la sesión de trabajo (heartbeat)
     * Se llama cada 30 segundos desde JavaScript
     */
    public function workSessionHeartbeat(Ticket $ticket)
    {
        $user = Auth::user();
        
        // Buscar sesión activa
        $activeSession = \App\Models\TicketWorkSession::where('ticket_id', $ticket->id)
            ->where('user_id', $user->id)
            ->whereNull('ended_at')
            ->first();
        
        if ($activeSession) {
            // Actualizar timestamp para indicar que la sesión sigue activa
            $activeSession->touch();
            
            // Calcular tiempo transcurrido
            $elapsed = now()->diffInSeconds($activeSession->started_at);
            
            return response()->json([
                'success' => true,
                'active' => true,
                'elapsed_seconds' => $elapsed,
                'formatted_time' => \App\Models\TicketWorkSession::formatDuration($elapsed),
            ]);
        }
        
        return response()->json([
            'success' => true,
            'active' => false,
        ]);
    }
}
