<?php

namespace App\Http\Controllers;

use App\Models\SupportTicket;
use App\Models\TicketAgent;
use App\Models\Staff;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;

class SupportTicketController extends Controller
{
    /**
     * Helper method to get device_id
     */
    private function getDeviceId()
    {
        $device_id = session('device_id');
        if (!$device_id) {
            $device = Auth::user()->devices()->first();
            $device_id = $device ? $device->id : null;
        }
        return $device_id;
    }

    /**
     * Display a listing of tickets
     */
    public function index(Request $request)
    {
        $user = Auth::user();
        
        // Get device_id from session or user's first device
        $device_id = session('device_id');
        if (!$device_id) {
            $device = $user->devices()->first();
            $device_id = $device ? $device->id : null;
        }

        $query = SupportTicket::with(['device', 'assignedAgent', 'assignedStaff', 'messages']);
        
        if ($device_id) {
            $query->where('device_id', $device_id);
        } elseif ($user->role !== 'admin') {
            // Non-admin users with no device should see no tickets
            $query->whereNull('id');
        }

        // Filter by status
        if ($request->has('status') && $request->status !== 'all') {
            $query->byStatus($request->status);
        }

        // Filter by priority
        if ($request->has('priority') && $request->priority !== 'all') {
            $query->byPriority($request->priority);
        }

        // Filter by assigned agent
        if ($request->has('assigned_to') && $request->assigned_to !== 'all') {
            if ($request->assigned_to === 'unassigned') {
                $query->unassigned();
            } else {
                $query->assignedToUser($request->assigned_to);
            }
        }

        // Search
        if ($request->has('search') && $request->search) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('ticket_number', 'like', "%{$search}%")
                  ->orWhere('customer_phone', 'like', "%{$search}%")
                  ->orWhere('customer_name', 'like', "%{$search}%")
                  ->orWhere('subject', 'like', "%{$search}%");
            });
        }

        $tickets = $query->orderBy('created_at', 'desc')->paginate(20);

        // Get statistics
        $statistics = $this->getStatistics();

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

    /**
     * Show the form for creating a new ticket
     */
    public function create()
    {
        return view('support.tickets.create');
    }

    /**
     * Store a newly created ticket
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'customer_phone' => 'required|string',
            'customer_name' => 'nullable|string',
            'customer_email' => 'nullable|email',
            'subject' => 'required|string|max:255',
            'description' => 'required|string',
            'priority' => 'required|in:low,medium,high,urgent',
            'category' => 'nullable|string',
        ]);

        $user = Auth::user();
        
        // Get device_id from session or user's first device
        $device_id = session('device_id');
        if (!$device_id) {
            $device = $user->devices()->first();
            if (!$device) {
                return back()->with('error', 'No device found. Please set up a device first.');
            }
            $device_id = $device->id;
        }

        $validated['device_id'] = $device_id;
        $validated['status'] = 'new';
        $validated['created_by'] = $user->id;

        $ticket = SupportTicket::create($validated);

        // Add initial message
        if ($request->description) {
            $ticket->addMessage(
                $request->description,
                'customer',
                null,
                'text'
            );
        }

        return redirect()->route('support.tickets.show', $ticket->id)
            ->with('success', 'Ticket created successfully.');
    }

    /**
     * Display the specified ticket
     */
    public function show($id)
    {
        $user = Auth::user();
        
        // Get device_id from session or user's first device
        $device_id = session('device_id') ?? $user->devices()->first()?->id;
        
        // Build query
        $query = SupportTicket::with(['device', 'assignedAgent', 'assignedStaff', 'creator', 'messages' => function ($query) {
            $query->orderBy('created_at', 'asc');
        }, 'lead']);
        
        // Filter by device if user is not admin
        if ($user->role !== 'admin' && $device_id) {
            $query->where('device_id', $device_id);
        }
        
        $ticket = $query->findOrFail($id);

        // Get available agents for assignment
        $availableAgents = TicketAgent::available()
            ->forDevice($ticket->device_id)
            ->with('user')
            ->get();

        // Get available staff for assignment
        $availableStaff = Staff::where('device_id', $ticket->device_id)
            ->where('user_id', $user->id)
            ->where('status', 'active')
            ->get();

        return view('support.tickets.show', compact('ticket', 'availableAgents', 'availableStaff'));
    }

    /**
     * Assign ticket to an agent or staff member
     */
    public function assign(Request $request, $id)
    {
        $request->validate([
            'agent_id' => 'nullable|string',
        ]);

        $user = Auth::user();
        
        // Get device_id from session or user's first device
        $device_id = session('device_id');
        if (!$device_id) {
            $device = $user->devices()->first();
            $device_id = $device ? $device->id : null;
        }

        $ticket = SupportTicket::where('device_id', $device_id)->findOrFail($id);
        
        $assigneeId = $request->agent_id;
        
        // Check if it's a staff member (starts with 'staff_')
        if (str_starts_with($assigneeId, 'staff_')) {
            $staffId = (int) str_replace('staff_', '', $assigneeId);
            
            // Verify staff belongs to same device
            $staff = Staff::where('id', $staffId)
                ->where('device_id', $device_id)
                ->where('status', 'active')
                ->firstOrFail();
            
            // Clear agent assignment and assign to staff
            $ticket->update([
                'assigned_to' => null,
                'assigned_staff_id' => $staffId,
                'status' => 'assigned',
            ]);
            
            return back()->with('success', "Ticket assigned to staff member: {$staff->staff_name}");
        } else {
            // Regular agent assignment
            $agentUserId = (int) $assigneeId;
            
            // Verify agent belongs to same device
            $agent = TicketAgent::where('user_id', $agentUserId)
                ->where('device_id', $device_id)
                ->firstOrFail();
            
            // Clear staff assignment and assign to agent
            $ticket->update([
                'assigned_to' => $agentUserId,
                'assigned_staff_id' => null,
                'status' => 'assigned',
            ]);
            
            return back()->with('success', 'Ticket assigned to agent successfully.');
        }
    }

    /**
     * Accept a ticket (by current user/agent)
     */
    public function accept($id)
    {
        $user = Auth::user();
        
        // Get device_id from session or user's first device
        $device_id = session('device_id');
        if (!$device_id) {
            $device = $user->devices()->first();
            $device_id = $device ? $device->id : null;
        }

        $ticket = SupportTicket::where('device_id', $device_id)->findOrFail($id);
        
        $agent = TicketAgent::where('user_id', Auth::id())
            ->where('device_id', $ticket->device_id)
            ->first();

        if (!$agent) {
            return back()->with('error', 'You are not registered as an agent.');
        }

        if (!$agent->canAcceptTicket()) {
            return back()->with('error', 'You cannot accept more tickets at this time.');
        }

        $ticket->assignToAgent(Auth::id());

        return back()->with('success', 'Ticket accepted successfully.');
    }

    /**
     * Resolve a ticket
     */
    public function resolve(Request $request, $id)
    {
        $request->validate([
            'resolution_note' => 'nullable|string|max:1000',
        ]);

        $ticket = SupportTicket::where('device_id', $this->getDeviceId())->findOrFail($id);
        $ticket->changeStatus('resolved', Auth::id());

        if ($request->resolution_note) {
            $ticket->addSystemMessage('Resolution note: ' . htmlspecialchars($request->resolution_note, ENT_QUOTES, 'UTF-8'));
        }

        return back()->with('success', 'Ticket resolved successfully.');
    }

    /**
     * Reopen a ticket
     */
    public function reopen($id)
    {
        $ticket = SupportTicket::where('device_id', $this->getDeviceId())->findOrFail($id);
        $ticket->changeStatus('open', Auth::id());

        return back()->with('success', 'Ticket reopened successfully.');
    }

    /**
     * Close a ticket
     */
    public function close($id)
    {
        $ticket = SupportTicket::where('device_id', $this->getDeviceId())->findOrFail($id);
        $ticket->changeStatus('closed', Auth::id());

        return back()->with('success', 'Ticket closed successfully.');
    }

    /**
     * Add a message to the ticket
     */
    public function addMessage(Request $request, $id)
    {
        $request->validate([
            'message' => 'required|string|max:5000',
            'is_internal_note' => 'nullable|boolean',
            'attachments.*' => 'nullable|file|max:10240|mimes:jpg,jpeg,png,pdf,doc,docx,xls,xlsx',
        ]);

        $ticket = SupportTicket::where('device_id', $this->getDeviceId())->findOrFail($id);

        $attachments = [];
        if ($request->hasFile('attachments')) {
            $allowedMimes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 
                            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                            'application/vnd.ms-excel', 
                            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
            
            foreach ($request->file('attachments') as $file) {
                // Security: Validate mime type
                if (!in_array($file->getMimeType(), $allowedMimes)) {
                    continue;
                }
                
                // Security: Sanitize filename
                $originalName = $file->getClientOriginalName();
                $safeName = preg_replace('/[^a-zA-Z0-9._-]/', '_', $originalName);
                
                $path = $file->store('ticket-attachments', 'public');
                $attachments[] = [
                    'filename' => $safeName,
                    'path' => $path,
                    'type' => $file->getMimeType(),
                    'size' => $file->getSize(),
                ];
            }
        }

        $ticket->addMessage(
            htmlspecialchars($request->message, ENT_QUOTES, 'UTF-8'),
            'agent',
            Auth::id(),
            'text',
            $attachments ?: null
        );

        return back()->with('success', 'Message added successfully.');
    }

    /**
     * Upload attachment to a ticket
     */
    public function uploadAttachment(Request $request, $id)
    {
        $request->validate([
            'file' => 'required|file|max:10240|mimes:jpg,jpeg,png,pdf,doc,docx,xls,xlsx', // 10MB max
        ]);

        $ticket = SupportTicket::where('device_id', $this->getDeviceId())->findOrFail($id);

        $file = $request->file('file');
        
        // Security: Additional mime type validation
        $allowedMimes = ['image/jpeg', 'image/png', 'application/pdf', 'application/msword', 
                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                        'application/vnd.ms-excel', 
                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
        
        if (!in_array($file->getMimeType(), $allowedMimes)) {
            return response()->json([
                'success' => false,
                'message' => 'File type not allowed.',
            ], 422);
        }
        
        // Security: Sanitize filename
        $originalName = $file->getClientOriginalName();
        $safeName = preg_replace('/[^a-zA-Z0-9._-]/', '_', $originalName);
        
        $path = $file->store('ticket-attachments', 'public');

        $attachment = [
            'filename' => $safeName,
            'path' => $path,
            'type' => $file->getMimeType(),
            'size' => $file->getSize(),
            'uploaded_by' => Auth::id(),
            'uploaded_at' => now()->toDateTimeString(),
        ];

        // Add to ticket attachments
        $attachments = $ticket->attachments ?? [];
        $attachments[] = $attachment;
        $ticket->attachments = $attachments;
        $ticket->save();

        return response()->json([
            'success' => true,
            'attachment' => $attachment,
        ]);
    }

    /**
     * Get ticket statistics
     */
    public function getStatistics()
    {
        $deviceId = session('device_id');

        return [
            'total' => SupportTicket::where('device_id', $deviceId)->count(),
            'new' => SupportTicket::where('device_id', $deviceId)->byStatus('new')->count(),
            'open' => SupportTicket::where('device_id', $deviceId)->open()->count(),
            'pending' => SupportTicket::where('device_id', $deviceId)->byStatus('pending')->count(),
            'resolved' => SupportTicket::where('device_id', $deviceId)->byStatus('resolved')->count(),
            'closed' => SupportTicket::where('device_id', $deviceId)->byStatus('closed')->count(),
            'unassigned' => SupportTicket::where('device_id', $deviceId)->unassigned()->count(),
        ];
    }
}
