<?php

namespace App\Http\Controllers;

use App\Models\Account;
use App\Models\Activity;
use App\Models\Call;
use App\Models\Company;
use App\Models\Contact;
use App\Models\Country;
use App\Models\Event;
use App\Models\Language;
use App\Models\LeadStage;
use App\Models\MeetingThirdPartyIntegration;
use App\Models\Note;
use App\Models\Priority;
use App\Models\Product;
use App\Models\Repeat;
use App\Models\Status;
use App\Models\Task;
use App\Models\Ticket;
use App\Models\TicketLanguage;
use App\Models\TicketPriority;
use App\Models\TicketProduct;
use App\Models\TicketSource;
use App\Models\TicketStage;
use App\Models\TicketStageStatus;
use App\Models\TicketAssignmentHistory;
use App\Models\TicketStatusTransition;
use App\Models\CrmAssignment;
use App\Models\CrmStatusHistory;
use App\Models\Campaign;
use App\Models\UserAccess;
use App\Models\AccessType;
use App\Models\User;
use App\Models\WonLost;
use App\Services\CrmNotificationService;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Validation\Rule;

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

        $this->middleware('permission:list_tickets')->only(['index']);
        $this->middleware('permission:list_tickets')->only(['show']);
        $this->middleware('permission:create_tickets')->only(['create', 'store']);
        $this->middleware('permission:update_tickets')->only(['edit', 'update']);
        $this->middleware('permission:delete_tickets')->only(['destroy']);
    }

    public function index(Request $request)
    {
        $user = auth()->user();
        $ticketQuery = $this->getAccessibleTickets($user->id);
        $this->useDefaultDateRange($request);
        $request->validate([
            'q' => ['nullable','string','max:100'],
            'stage_id' => ['nullable','integer'],
            'priority_id' => ['nullable','integer'],
            'contact_owner_id' => ['nullable','integer'],
            'date_from' => ['nullable','date'],
            'date_to' => ['nullable','date','after_or_equal:date_from'],
        ]);
        $search = trim((string) $request->input('q'));
        $ticketQuery
        ->when($request->filled('stage_id'), fn ($query) => $query->where('stage_id', $request->integer('stage_id')))
        ->when($request->filled('priority_id'), fn ($query) => $query->where('priority_id', $request->integer('priority_id')))
        ->when($request->filled('contact_owner_id'), fn ($query) => $query->where('contact_owner_id', $request->integer('contact_owner_id')))
        ->when($request->filled('date_from'), fn ($query) => $query->whereDate('created_at', '>=', $request->date_from))
        ->when($request->filled('date_to'), fn ($query) => $query->whereDate('created_at', '<=', $request->date_to))
        ->when($search !== '', fn ($query) => $query->where(fn ($filter) => $filter
            ->where('topic', 'like', "%{$search}%")
            ->orWhere('contact_name', 'like', "%{$search}%")
            ->orWhere('email', 'like', "%{$search}%")
            ->orWhere('phone', 'like', "%{$search}%")));
        $todayTicketsCount = (clone $ticketQuery)->whereDate('created_at', today())->count();
        $monthTicketsCount = (clone $ticketQuery)->whereMonth('created_at', now()->month)->whereYear('created_at', now()->year)->count();
        $yearTicketsCount = (clone $ticketQuery)->whereYear('created_at', now()->year)->count();
        $totalTicketsCount = (clone $ticketQuery)->count();
        $ticketPaginator = $ticketQuery->latest()->paginate(25)->withQueryString();
        $tickets = collect($ticketPaginator->items());

        // Ticket counts
        $todayTickets = $tickets->filter(fn ($ticket) => $ticket->created_at->isToday());
        $monthTickets = $tickets->filter(fn ($ticket) => $ticket->created_at->isCurrentMonth());
        $yearTickets = $tickets->filter(fn ($ticket) => $ticket->created_at->isCurrentYear());
        $totalTickets = $tickets; // already fetched

        $stages = TicketStage::all();
        $activities = collect();
        $priorities = Priority::all();
        $countries = Country::all();
        $meetings = MeetingThirdPartyIntegration::all();
        $eventStatuses = Status::all();
        $companies = Company::all();
        $repeats = Repeat::all();
        $users = $this->getAccessibleUsers();
        $contacts = Contact::where('business_id', $user->business_id)
            ->orderBy('first_name')->limit(250)->get(['id', 'first_name', 'last_name']);

        $activityTypes = [
            1 => 'Call',
            2 => 'Appointment',
            3 => 'Task',
            4 => 'Event',
            5 => 'Deadline',
            6 => 'Other Activity',
            7 => 'Letter',
            8 => 'Fax',
            9 => 'Email',
            10 => 'Campaign',
        ];

        return view('ticket.tickets', compact(
            'tickets',
            'todayTickets',
            'monthTickets',
            'yearTickets',
            'totalTickets',
            'stages',
            'activities',
            'activityTypes',
            'priorities',
            'countries',
            'meetings',
            'eventStatuses',
            'companies',
            'repeats',
            'contacts',
            'users',
            'ticketPaginator',
            'todayTicketsCount',
            'monthTicketsCount',
            'yearTicketsCount',
            'totalTicketsCount'
        ));
    }

    private function getAccessibleTickets($userId, $filter = null)
    {
        $accessibleUserIds = $this->getAccessibleUserIds($userId);

        $query = Ticket::with(['ticketProducts', 'ticketLanguages', 'assignedUser'])
            ->whereIn('contact_owner_id', $accessibleUserIds)
            ->where('business_id', auth()->user()->business_id);
        $query->whereNull('moved_at');

        // Apply date filters
        if ($filter === 'today') {
            $query->whereDate('created_at', today());
        } elseif ($filter === 'month') {
            $query->whereMonth('created_at', now()->month)
                ->whereYear('created_at', now()->year);
        } elseif ($filter === 'year') {
            $query->whereYear('created_at', now()->year);
        }

        return $query;
    }

    private function getAccessibleUserIds($currentUserId)
    {
        $accessibleUserIds = collect([$currentUserId]); // Always include self

        // Check if current user is admin - admins can see all users
        $currentUser = User::find($currentUserId);
        if ($currentUser && $currentUser->is_admin === 1) {
            // Return all user IDs for admin users
            return User::where('business_id', auth()->user()->business_id)
                ->pluck('id')
                ->toArray();
        }

        // Employees may only view Tickets assigned directly to them.
        return [$currentUserId];

        // First, check what access type the current user has
        $currentUserAccess = UserAccess::where('user_id', $currentUserId)->first();
        
        // If current user is PRIVATE, they can only see their own data
        if ($currentUserAccess && $currentUserAccess->access_type_id == AccessType::PRIVATE) {
            return $accessibleUserIds->unique()->toArray(); // Return only self
        }

        // If current user is PUBLIC, they can see PUBLIC, PRIVATE, and SPECIFIC users
        if ($currentUserAccess && $currentUserAccess->access_type_id == AccessType::PUBLIC) {
            $publicUsers = UserAccess::where('access_type_id', AccessType::PUBLIC)
                ->pluck('user_id');
            $privateUsers = UserAccess::where('access_type_id', AccessType::PRIVATE)
                ->pluck('user_id');
            $specificUsers = UserAccess::where('access_type_id', AccessType::SPECIFIC_USERS)
                ->pluck('user_id');
            
            $accessibleUserIds = $accessibleUserIds->merge($publicUsers)
                ->merge($privateUsers)
                ->merge($specificUsers);
        return $accessibleUserIds->unique()->toArray();
        } 

        // Get users with SPECIFIC_USERS access where current user is specifically allowed
        $specificUsers = UserAccess::where('access_type_id', AccessType::SPECIFIC_USERS)
            ->where('user_id', $currentUserId)
            ->pluck('specific_user_id'); 
        $accessibleUserIds = $accessibleUserIds->merge($specificUsers);

        return $accessibleUserIds->unique()->toArray();
    }

    private function getAccessibleUsers()
    {
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        return User::whereIn('id', $accessibleUserIds)->get();
    }

    public function updateTicketStage(Request $request, $id)
    {
        $validated = $request->validate([
            'stage_id' => 'required|integer',
        ]);

        $ticket = Ticket::findOrFail($id);

        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to update this ticket.');
        }

        $currentStageId = $ticket->stage_id;
        $this->assertAllowedStageTransition($ticket, (int) $validated['stage_id'], $request->input('reason'));

        $ticket->stage_id = $validated['stage_id'];
        $ticket->save();
        $this->recordStageHistory($ticket, $currentStageId, (int) $validated['stage_id'], $request->input('reason'));

        // Loop through all the previous stages and set their stage_status to 3 (completed)
        for ($i = 1; $i < $validated['stage_id']; $i++) {
            $ticketStageStatus = TicketStageStatus::firstOrCreate([
                'ticket_id' => $ticket->id,
                'stage_id' => $i,
            ]);

            $ticketStageStatus->stage_status = 3; // Set to completed
            $ticketStageStatus->save();
        }

        // Set the stage_status for the current stage to 1 (active)
        $ticketStageStatus = TicketStageStatus::firstOrCreate([
            'ticket_id' => $ticket->id,
            'stage_id' => $validated['stage_id'],
        ]);

        $ticketStageStatus->stage_status = 1; // Set to active
        $ticketStageStatus->save();

        return response()->json(['message' => 'Stage updated successfully!']);
    }

    public function updateStageStatus(Request $request)
    {
        $ticket = Ticket::findOrFail($request->ticket_id);

        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to update this ticket.');
        }

        $request->validate([
            'ticket_id' => 'required|exists:tickets,id',
            'stage_status' => 'required|in:1,2,3',
            'stage_id' => 'required|integer',
        ]);

        $ticketStageStatus = TicketStageStatus::updateOrCreate(
            ['ticket_id' => $request->ticket_id, 'stage_id' => $request->stage_id],
            ['stage_status' => $request->stage_status]
        );

        $highestStageId = TicketStageStatus::where('ticket_id', $request->ticket_id)
            ->max('stage_id');

        $highestStageStatus = TicketStageStatus::where('ticket_id', $request->ticket_id)
            ->where('stage_id', $highestStageId)
            ->value('stage_status');

        if ($highestStageStatus == 3) {
            $ticket = Ticket::find($request->ticket_id);
            if ($ticket) {
                $ticket->stage_id = $highestStageId;
                $ticket->save();
            }
        }

        return response()->json([
            'success' => true,
            'message' => 'Stage status updated successfully!',
        ]);
    }

    public function activitiesKList()
    {
        $ticketIds = Ticket::whereIn('contact_owner_id', $this->getAccessibleUserIds(auth()->id()))->pluck('id');
        $calls = Call::whereIn('ticket_id', $ticketIds)->get();
        $tasks = Task::whereIn('ticket_id', $ticketIds)->get();
        $events = Event::whereIn('ticket_id', $ticketIds)->get();

        // dd($contacts);
        return view('ticket.lists', compact('calls', 'tasks', 'events'));
    }


    public function dashboard()
    {
        $stages = TicketStage::all();
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());

        // Base query
        $baseQuery = Ticket::whereIn('contact_owner_id', $accessibleUserIds);

        // Ticket counts
        $todayTickets = (clone $baseQuery)->whereDate('created_at', today())->count();
        $monthTickets = (clone $baseQuery)->whereMonth('created_at', now()->month)
                                        ->whereYear('created_at', now()->year)
                                        ->count();
        $yearTickets  = (clone $baseQuery)->whereYear('created_at', now()->year)->count();
        $totalTickets = (clone $baseQuery)->count();

        // Tickets grouped by stage (keeping your logic intact)
        $tickets = $baseQuery->get()
            ->map(function ($ticket) {
                $ticketStageStatus = TicketStageStatus::where('ticket_id', $ticket->id)
                    ->where('stage_status', '!=', 3)
                    ->first();

                $ticket->current_stage_id = $ticketStageStatus ? $ticketStageStatus->stage_id : $ticket->stage_id;

                return $ticket;
            })
            ->groupBy('current_stage_id');

        return view('ticket.tickets-dashboard', compact(
            'tickets',
            'stages',
            'todayTickets',
            'monthTickets',
            'yearTickets',
            'totalTickets'
        ));
    }


    public function updateStage(Request $request, $ticketId)
    {

        $request->validate([
            'stage_id' => 'required|exists:ticket_stages,id',
        ]);

        $ticket = Ticket::find($ticketId);

        if (!$ticket) {
            return response()->json(['message' => 'Ticket not found'], 404);
        }

        // Check access permission
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            return response()->json(['message' => 'You do not have permission to update this ticket.'], 403);
        }

        $previousStage = (int) $ticket->stage_id;
        $this->assertAllowedStageTransition($ticket, (int) $request->stage_id, $request->input('reason'));
        $ticket->stage_id = $request->stage_id;
        $ticket->save();
        $this->recordStageHistory($ticket, $previousStage, (int) $request->stage_id, $request->input('reason'));

        return response()->json(['message' => 'Ticket stage updated successfully']);
    }

    public function create()
    {
        $languages = Language::all();
        $contacts = Contact::all();
        $stages = TicketStage::all();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $ticketSources  = TicketSource::all();
        $campaigns = Campaign::where('business_id', auth()->user()->business_id)->orderBy('campaign_name')->get();
        $priorities  = TicketPriority::all();
        $users = $this->getAccessibleUsers();

        return view('ticket.ticket-create', compact('languages', 'contacts', 'stages', 'companies', 'products', 'accounts', 'ticketSources', 'priorities', 'users', 'campaigns'));
    }


    public function store(Request $request)
    {
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        $request->validate([
            'contact_owner' => 'required|in:' . implode(',', $accessibleUserIds),
            'stage_id' => 'required|exists:ticket_stages,id',
            'topic' => 'required|string|max:255',
            'campaign_id' => ['nullable', Rule::exists('campaigns', 'id')->where(fn ($query) => $query->where('business_id', auth()->user()->business_id))],
            'languages' => 'nullable|array',
            'products' => 'required|array|min:1',
            'products.*' => 'exists:products,id',
        ]);

        $ticket = Ticket::create([
            'business_id' => auth()->user()->business_id,
            'contact_owner_id' => $request->contact_owner,
            'primary_contact_id' => $request->primary_contact,
            'employee_id' => $request->employee_id,
            'account_id' => $request->account_id,
            'source_id' => $request->source_id,
            'campaign_id' => $request->campaign_id,
            'topic' => $request->topic,
            'description' => $request->description,
            'comments' => $request->comments,
            'contact_name' => $request->contact_name,
            'phone' => $request->phone,
            'email' => $request->email,
            'social_media' => $request->social_media,
            'priority_id' => $request->priority_id,
            'stage_id' => $request->stage_id,
            'date_time' => $request->date_time,
        ]);

        TicketAssignmentHistory::create([
            'business_id' => $ticket->business_id,
            'ticket_id' => $ticket->id,
            'from_user_id' => null,
            'to_user_id' => $ticket->contact_owner_id,
            'assigned_by' => auth()->id(),
            'note' => 'Initial Ticket assignment',
        ]);
        CrmAssignment::create([
            'business_id' => $ticket->business_id,
            'assignable_type' => Ticket::class,
            'assignable_id' => $ticket->id,
            'user_id' => $ticket->contact_owner_id,
            'assigned_by' => auth()->id(),
        ]);
        if ($assignee = User::find($ticket->contact_owner_id)) {
            app(CrmNotificationService::class)->assignment(
                $assignee,
                $ticket,
                'Ticket',
                route('ticket.view', ['id' => $ticket->id])
            );
        }
        CrmStatusHistory::create([
            'business_id' => $ticket->business_id,
            'statusable_type' => Ticket::class,
            'statusable_id' => $ticket->id,
            'from_status' => null,
            'to_status' => TicketStage::find($ticket->stage_id)?->name ?? (string) $ticket->stage_id,
            'reason' => 'Ticket created',
            'changed_by' => auth()->id(),
            'changed_at' => now(),
        ]);


        foreach ($request->input('languages', []) as $languageId) {
            TicketLanguage::create([
                'ticket_id' => $ticket->id,
                'language_id' => $languageId,
            ]);
        }

        foreach ($request->input('products', []) as $productId) {
            TicketProduct::create([
                'ticket_id' => $ticket->id,
                'product_id' => $productId,
            ]);
        }


        return redirect()->route('tickets')->with('success', 'Ticket created successfully!');
    }

    public function show(Request $request)
    {

        $ticketId = $request->query('id');
        $ticket = Ticket::with([
            'ticketLanguages',
            'assignedUser',
            'ticketProducts.product',
            'campaign',
            'account',
            'primaryContact',
            'activities',
            'assignments.user',
            'statusHistory.changedBy',
            'files',
            'moveHistories.actor',
            'assignmentHistories.fromUser',
            'assignmentHistories.toUser',
            'assignmentHistories.actor',
        ])->findOrFail($ticketId);

        // Check if current user can access this ticket's owner
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to view this ticket.');
        }

        $notes = Note::where('ticket_id', $ticketId)->get();
        $activities = $ticket->activities;

        $won = WonLost::where('ticket_id', $ticketId)
            ->where('status', 'WON')
            ->get();
        $lost = WonLost::where('ticket_id', $ticketId)
            ->where('status', 'LOST')
            ->get();

        $stages = TicketStage::all();

        // dd($contacts);
        return view('ticket.ticket-view', compact('ticket', 'notes', 'activities', 'won', 'lost', 'stages'));
    }

    public function edit(Request $request)
    {
        $ticketId = $request->query('id');

        $ticket = Ticket::with(['ticketLanguages'])->findOrFail($ticketId);

        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to edit this ticket.');
        }

        $languages = Language::all();
        $contacts = Contact::all();
        $stages = TicketStage::all();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $ticketSources  = TicketSource::all();
        $campaigns = Campaign::where('business_id', auth()->user()->business_id)->orderBy('campaign_name')->get();
        $priorities  = TicketPriority::all();
        $users = $this->getAccessibleUsers();



        return view('ticket.ticket-edit', compact('ticket', 'languages', 'contacts', 'stages', 'companies', 'users', 'accounts', 'ticketSources', 'priorities', 'products', 'campaigns'));
    }



    public function update(Request $request, $id)
    {
        // Find the ticket by ID
        $ticket = Ticket::findOrFail($id);

        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to update this ticket.');
        }

        // dd($request);
        $validated = $request->validate([
            'contact_owner' => 'required|in:' . implode(',', $accessibleUserIds),
            'topic' => 'required|string|max:255',
            'languages' => 'nullable|array',
            'languages.*' => 'exists:languages,id',
            'products' => 'required|array|min:1',
            'products.*' => 'exists:products,id',
            'stage_id' => 'required|exists:ticket_stages,id',
            'campaign_id' => ['nullable', Rule::exists('campaigns', 'id')->where(fn ($query) => $query->where('business_id', auth()->user()->business_id))],
        ]);

        $previousOwner = $ticket->contact_owner_id;
        $previousStage = (int) $ticket->stage_id;
        $this->assertAllowedStageTransition($ticket, (int) $request->stage_id, $request->input('stage_change_reason'));

        // Update the ticket data
        $ticket->update([
            'business_id' => auth()->user()->business_id,
            'contact_owner_id' => $request->contact_owner,
            'primary_contact_id' => $request->primary_contact,
            'employee_id' => $request->employee_id,
            'account_id' => $request->account_id,
            'source_id' => $request->source_id,
            'campaign_id' => $request->campaign_id,
            'topic' => $request->topic,
            'description' => $request->description,
            'comments' => $request->comments,
            'contact_name' => $request->contact_name,
            'phone' => $request->phone,
            'email' => $request->email,
            'social_media' => $request->social_media,
            'priority_id' => $request->priority_id,
            'stage_id' => $request->stage_id,
            'date_time' => $request->date_time,
        ]);

        if ((int) $previousOwner !== (int) $ticket->contact_owner_id) {
            TicketAssignmentHistory::create([
                'business_id' => $ticket->business_id,
                'ticket_id' => $ticket->id,
                'from_user_id' => $previousOwner,
                'to_user_id' => $ticket->contact_owner_id,
                'assigned_by' => auth()->id(),
                'note' => $request->assignment_note,
            ]);
            if ($assignee = User::find($ticket->contact_owner_id)) {
                app(CrmNotificationService::class)->assignment(
                    $assignee,
                    $ticket,
                    'Ticket',
                    route('ticket.view', ['id' => $ticket->id])
                );
            }
        }
        CrmAssignment::updateOrCreate([
            'business_id' => $ticket->business_id,
            'assignable_type' => Ticket::class,
            'assignable_id' => $ticket->id,
            'user_id' => $ticket->contact_owner_id,
        ], ['assigned_by' => auth()->id()]);
        $this->recordStageHistory($ticket, $previousStage, (int) $ticket->stage_id, $request->input('stage_change_reason'));

        // Update languages associated with the ticket
        TicketLanguage::where('ticket_id', $id)->delete();
        foreach ($request->languages as $languageId) {
            TicketLanguage::create([
                'ticket_id' => $ticket->id,
                'language_id' => $languageId,
            ]);
        }

        // Update products associated with the ticket
        TicketProduct::where('ticket_id', $id)->delete();
        foreach ($request->products as $productId) {
            TicketProduct::create([
                'ticket_id' => $ticket->id,
                'product_id' => $productId,
            ]);
        }


        return redirect()->route('tickets')->with('success', 'Ticket updated successfully!');
    }

    private function assertAllowedStageTransition(Ticket $ticket, int $toStageId, ?string $reason = null): void
    {
        $fromStageId = (int) $ticket->stage_id;
        if ($fromStageId === $toStageId) {
            return;
        }

        $transition = TicketStatusTransition::where('from_stage_id', $fromStageId)
            ->where('to_stage_id', $toStageId)
            ->where('active', true)
            ->where(fn ($query) => $query->whereNull('business_id')->orWhere('business_id', $ticket->business_id))
            ->orderByDesc('business_id')
            ->first();

        abort_unless($transition, 422, 'This Ticket status transition is not allowed. Complete the current stage first.');
        abort_if($transition->requires_comment && blank($reason), 422, 'A transition comment is required.');
    }

    private function recordStageHistory(Ticket $ticket, int $fromStageId, int $toStageId, ?string $reason): void
    {
        if ($fromStageId === $toStageId) {
            return;
        }
        CrmStatusHistory::create([
            'business_id' => $ticket->business_id,
            'statusable_type' => Ticket::class,
            'statusable_id' => $ticket->id,
            'from_status' => TicketStage::find($fromStageId)?->name,
            'to_status' => TicketStage::find($toStageId)?->name ?? (string) $toStageId,
            'reason' => $reason,
            'changed_by' => auth()->id(),
            'changed_at' => now(),
        ]);
    }


    public function destroy($id)
    {
        // Find the lead by ID
        $ticket = Ticket::findOrFail($id);

        // Check access permission
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        
        if (!in_array($ticket->contact_owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to delete this ticket.');
        }

        $ticket->ticketLanguages()->delete();


        $ticket->delete();

        return redirect()->route('tickets')->with('success', 'Ticket and associated Contact deleted successfully!');
    }

    public function callCreate()
    {

        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $tickets  = Ticket::all();
        $priorities  = TicketPriority::all();
        $users = User::all();

        return view('ticket.calls', compact('languages', 'contacts', 'stages', 'companies', 'products', 'accounts', 'tickets', 'priorities', 'users'));
    }


    public function callStore(Request $request)
    {
        $this->authorizeLegacyTicketRequest($request);

        $request->validate([
            'ticket_id' => 'required|exists:tickets,id',
            'topic' => 'required|string|max:255',
            'contact_name' => 'required|string|max:255',
            'direction' => 'required|in:incoming,outgoing',
            'call_status' => 'required|in:planned,completed,cancelled',
            'outcome' => 'required|in:interested,follow_up_required,not_interested',
            'start_time' => 'required|date',
            'contact_owner' => 'required|exists:users,id',
        ]);

        $call = Call::create([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'contact_name' => $request->contact_name,
            'direction' => $request->direction,
            'call_status' => $request->call_status,
            'outcome' => $request->outcome,
            'start_time' => $request->start_time,
            'duration' => $request->duration,
            'priority' => $request->priority_id,
            'call_owner' => $request->contact_owner,
            'description' => $request->description,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($call, 'call', $request);


        return redirect()->back()->with('success', 'Call created successfully!');
    }


    public function callEdit(Request $request)
    {
        $callId = $request->query('id');

        $call = Call::findOrFail($callId);
        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $ticketSources  = TicketSource::all();
        $priorities  = TicketPriority::all();
        $users = User::all();
        $tickets  = Ticket::all();


        return view('ticket.call-edit', compact('tickets', 'languages', 'contacts', 'stages', 'companies', 'users', 'accounts', 'ticketSources', 'priorities', 'products', 'call'));
    }



    public function callUpdate(Request $request, $id)
    {

        $call = Call::findOrFail($id);
        $this->authorizeLegacyRecord($call);
        $this->authorizeLegacyTicketRequest($request);

        // Update the ticket data
        $call->update([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'contact_name' => $request->contact_name,
            'direction' => $request->direction,
            'call_status' => $request->call_status,
            'outcome' => $request->outcome,
            'start_time' => $request->start_time,
            'duration' => $request->duration,
            'priority' => $request->priority_id,
            'call_owner' => $request->contact_owner,
            'description' => $request->description,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($call, 'call', $request);


        return redirect()->route('activities-list')->with('success', 'Call updated successfully!');
    }


    public function callDestroy($id)
    {

        $call = Call::findOrFail($id);
        $this->authorizeLegacyRecord($call);
        Activity::where('legacy_type', 'call')->where('legacy_id', $call->id)->delete();
        $call->delete();

        return redirect()->route('activities-list')->with('success', 'Call and associated Contact deleted successfully!');
    }

    public function taskCreate()
    {

        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $tickets  = Ticket::all();
        $priorities  = TicketPriority::all();
        $users = User::all();

        return view('ticket.task', compact('languages', 'contacts', 'stages', 'companies', 'products', 'accounts', 'tickets', 'priorities', 'users'));
    }


    public function taskStore(Request $request)
    {
        $this->authorizeLegacyTicketRequest($request);

        $request->validate([
            'ticket_id' => 'required|exists:tickets,id',
            'topic' => 'required|string|max:255',
            'contact_name' => 'required|string|max:255',
            'due_date_time' => 'required|date',
            'contact_owner' => 'required|exists:users,id',
            'priority_id' => 'required',
            'status' => 'required|in:pending,in_progress,completed,cancelled',
        ]);

        $call = Task::create([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'contact_name' => $request->contact_name,
            'due_date_time' => $request->due_date_time,
            'task_owner' => $request->contact_owner,
            'priority' => $request->priority_id,
            'status' => $request->status,
            'description' => $request->description,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($call, 'task', $request);


        return redirect()->back()->with('success', 'Task created successfully!');
    }


    public function taskEdit(Request $request)
    {
        $taskId = $request->query('id');

        $task = Task::findOrFail($taskId);
        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $ticketSources  = TicketSource::all();
        $priorities  = TicketPriority::all();
        $users = User::all();
        $tickets  = Ticket::all();


        return view('ticket.task-edit', compact('tickets', 'languages', 'contacts', 'stages', 'companies', 'users', 'accounts', 'ticketSources', 'priorities', 'products', 'task'));
    }



    public function taskUpdate(Request $request, $id)
    {

        $task = Task::findOrFail($id);
        $this->authorizeLegacyRecord($task);
        $this->authorizeLegacyTicketRequest($request);

        // Update the ticket data
        $task->update([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'contact_name' => $request->contact_name,
            'due_date_time' => $request->due_date_time,
            'task_owner' => $request->contact_owner,
            'priority' => $request->priority_id,
            'status' => $request->status,
            'description' => $request->description,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($task, 'task', $request);


        return redirect()->route('activities-list')->with('success', 'Task updated successfully!');
    }

    public function taskDestroy($id)
    {

        $task = Task::findOrFail($id);
        $this->authorizeLegacyRecord($task);
        Activity::where('legacy_type', 'task')->where('legacy_id', $task->id)->delete();
        $task->delete();

        return redirect()->route('activities-list')->with('success', 'Task and associated Contact deleted successfully!');
    }

    public function eventCreate()
    {

        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $tickets  = Ticket::all();
        $priorities  = TicketPriority::all();
        $users = User::all();

        return view('ticket.event', compact('languages', 'contacts', 'stages', 'companies', 'products', 'accounts', 'tickets', 'priorities', 'users'));
    }


    public function eventStore(Request $request)
    {
        $this->authorizeLegacyTicketRequest($request);

        $event = Event::create([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'category' => $request->category,
            'contact_name' => $request->contact_name,
            'due_date_time' => $request->due_date_time,
            'task_owner' => $request->contact_owner,
            'priority' => $request->priority_id,
            'status' => $request->status,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($event, 'event', $request);


        return redirect()->back()->with('success', 'Event created successfully!');
    }


    public function eventEdit(Request $request)
    {
        $eventId = $request->query('id');

        $event = Event::findOrFail($eventId);
        $languages = Language::all();
        $contacts = Contact::all();
        $stages = LeadStage::active()->orderBy('id')->get();
        $companies = Company::all();
        $products = Product::all();
        $accounts = Account::all();
        $ticketSources  = TicketSource::all();
        $priorities  = TicketPriority::all();
        $users = User::all();
        $tickets  = Ticket::all();


        return view('ticket.event-edit', compact('tickets', 'languages', 'contacts', 'stages', 'companies', 'users', 'accounts', 'ticketSources', 'priorities', 'products', 'event'));
    }



    public function eventUpdate(Request $request, $id)
    {

        $event = Event::findOrFail($id);
        $this->authorizeLegacyRecord($event);
        $this->authorizeLegacyTicketRequest($request);

        // Update the ticket data
        $event->update([
            'ticket_id' => $request->ticket_id,
            'topic' => $request->topic,
            'category' => $request->category,
            'contact_name' => $request->contact_name,
            'due_date_time' => $request->due_date_time,
            'task_owner' => $request->contact_owner,
            'priority' => $request->priority_id,
            'status' => $request->status,
            'reminder_status' => $request->reminder_status,
        ]);
        $this->syncLegacyActivity($event, 'event', $request);


        return redirect()->route('activities-list')->with('success', 'Event updated successfully!');
    }

    public function eventDestroy($id)
    {

        $event = Event::findOrFail($id);
        $this->authorizeLegacyRecord($event);
        Activity::where('legacy_type', 'event')->where('legacy_id', $event->id)->delete();
        $event->delete();

        return redirect()->route('activities-list')->with('success', 'Event and associated Contact deleted successfully!');
    }

    private function syncLegacyActivity(Model $legacy, string $kind, Request $request): Activity
    {
        $ticket = Ticket::findOrFail($legacy->ticket_id);
        abort_unless($ticket->business_id === auth()->user()->business_id, 403);
        $typeIds = ['call' => 1, 'task' => 3, 'event' => 4];
        $dateTime = $kind === 'call' ? $legacy->start_time : $legacy->due_date_time;
        try { $at = $dateTime ? Carbon::parse($dateTime) : now(); } catch (\Throwable) { $at = now(); }
        $owner = (int) ($request->contact_owner ?: auth()->id());
        $status = strtolower((string) ($legacy->call_status ?? $legacy->status ?? 'planned'));
        $lifecycle = match (true) {
            str_contains($status, 'complete') => 'completed',
            str_contains($status, 'cancel') => 'cancelled',
            str_contains($status, 'progress') => 'in_progress',
            default => 'planned',
        };
        $activity = Activity::withTrashed()->updateOrCreate(
            ['legacy_type' => $kind, 'legacy_id' => $legacy->id],
            [
                'deleted_at' => null, 'business_id' => $ticket->business_id, 'ticket_id' => $ticket->id,
                'contact_id' => $ticket->primary_contact_id, 'account_id' => $ticket->account_id,
                'activity_type_id' => $typeIds[$kind], 'title' => $legacy->topic ?: ucfirst($kind),
                'description' => $legacy->description ?? null, 'direction' => $legacy->direction ?? null,
                'start_date' => $at->toDateString(), 'start_time' => $at->format('H:i:s'),
                'due_date' => $kind === 'call' ? null : $at->toDateString(),
                'duration' => $legacy->duration ?? null, 'owner_id' => $owner,
                'outcome' => $legacy->outcome ?? null,
                'lifecycle_status' => $lifecycle, 'status' => 'active',
                'category' => $legacy->category ?? $kind,
            ]
        );
        if ($activity->trashed()) $activity->restore();
        $assignees = collect($request->input('assignee_ids', []))->push($owner)->filter()->unique();
        $activity->assignments()->delete();
        foreach ($assignees as $userId) {
            if (User::where('business_id', $ticket->business_id)->whereKey($userId)->exists()) {
                $activity->assignments()->create([
                    'business_id' => $ticket->business_id, 'user_id' => $userId, 'assigned_by' => auth()->id(),
                ]);
            }
        }
        if ($kind === 'call' && ($legacy->outcome ?? null) === 'follow_up_required') {
            \App\Models\FollowUp::firstOrCreate(
                ['business_id' => $ticket->business_id, 'previous_activity_id' => $activity->id],
                ['title' => 'Follow-up: '.$activity->title, 'related_type' => Activity::class,
                    'related_id' => $activity->id, 'owner_id' => $owner, 'follow_up_at' => now()->addDay(),
                    'priority' => 'high', 'status' => 'pending', 'remind_at' => now()->addDay()->subHour()]
            );
        }
        return $activity;
    }

    private function authorizeLegacyTicketRequest(Request $request): Ticket
    {
        $businessId = auth()->user()->business_id;
        $request->validate([
            'ticket_id' => ['required', 'integer', Rule::exists('tickets', 'id')->where(fn ($query) =>
                $query->where('business_id', $businessId)->whereNull('deleted_at')->whereNull('moved_at'))],
            'contact_owner' => ['nullable', 'integer', Rule::exists('users', 'id')->where('business_id', $businessId)],
        ]);
        $ticket = Ticket::findOrFail($request->integer('ticket_id'));
        abort_unless(in_array((int) $ticket->contact_owner_id, array_map('intval', $this->getAccessibleUserIds(auth()->id())), true), 403);
        return $ticket;
    }

    private function authorizeLegacyRecord(Model $record): void
    {
        $ticket = Ticket::findOrFail($record->ticket_id);
        abort_unless((int) $ticket->business_id === (int) auth()->user()->business_id, 403);
        abort_unless(in_array((int) $ticket->contact_owner_id, array_map('intval', $this->getAccessibleUserIds(auth()->id())), true), 403);
    }
}
