<?php

namespace App\Http\Controllers;

use App\Models\Activity;
use App\Models\Account;
use App\Models\Project;
use App\Models\CrmCase;
use App\Models\Business;
use App\Models\Company;
use App\Models\Contact;
use App\Models\ContactEmail;
use App\Models\Lead;
use App\Models\Country;
use App\Models\Deal;
use App\Models\MeetingThirdPartyIntegration;
use App\Models\Priority;
use App\Models\Repeat;
use App\Models\Status;
use App\Models\User;
use App\Models\UserAccess;
use App\Models\AccessType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\Rule;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use App\Models\FollowUp;
use App\Models\Todo;
use App\Models\EmailTemplate;
use App\Models\IntegrationSetting;
use App\Models\Message;
use App\Models\Note;

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

        $this->middleware('permission:list_activities')->only(['index']);
        $this->middleware('permission:list_activities')->only(['show']);
        $this->middleware('permission:create_activities')->only(['create', 'store']);
        $this->middleware('permission:update_activities')->only(['edit', 'update']);
        $this->middleware('permission:delete_activities')->only(['destroy']);
    }

    public function index(Request $request)
    {
        return $this->workspace($request);
    }

    private function legacyIndex(Request $request)
    {
        $user = auth()->user();
        $this->useDefaultDateRange($request);

        // Get deals based on user access permissions
        $request->validate([
            'q'=>['nullable','string','max:100'],'lifecycle_status'=>['nullable',Rule::in(['planned','completed','cancelled'])],
            'activity_type_id'=>['nullable','integer'],'date_from'=>['nullable','date'],
            'date_to'=>['nullable','date','after_or_equal:date_from'],
        ]);
        $search=trim((string)$request->input('q'));
        $activityPaginator = $this->getAccessibleActivities($user->id)
            ->when($request->filled('lifecycle_status'),fn($q)=>$q->where('lifecycle_status',$request->lifecycle_status))
            ->when($request->filled('activity_type_id'),fn($q)=>$q->where('activity_type_id',$request->integer('activity_type_id')))
            ->when($request->filled('date_from'),fn($q)=>$q->whereDate('created_at','>=',$request->date_from))
            ->when($request->filled('date_to'),fn($q)=>$q->whereDate('created_at','<=',$request->date_to))
            ->when($search!=='',fn($query)=>$query->where(fn($filter)=>$filter
                ->where('title','like',"%{$search}%")
                ->orWhere('description','like',"%{$search}%")
                ->orWhere('location','like',"%{$search}%")))
            ->latest()->paginate(25)->withQueryString();
        $activities = collect($activityPaginator->items());
        // $activities = Activity::where('owner_id', auth()->id())
        //  ->where('business_id', auth()->user()->business_id)
        //  ->get();

        $activityTypes = [
            1 => 'Call',
            2 => 'Appointment',
            3 => 'Task',
            4 => 'Event',
            5 => 'Deadline',
            6 => 'Other Activity',
            7 => 'Letter',
            8 => 'Fax',
            9 => 'Email',
            10 => 'Campaign',
        ];
        // dd($activities);
        return view('applications.activities', compact('activities', 'activityPaginator', 'activityTypes'));
    }

    private function workspace(Request $request)
    {
        $request->validate([
            'q' => ['nullable', 'string', 'max:100'],
            'type' => ['nullable', Rule::in(['call', 'meeting', 'task', 'email', 'message', 'note', 'follow_up', 'todo', 'event'])],
            'scope' => ['nullable', Rule::in(['mine', 'team', 'assigned'])],
            'owner_id' => ['nullable', 'integer'], 'related_record' => ['nullable', 'integer'],
            'status' => ['nullable', 'string', 'max:100'], 'date_from' => ['nullable', 'date'],
            'date_to' => ['nullable', 'date', 'after_or_equal:date_from'],
        ]);
        $businessId = $request->user()->business_id;
        $accessibleUserIds = $this->getAccessibleUserIds($request->user()->id);
        $teamUserIds = filled($request->user()->team_name)
            ? User::where('business_id', $businessId)->where('team_name', $request->user()->team_name)->pluck('id')->all()
            : [];
        $visibleOwnerIds = array_values(array_unique(array_merge($accessibleUserIds, $teamUserIds, [$request->user()->id])));
        $applyAccess = function ($query, bool $usesVisibility = false) use ($request, $accessibleUserIds, $teamUserIds, $visibleOwnerIds) {
            if ((int) $request->user()->is_admin !== 1) {
                $query->where(function ($access) use ($request, $accessibleUserIds, $teamUserIds, $visibleOwnerIds, $usesVisibility) {
                    $access->where('owner_id', $request->user()->id)
                        ->orWhereHas('assignments', fn ($assignments) => $assignments->where('user_id', $request->user()->id));

                    if (! $usesVisibility) {
                        $access->orWhereIn('owner_id', $visibleOwnerIds);
                        return;
                    }

                    $access->orWhere('visibility', 'public')
                        ->orWhere(fn ($shared) => $shared->whereIn('owner_id', $accessibleUserIds)->where('visibility', '!=', 'private'));
                    if ($teamUserIds !== []) {
                        $access->orWhere(fn ($team) => $team->where('visibility', 'team')->whereIn('owner_id', $teamUserIds));
                    }
                });
            }

            return match ($request->input('scope')) {
                'mine' => $query->where('owner_id', $request->user()->id),
                'team' => $query->whereIn('owner_id', $teamUserIds),
                'assigned' => $query->whereHas('assignments', fn ($assignments) => $assignments->where('user_id', $request->user()->id)),
                default => $query,
            };
        };
        $relatedId = $request->integer('related_record') ?: null;
        $type = $request->input('type');
        $entries = collect();
        $add = function (string $type, string $title, $date, ?string $status, ?int $ownerId, string $related, string $editUrl, string $source, int $filesCount = 0, ?string $filesUrl = null, array $assignedNames = []) use (&$entries) {
            $entries->push((object) compact('type', 'title', 'date', 'status', 'ownerId', 'related', 'editUrl', 'source', 'filesCount', 'filesUrl', 'assignedNames'));
        };

        $applyAccess(Activity::where('business_id', $businessId), true)
            ->when($relatedId, fn ($query) => $query->where(fn ($related) => $related->where('account_id', $relatedId)->orWhere('contact_id', $relatedId)->orWhere('lead_id', $relatedId)->orWhere('deal_id', $relatedId)->orWhere('project_id', $relatedId)->orWhere('case_id', $relatedId)))
            ->when($request->filled('owner_id'), fn ($query) => $query->where('owner_id', $request->owner_id))
            ->when($request->filled('status'), fn ($query) => $query->where(fn ($status) => $status->where('lifecycle_status', $request->status)->orWhere('email_status', $request->status)->orWhere('status', $request->status)))
            ->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))
            ->with('assignments.user:id,name')->withCount('files')->get()->each(function (Activity $activity) use ($add, $type) {
                $activityType = $activity->legacy_type ?: match ((int) $activity->activity_type_id) { 1 => 'call', 2 => 'meeting', 3 => 'task', 4 => 'event', 9 => 'email', default => 'activity' };
                if ($type && $type !== $activityType) return;
                $legacyRoutes = ['call' => 'call.edit', 'task' => 'task.edit', 'event' => 'event.edit'];
                $editUrl = isset($legacyRoutes[$activity->legacy_type]) ? route($legacyRoutes[$activity->legacy_type], ['id' => $activity->legacy_id]) : route('activities.edit', ['id' => $activity->id]);
                $related = collect(['Account' => $activity->account_id, 'Contact' => $activity->contact_id, 'Lead' => $activity->lead_id, 'Deal' => $activity->deal_id, 'Project' => $activity->project_id, 'Case' => $activity->case_id])->filter()->map(fn ($id, $label) => "$label #$id")->join(' · ') ?: 'No related record';
                $add($activityType, $activity->title ?: $activity->subject ?: ucfirst($activityType), $activity->completed_at ?: $activity->sent_at ?: $activity->start_date ?: $activity->created_at, $activity->lifecycle_status ?: $activity->email_status ?: $activity->status, $activity->owner_id, $related, $editUrl, $activity->legacy_type ? 'Legacy '.$activity->legacy_type.' (synchronized)' : 'Activity', (int) $activity->files_count, route('crm-files.index', ['activities', $activity->id]), $activity->assignments->pluck('user.name')->filter()->values()->all());
            });

        $applyAccess(FollowUp::where('business_id', $businessId))
            ->when($relatedId, fn ($query) => $query->where('related_id', $relatedId))
            ->when($request->filled('owner_id'), fn ($query) => $query->where('owner_id', $request->owner_id))
            ->when($request->filled('status'), fn ($query) => $query->where('status', $request->status))
            ->when($request->filled('date_from'), fn ($query) => $query->whereDate('follow_up_at', '>=', $request->date_from))
            ->when($request->filled('date_to'), fn ($query) => $query->whereDate('follow_up_at', '<=', $request->date_to))
            ->with('assignments.user:id,name')->withCount('files')->get()->each(fn ($followUp) => (! $type || $type === 'follow_up') && $add('follow_up', $followUp->title, $followUp->follow_up_at ?: $followUp->created_at, $followUp->status, $followUp->owner_id, ($followUp->related_type ? class_basename($followUp->related_type).' #'.$followUp->related_id : 'No related record'), route('workflow.index', 'follow-ups'), 'Follow-up', (int) $followUp->files_count, route('crm-files.index', ['follow-ups', $followUp->id]), $followUp->assignments->pluck('user.name')->filter()->values()->all()));
        $applyAccess(Todo::where('business_id', $businessId))
            ->when($relatedId, fn ($query) => $query->where('related_id', $relatedId))
            ->when($request->filled('owner_id'), fn ($query) => $query->where('owner_id', $request->owner_id))
            ->when($request->filled('status'), fn ($query) => $query->where('status', $request->status))
            ->when($request->filled('date_from'), fn ($query) => $query->whereDate('due_at', '>=', $request->date_from))
            ->when($request->filled('date_to'), fn ($query) => $query->whereDate('due_at', '<=', $request->date_to))
            ->with('assignments.user:id,name')->withCount('files')->get()->each(fn ($todo) => (! $type || $type === 'todo') && $add('todo', $todo->title, $todo->due_at ?: $todo->created_at, $todo->status, $todo->owner_id, ($todo->related_type ? class_basename($todo->related_type).' #'.$todo->related_id : 'No related record'), route('workflow.index', 'todos'), 'To-do', (int) $todo->files_count, route('crm-files.index', ['todos', $todo->id]), $todo->assignments->pluck('user.name')->filter()->values()->all()));

        $applyAccess(Message::where('business_id', $businessId))
            ->when($relatedId, fn ($query) => $query->where('related_id', $relatedId))
            ->when($request->filled('owner_id'), fn ($query) => $query->where('owner_id', $request->owner_id))
            ->when($request->filled('status'), fn ($query) => $query->where('status', $request->status))
            ->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))
            ->with('assignments.user:id,name')->withCount('files')->get()->each(fn ($message) => (! $type || $type === 'message') && $add('message', $message->subject ?: 'Message', $message->sent_at ?: $message->created_at, $message->status, $message->owner_id, ($message->related_type ? class_basename($message->related_type).' #'.$message->related_id : 'No related record'), route('workflow.index', 'messages'), 'Message', (int) $message->files_count, route('crm-files.index', ['messages', $message->id]), $message->assignments->pluck('user.name')->filter()->values()->all()));

        $applyAccess(Note::where('business_id', $businessId), true)
            ->when($relatedId, fn ($query) => $query->where(fn ($related) => $related->where('account_id', $relatedId)->orWhere('contact_id', $relatedId)->orWhere('lead_id', $relatedId)->orWhere('deal_id', $relatedId)->orWhere('project_id', $relatedId)->orWhere('case_id', $relatedId)))
            ->when($request->filled('owner_id'), fn ($query) => $query->where('owner_id', $request->owner_id))
            ->when($request->filled('status'), fn ($query) => $query->where('visibility', $request->status))
            ->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))
            ->with('assignments.user:id,name')->withCount('files')->get()->each(function ($note) use ($add, $type) {
                if ($type && $type !== 'note') return;
                $related = collect(['Account' => $note->account_id, 'Contact' => $note->contact_id, 'Lead' => $note->lead_id, 'Deal' => $note->deal_id, 'Project' => $note->project_id, 'Case' => $note->case_id])->filter()->map(fn ($id, $label) => "$label #$id")->join(' · ') ?: 'No related record';
                $add('note', $note->title ?: 'Note', $note->created_at, $note->visibility, $note->owner_id, $related, route('workflow.index', 'notes'), 'Note', (int) $note->files_count, route('crm-files.index', ['notes', $note->id]), $note->assignments->pluck('user.name')->filter()->values()->all());
            });

        if ($request->filled('q')) {
            $search = mb_strtolower(trim((string) $request->q));
            $entries = $entries->filter(function ($entry) use ($search) {
                return str_contains(mb_strtolower(implode(' ', [
                    $entry->title,
                    $entry->type,
                    $entry->related,
                    $entry->source,
                    $entry->status,
                ])), $search);
            });
        }

        $entries = $entries->sortByDesc('date')->values();
        $listedOwnerIds = $entries->pluck('ownerId')->filter()->map(fn ($id) => (int) $id)->all();
        $ownerOptionIds = array_values(array_unique(array_merge($visibleOwnerIds, $listedOwnerIds)));
        $users = User::where('business_id', $businessId)->whereIn('id', $ownerOptionIds)->orderBy('name')->get(['id', 'name']);
        $attachmentRequirements = \DB::table('activity_attachment_requirements')->where('business_id', $businessId)->orderBy('activity_type')->orderBy('outcome')->get();
        return view('applications.unified-activity-workspace', compact('entries', 'users', 'attachmentRequirements'));
    }

    private function getAccessibleActivities($userId)
    {
        $accessibleUserIds = $this->getAccessibleUserIds($userId);
        
        return Activity::whereIn('owner_id', $accessibleUserIds)
            ->where('business_id', auth()->user()->business_id)
            ;
    }

    private function getAccessibleUserIds($currentUserId)
    {
        $accessibleUserIds = collect([$currentUserId]); // Always include self
        $businessId = auth()->user()->business_id;

        // 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();
        }

        // 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)
                ->whereHas('user', fn ($query) => $query->where('business_id', $businessId))
                ->pluck('user_id');
            $privateUsers = UserAccess::where('access_type_id', AccessType::PRIVATE)
                ->whereHas('user', fn ($query) => $query->where('business_id', $businessId))
                ->pluck('user_id');
            $specificUsers = UserAccess::where('access_type_id', AccessType::SPECIFIC_USERS)
                ->whereHas('user', fn ($query) => $query->where('business_id', $businessId))
                ->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)
            ->whereHas('user', fn ($query) => $query->where('business_id', $businessId))
            ->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 create()
    {
        $businessId = auth()->user()->business_id;
        $activities = $this->getAccessibleActivities(auth()->id())->get();
        $priorities = Priority::where('status', 'active')
            ->where(fn ($query) => $query->where('business_id', $businessId)->orWhereNull('business_id'))
            ->orderBy('name')
            ->get();
        $countries = Country::all();
        $meetings = MeetingThirdPartyIntegration::all();
        $eventStatuses = Status::all();
        $companies = Company::all();
        $repeats = Repeat::all();
        $contacts = Contact::where('business_id', $businessId)->with(['contactPhones', 'contactEmails', 'contactSocialMedia.socialMediaType', 'assignedUser'])
            ->orderBy('first_name')->limit(250)->get();
        $leads = Lead::where('business_id', $businessId)->with(['contactPhones', 'contactEmails', 'contactSocialMedia.socialMediaType', 'assignedUser'])
            ->orderBy('first_name')->limit(250)->get();
        $deals = Deal::where('business_id', $businessId)->with(['contactPhones', 'contact.contactPhones', 'contact.contactEmails', 'assignedUser'])
            ->orderBy('name')->limit(250)->get();
        $accounts = Account::where('business_id',$businessId)->with(['contactPhones', 'contactEmails', 'primaryContact.contactPhones', 'primaryContact.contactEmails', 'assignedUser'])
            ->orderBy('account_name')->limit(250)->get();
        $projects=Project::where('business_id',$businessId)->with(['owner','account.primaryContact.contactPhones'])
            ->orderBy('name')->limit(250)->get();
        $cases=CrmCase::where('business_id',$businessId)->with(['contact.contactPhones','lead.contactPhones','deal.contact.contactPhones','account.primaryContact.contactPhones','assignee'])
            ->orderByDesc('id')->limit(250)->get();
        $users = $this->getAccessibleUsers();
        $emailTemplates = EmailTemplate::where('active', true)->orderBy('name')->get();
        $messageIntegrations = IntegrationSetting::where('business_id', $businessId)
            ->whereIn('provider', ['whatsapp', 'facebook'])->get()->keyBy('provider');



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


        $submissionToken = (string) Str::uuid();
        session()->put("activity_submission_tokens.$submissionToken", true);

        return view('applications.schedule-activity', compact('activities', 'activityTypes', 'priorities', 'countries', 'meetings', 'eventStatuses', 'companies', 'repeats', 'contacts', 'leads', 'deals', 'accounts','projects','cases','users', 'emailTemplates', 'messageIntegrations', 'submissionToken'));
    }

    public function getSchedules()
    {
        $schedules = $this->getAccessibleActivities(auth()->id())
            ->get()
            ->filter(fn (Activity $activity) => $activity->start_date || $activity->due_date)
            ->values();
        return response()->json(['data' => $schedules]);
    }


    public function store(Request $request)
    {
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        $business = Business::find(auth()->user()->business_id);
        $allowedSenders = collect([
            auth()->user()->email,
            $business?->common_email,
        ])->filter()->unique()->values()->all();

        if ((int) $request->activity_type_id === 9) {
            if (!$request->filled('from_email')) {
                $request->merge(['from_email' => auth()->user()->email]);
            }

            if (!$request->filled('email_to')) {
                $recipient = null;

                if ($request->contact_id) {
                    $recipient = ContactEmail::where('contact_id', $request->contact_id)->value('email');
                } elseif ($request->lead_id) {
                    $recipient = ContactEmail::where('lead_id', $request->lead_id)->value('email');
                } elseif ($request->deal_id) {
                    $deal = Deal::find($request->deal_id);
                    $recipient = $deal?->contact_id
                        ? ContactEmail::where('contact_id', $deal->contact_id)->value('email')
                        : null;
                    $recipient ??= ContactEmail::where('deal_id', $request->deal_id)->value('email');
                }

                if ($recipient) {
                    $request->merge(['email_to' => $recipient]);
                }
            }
        }

        if (in_array((int) $request->activity_type_id, [1, 2], true) && $request->lifecycle_status === 'completed' && ! $request->filled('completed_at')) {
            $request->merge(['completed_at' => now()->format('Y-m-d H:i:s')]);
        }
        
        $request->validate([
            'submission_token' => 'required|uuid',
            'return_to' => ['nullable', Rule::in(['myactivities'])],
            'popup_type' => ['nullable', Rule::in(['call', 'meeting', 'task', 'email'])],
            'owner' => 'required|in:' . implode(',', $accessibleUserIds),
            'activity_type_id' => 'required|integer|between:1,10',
            'title' => 'required|string|max:255',
            'start_date' => 'required|date',
            'start_time' => 'required|date_format:H:i',
            'end_date' => 'required|date|after_or_equal:start_date',
            'end_time' => 'required|date_format:H:i',
            'contact_id' => ['nullable', Rule::exists('contacts', 'id')->where('business_id', auth()->user()->business_id)],
            'lead_id' => ['nullable', Rule::exists('leads', 'id')->where('business_id', auth()->user()->business_id)],
            'deal_id' => ['nullable', Rule::exists('deals', 'id')->where('business_id', auth()->user()->business_id)],
            'ticket_id' => ['nullable', Rule::exists('tickets', 'id')->where('business_id', auth()->user()->business_id)],
            'account_id' => ['nullable', Rule::exists('accounts', 'id')->where('business_id', auth()->user()->business_id)],
            'project_id' => ['nullable', Rule::exists('projects', 'id')->where('business_id', auth()->user()->business_id)],
            'case_id' => ['nullable', Rule::exists('cases', 'id')->where('business_id', auth()->user()->business_id)],
            'priority' => [
                'nullable',
                Rule::exists('priorities', 'id')->where(
                    fn ($query) => $query->where('business_id', auth()->user()->business_id)->orWhereNull('business_id')
                ),
            ],
            'meeting_integration' => 'nullable|exists:meeting_third_party_integrations,id',
            'from_email' => [
                'nullable',
                'required_if:activity_type_id,9',
                'email',
                Rule::in($allowedSenders),
            ],
            'email_to' => 'nullable|required_if:activity_type_id,9|string',
            'subject' => 'nullable|required_if:activity_type_id,9|string|max:255',
            'email_body' => 'nullable|required_if:activity_type_id,9|string',
            'lifecycle_status' => ['nullable', Rule::in(['planned', 'open', 'in_progress', 'completed', 'cancelled'])],
            'outcome' => ['nullable', Rule::in(['interested', 'follow_up_required', 'not_interested'])],
            'completed_at' => 'nullable|date',
            'next_action_type' => ['nullable', Rule::in(['follow_up', 'todo', 'none'])],
            'next_action' => 'nullable|string|max:2000',
            'no_next_action_reason' => 'nullable|string|max:2000',
            'direction' => ['nullable', Rule::in(['inbound', 'outbound'])],
            'meeting_type' => ['nullable', Rule::in(['online', 'physical', 'phone'])],
            'meeting_location_type' => ['nullable', Rule::in(['office','online','customer_location'])],
            'meeting_link' => 'nullable|url|max:2048',
            'visibility' => ['nullable', Rule::in(['private', 'team', 'public'])],
            'email_status' => ['nullable', Rule::in(['draft', 'sent', 'opened', 'replied', 'failed'])],
            'sent_at' => 'nullable|date',
            'assignee_ids' => 'nullable|array',
            'assignee_ids.*' => ['integer', Rule::in($accessibleUserIds)],
            'attendee_ids' => 'nullable|array',
            'attendee_ids.*' => ['integer', Rule::in($accessibleUserIds)],
            'remind_at' => 'nullable|date',
            'scheduled_at' => 'nullable|date',
            'attachment' => 'nullable|file|max:10240',
        ]);
        $this->validateCommunicationRequirements($request);
        $this->validateAttachmentRequirement($request);

        abort_unless(session()->pull("activity_submission_tokens.{$request->submission_token}"), 419, 'This activity form was already submitted. Please open a new form.');

        if ($request->start_date === $request->end_date && $request->end_time < $request->start_time) {
            return back()->withErrors(['end_time' => 'The end time must be after the start time.'])->withInput();
        }

        $toRecipients = $this->emailList($request->email_to);
        $ccRecipients = $this->emailList($request->cc_recipients);
        $bccRecipients = $this->emailList($request->bcc_recipients);

        $activity = new Activity([
            'business_id' => auth()->user()->business_id,
            'contact_id' => $request->contact_id,
            'lead_id' => $request->lead_id,
            'deal_id' => $request->deal_id,
            'ticket_id' => $request->ticket_id,
            'account_id' => $request->account_id,'project_id' => $request->project_id,'case_id' => $request->case_id,
            'activity_type_id' => $request->activity_type_id,
            'title' => $request->title,
            'description' => $request->description,
            'service' => $request->service,
            'call_from' => $request->callFrom,
            'phone_number' => $request->phoneNumber,

            'location' => $request->location,
            'meeting_integration_id' => $request->meeting_integration,
            // 'attachment' => $request->attachment,
            'start_date' => $request->start_date,
            'start_time' => $request->start_time,
            'end_date' => $request->end_date,
            'end_time' => $request->end_time,
            'regarding' => $request->regarding,
            'fax' => $request->fax,
            'address' => $request->address,
            'direction' => $request->direction,
            'from_email' => $request->from_email,
            'email_to' => $request->email_to,
            'subject' => $request->subject,
            'email_body' => $request->email_body,
            'email_attachment' => null,
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'meeting_details' => $request->meeting_details,
            'hosting' => $request->hosting,
            'duration' => $request->duration,
            'due_date' => $request->due_date,
            'promotion_code' => $request->promotion_code,
            'response_code' => $request->response_code,
            'received_on' => $request->received_on,
            'close_by' => $request->close_by,
            'status' => 'active',
            'owner_id' => $request->owner,
            'all_day_eventstatus' => $request->allDayEventStatus,
            'customer_id' => $request->customer,
            'priority_type_id' => $request->priority,
            'company_id' => $request->company,
            'channel_id' => $request->channel,
            'related_to_id' => $request->related_to,
            'repeat_type_id' => $request->repeat_type,
            'participant_id' => $request->participants,
            'related_campaign_id' => $request->related_campaign,
            'lifecycle_status' => $request->lifecycle_status ?: 'planned',
            'outcome' => $request->outcome,
            'meeting_type' => $request->meeting_type,
            'meeting_location_type' => $request->meeting_location_type,'meeting_link' => $request->meeting_link,
            'agenda' => $request->agenda,
            'next_action' => $request->next_action,
            'next_action_type' => $request->next_action_type,
            'no_next_action_reason' => $request->no_next_action_reason,
            'attendee_result' => $request->attendee_result,
            'completed_at' => $request->lifecycle_status === 'completed' ? $request->completed_at : null,
            'remind_at' => $request->remind_at,
            'visibility' => $request->visibility ?: 'team',
            'to_recipients' => $toRecipients,
            'cc_recipients' => $ccRecipients,
            'bcc_recipients' => $bccRecipients,
            'email_status' => (int) $request->activity_type_id === 9 ? ($request->email_status ?: 'draft') : null,
            'scheduled_at' => $request->scheduled_at,
            'sent_at' => $request->sent_at,
            'reminder_escalation_hours' => $request->integer('reminder_escalation_hours', 24),
            'category' => $request->category,
            'tracking_token' => (int) $request->activity_type_id === 9 ? (string) Str::uuid() : null,
            'reply_token' => (int) $request->activity_type_id === 9 ? (string) Str::uuid() : null,
            'calendar_uid' => (int) $request->activity_type_id === 2 ? (string) Str::uuid() : null,
            'calendar_sync_status' => (int) $request->activity_type_id === 2 ? 'pending' : null,

        ]);

        $activity->save();
        $this->syncPeople($activity, $request, $accessibleUserIds);
        $this->storeAttachment($activity, $request);
        $this->createOutcomeFollowUp($activity);
        $this->createCompletionNextAction($activity);
        if ((int) $activity->activity_type_id === 2) {
            $this->sendMeetingInvitations($activity);
            app(\App\Services\CalendarSyncService::class)->sync($activity);
        }

        $this->deliverEmailWhenDue($activity);

        $returnRoute = $request->return_to === 'myactivities' ? 'myactivities' : 'schedule-activity';

        return redirect()->route($returnRoute)->with(
            'success',
            (int) $activity->activity_type_id === 9
                ? 'Email sent and activity created successfully!'
                : 'Activity created successfully!'
        );
    }

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

        $scheduledActivity = Activity::where('business_id', auth()->user()->business_id)
            ->with('assignees')->findOrFail($activityId);

        // dd($scheduledActivity);
        $activities = Activity::all();
        $priorities = Priority::all();
        $countries = Country::all();
        $meetings = MeetingThirdPartyIntegration::all();
        $eventStatuses = Status::all();
        $companies = Company::all();
        $repeats = Repeat::all();
        $businessId = auth()->user()->business_id;
        $contacts = Contact::where('business_id', $businessId)->with(['contactPhones', 'assignedUser'])
            ->orderBy('first_name')->limit(250)->get();
        $leads = Lead::where('business_id', $businessId)->with(['contactPhones', 'assignedUser'])
            ->orderBy('first_name')->limit(250)->get();
        $deals = Deal::where('business_id', $businessId)->with(['contactPhones', 'contact.contactPhones', 'assignedUser'])
            ->orderBy('name')->limit(250)->get();
        $accounts = Account::where('business_id', $businessId)->with(['contactPhones', 'primaryContact.contactPhones', 'assignedUser'])
            ->orderBy('account_name')->limit(250)->get();
        $cases = CrmCase::where('business_id', $businessId)->with(['contact.contactPhones','lead.contactPhones','deal.contact.contactPhones','account.primaryContact.contactPhones','assignee'])
            ->orderByDesc('id')->limit(250)->get();
        $users = $this->getAccessibleUsers();
        $emailTemplates = EmailTemplate::where('active', true)->orderBy('name')->get();




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


        if ((int) $scheduledActivity->activity_type_id === 1) {
            return view('applications.activity-call-edit', compact('scheduledActivity', 'contacts', 'leads', 'deals', 'accounts', 'cases', 'users'));
        }

        return view('applications.activity-edit', compact('activities', 'activityTypes', 'priorities', 'countries', 'meetings', 'eventStatuses', 'companies', 'repeats', 'scheduledActivity', 'contacts', 'users', 'emailTemplates'));
    }



    public function update(Request $request, $id)
    {
        $activity = Activity::where('business_id', auth()->user()->business_id)->findOrFail($id);
        $previousLifecycleStatus = $activity->lifecycle_status;

        // Check access permission
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());

        if (in_array((int) $request->activity_type_id, [1, 2], true) && $request->lifecycle_status === 'completed' && ! $request->filled('completed_at')) {
            $request->merge(['completed_at' => now()->format('Y-m-d H:i:s')]);
        }
        
        if (!in_array($activity->owner_id, $accessibleUserIds)) {
            abort(403, 'You do not have permission to update this activity.');
        }

        // Validate that the new owner is accessible
        $request->validate([
            'owner' => 'required|in:' . implode(',', $accessibleUserIds),
            'activity_type_id' => 'required|integer|between:1,10',
            'title' => 'required|string|max:255',
            'start_date' => 'required|date',
            'start_time' => 'required|date_format:H:i',
            'end_date' => 'required|date|after_or_equal:start_date',
            'end_time' => 'required|date_format:H:i',
            'contact_id' => ['nullable', Rule::exists('contacts', 'id')->where('business_id', auth()->user()->business_id)],
            'lead_id' => ['nullable', Rule::exists('leads', 'id')->where('business_id', auth()->user()->business_id)],
            'deal_id' => ['nullable', Rule::exists('deals', 'id')->where('business_id', auth()->user()->business_id)],
            'account_id' => ['nullable', Rule::exists('accounts', 'id')->where('business_id', auth()->user()->business_id)],
            'case_id' => ['nullable', Rule::exists('cases', 'id')->where('business_id', auth()->user()->business_id)],
            'lifecycle_status' => ['nullable', Rule::in(['planned', 'open', 'in_progress', 'completed', 'cancelled'])],
            'outcome' => ['nullable', Rule::in(['interested', 'follow_up_required', 'not_interested'])],
            'completed_at' => 'nullable|date',
            'next_action_type' => ['nullable', Rule::in(['follow_up', 'todo', 'none'])],
            'next_action' => 'nullable|string|max:2000',
            'no_next_action_reason' => 'nullable|string|max:2000',
            'direction' => ['nullable', Rule::in(['inbound', 'outbound'])],
            'meeting_type' => ['nullable', Rule::in(['online', 'physical', 'phone'])],
            'visibility' => ['nullable', Rule::in(['private', 'team', 'public'])],
            'assignee_ids' => 'nullable|array',
            'assignee_ids.*' => ['integer', Rule::in($accessibleUserIds)],
            'attendee_ids' => 'nullable|array',
            'attendee_ids.*' => ['integer', Rule::in($accessibleUserIds)],
            'attachment' => 'nullable|file|max:10240',
        ]);
        $this->validateCommunicationRequirements($request);
        $this->validateAttachmentRequirement($request, $activity);

        if ($request->start_date === $request->end_date && $request->end_time < $request->start_time) {
            return back()->withErrors(['end_time' => 'The end time must be after the start time.'])->withInput();
        }

        // Update activity data
        $activity->update([
            'business_id' => auth()->user()->business_id,
            'contact_id' => $request->contact_id,
            'lead_id' => $request->lead_id,
            'deal_id' => $request->deal_id,
            'account_id' => $request->account_id,
            'case_id' => $request->case_id,
            'ticket_id' => $request->ticket_id,
            'activity_type_id' => $request->activity_type_id,
            'title' => $request->title,
            'description' => $request->description,
            'service' => $request->service,
            'call_from' => $request->callFrom,
            'phone_number' => $request->phoneNumber,
            'location' => $request->location,
            'meeting_integration_id' => $request->meeting_integration_id,
            'start_date' => $request->start_date,
            'start_time' => $request->start_time,
            'end_date' => $request->end_date,
            'end_time' => $request->end_time,
            'regarding' => $request->regarding,
            'fax' => $request->fax,
            'address' => $request->address,
            'direction' => $request->direction,
            'from_email' => $request->from_email,
            'email_to' => $request->email_to,
            'subject' => $request->subject,
            'email_body' => $request->email_body,
            'email_attachment' => $activity->email_attachment,
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'meeting_details' => $request->meeting_details,
            'hosting' => $request->hosting,
            'duration' => $request->duration,
            'due_date' => $request->due_date,
            'promotion_code' => $request->promotion_code,
            'response_code' => $request->response_code,
            'received_on' => $request->received_on,
            'close_by' => $request->close_by,
            'status' => $request->status,
            'owner_id' => $request->owner,
            'all_day_eventstatus' => $request->allDayEventStatus,
            'customer_id' => $request->customer,
            'priority_type_id' => $request->priority,
            'company_id' => $request->company,
            'channel_id' => $request->channel,
            'related_to_id' => $request->related_to,
            'repeat_type_id' => $request->repeat_type,
            'participant_id' => $request->participants,
            'related_campaign_id' => $request->related_campaign,
            'lifecycle_status' => $request->lifecycle_status ?: $activity->lifecycle_status,
            'outcome' => $request->outcome,
            'meeting_type' => $request->meeting_type,
            'meeting_location_type' => $request->meeting_location_type,'meeting_link' => $request->meeting_link,
            'agenda' => $request->agenda,
            'next_action' => $request->next_action,
            'next_action_type' => $request->next_action_type,
            'no_next_action_reason' => $request->no_next_action_reason,
            'attendee_result' => $request->attendee_result,
            'completed_at' => $request->lifecycle_status === 'completed' ? ($request->completed_at ?: $activity->completed_at) : null,
            'remind_at' => $request->remind_at,
            'visibility' => $request->visibility ?: 'team',
            'to_recipients' => $this->emailList($request->email_to),
            'cc_recipients' => $this->emailList($request->cc_recipients),
            'bcc_recipients' => $this->emailList($request->bcc_recipients),
            'email_status' => $request->email_status,
            'scheduled_at' => $request->scheduled_at,
            'sent_at' => $request->sent_at,
            'reminder_escalation_hours' => $request->integer('reminder_escalation_hours', 24),
            'category' => $request->category,
        ]);

        $this->syncPeople($activity, $request, $accessibleUserIds);
        $this->storeAttachment($activity, $request);
        $this->createOutcomeFollowUp($activity);
        $this->createCompletionNextAction($activity);
        if ((int) $activity->activity_type_id === 2) {
            app(\App\Services\CalendarSyncService::class)->sync($activity);
        }
        $this->deliverEmailWhenDue($activity);
        if ($previousLifecycleStatus !== $activity->lifecycle_status) {
            app(\App\Services\ActivityWatcherService::class)->notify(
                $activity,
                $activity->lifecycle_status === 'completed' ? 'completion' : 'status',
                ($activity->title ?: 'Activity').' status changed to '.str_replace('_', ' ', $activity->lifecycle_status).'.'
            );
        }

        return redirect()->route('schedule-activity')->with('success', 'Activity updated successfully!');
    }


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

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

        if ((int) $activity->activity_type_id === 2) {
            app(\App\Services\CalendarSyncService::class)->delete($activity);
        }
        $activity->delete();

        return redirect()->route('schedule-activity')->with('success', 'Activity and associated Contact deleted successfully!');
    }


    public function getActivityDetails($id)
    {
        $activity = Activity::find($id);

        if (!$activity) {
            return response()->json(['error' => 'Activity not found'], 404);
        }

        // Manually select all columns except created_at and updated_at
        $details = collect($activity)
            ->except(['created_at', 'updated_at']) // Explicitly remove created_at and updated_at
            ->filter(function ($value) {
                return !is_null($value); // Keep only non-null values
            });

        return response()->json($details);
    }

    private function emailList(?string $value): array
    {
        return collect(preg_split('/[,;]+/', (string) $value))
            ->map(fn ($email) => trim($email))->filter(fn ($email) => filter_var($email, FILTER_VALIDATE_EMAIL))
            ->unique()->values()->all();
    }

    private function validateCommunicationRequirements(Request $request): void
    {
        $isEmail = (int) $request->activity_type_id === 9;
        $isCall = (int) $request->activity_type_id === 1;
        $isMeeting = (int) $request->activity_type_id === 2;
        $isCompleted = $request->lifecycle_status === 'completed';

        if ($isEmail && $this->emailList($request->email_to) === []) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'email_to' => 'Enter at least one valid recipient email address.',
            ]);
        }
        if ($isEmail && (! $request->filled('email_status') || ($request->email_status !== 'draft' && ! $request->filled('scheduled_at') && ! $request->filled('sent_at')))) {
            throw \Illuminate\Validation\ValidationException::withMessages(['email_status' => 'Emails require a status and either a scheduled send date/time or sent date/time.']);
        }
        if ($isCall && ! $request->filled('phoneNumber')) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'phoneNumber' => 'A phone number is required for a call activity.',
            ]);
        }
        $hasNonContactRelation = $request->filled('lead_id') || $request->filled('deal_id') || $request->filled('ticket_id') || $request->filled('account_id') || $request->filled('project_id') || $request->filled('case_id');
        if (($isCall || $isEmail) && ! $request->filled('contact_id') && ! $hasNonContactRelation) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'related_to' => 'Calls and emails must be linked to a contact or another CRM record.',
            ]);
        }
        if ($isMeeting && ! $request->filled('contact_id') && ! $hasNonContactRelation) {
            throw \Illuminate\Validation\ValidationException::withMessages(['related_to' => 'Meetings must be linked to a contact, lead, deal, ticket, account, project, or case.']);
        }
        if ($isCall && (! $request->filled('direction') || ! $request->filled('duration'))) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'direction' => 'Calls require an inbound/outbound type and duration.',
            ]);
        }
        if ($isMeeting && (! $request->filled('meeting_type') || ! $request->filled('meeting_location_type') || ! $request->filled('agenda') || ! $request->filled('duration') || empty($request->input('attendee_ids', [])))) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'meeting_type' => 'Meetings require type, location type, agenda, duration, and at least one attendee.',
            ]);
        }
        if ($isCompleted && ($isCall || $isEmail) && (! $request->filled('outcome') || ! $request->filled('description'))) {
            throw \Illuminate\Validation\ValidationException::withMessages([
                'outcome' => 'Completed activities require an outcome and interaction notes.',
            ]);
        }
        if ($isCompleted && ($isCall || $isMeeting || $isEmail) && ! $request->filled('completed_at')) {
            throw \Illuminate\Validation\ValidationException::withMessages(['completed_at' => 'Completed calls, meetings, and emails require a completion timestamp.']);
        }
        if ($isCompleted && $isEmail && ! $request->filled('next_action_type')) {
            throw \Illuminate\Validation\ValidationException::withMessages(['next_action_type' => 'Choose a Follow-up, To-do, or No next action decision.']);
        }
        if ($isCompleted && $isEmail && in_array($request->next_action_type, ['follow_up', 'todo'], true) && ! $request->filled('next_action')) {
            throw \Illuminate\Validation\ValidationException::withMessages(['next_action' => 'Enter the Follow-up or To-do title.']);
        }
        if ($isCompleted && $isEmail && $request->next_action_type === 'none' && ! $request->filled('no_next_action_reason')) {
            throw \Illuminate\Validation\ValidationException::withMessages(['no_next_action_reason' => 'Explain why no next action is needed.']);
        }
    }

    private function validateAttachmentRequirement(Request $request, ?Activity $activity = null): void
    {
        $type = match ((int) $request->activity_type_id) { 1 => 'call', 2 => 'meeting', 9 => 'email', default => null };
        if (! $type) return;
        $requirement = \DB::table('activity_attachment_requirements')->where('business_id', $request->user()->business_id)
            ->where('activity_type', $type)->where('required', true)
            ->where(fn ($query) => $query->where('outcome', $request->outcome)->orWhereNull('outcome'))->orderByRaw('outcome is null')->first();
        if ($requirement && ! $request->hasFile('attachment') && ! $activity?->files()->exists()) {
            throw \Illuminate\Validation\ValidationException::withMessages(['attachment' => 'An attachment is required for this activity type and outcome.']);
        }
    }

    public function saveAttachmentRequirement(Request $request)
    {
        abort_unless($request->user()->is_admin, 403);
        $data = $request->validate(['activity_type' => ['required', Rule::in(['call', 'meeting', 'email'])], 'outcome' => 'nullable|string|max:100', 'required' => 'nullable|boolean']);
        \DB::table('activity_attachment_requirements')->updateOrInsert(['business_id' => $request->user()->business_id, 'activity_type' => $data['activity_type'], 'outcome' => $data['outcome'] ?? null], ['required' => $request->boolean('required'), 'updated_at' => now(), 'created_at' => now()]);
        return back()->with('success', 'Activity attachment requirement saved.');
    }

    private function deliverEmailWhenDue(Activity $activity): void
    {
        if ((int) $activity->activity_type_id !== 9 || $activity->sent_at || ($activity->scheduled_at && $activity->scheduled_at->isFuture())) return;
        if ($activity->email_status === 'draft' && ! $activity->scheduled_at) return;

        $trackedBody = nl2br(e($activity->email_body)).
            '<img src="'.route('email-tracking.open', $activity->tracking_token).'" width="1" height="1" alt="">';
        try {
            Mail::html($trackedBody, function ($message) use ($activity) {
                $message->to($activity->to_recipients ?: [$activity->email_to])
                    ->from($activity->from_email, auth()->user()->name)->subject($activity->subject);
                if ($activity->cc_recipients) $message->cc($activity->cc_recipients);
                if ($activity->bcc_recipients) $message->bcc($activity->bcc_recipients);
            });
            $activity->update(['email_status' => 'sent', 'sent_at' => now()]);
        } catch (\Throwable $exception) {
            $activity->update(['email_status' => 'failed']);
            report($exception);
        }
    }

    private function syncPeople(Activity $activity, Request $request, array $accessibleUserIds): void
    {
        $assignees = collect($request->input('assignee_ids', [$request->owner]))
            ->push($request->owner)->filter()->map(fn ($id) => (int) $id)
            ->intersect($accessibleUserIds)->unique();
        $activity->assignments()->delete();
        foreach ($assignees as $userId) {
            $activity->assignments()->create([
                'business_id' => auth()->user()->business_id,
                'user_id' => $userId,
                'assigned_by' => auth()->id(),
            ]);
        }
        $attendees = collect($request->input('attendee_ids', []))->map(fn ($id) => (int) $id)
            ->intersect($accessibleUserIds)->unique();
        $activity->attendees()->sync($attendees);
    }

    private function storeAttachment(Activity $activity, Request $request): void
    {
        if (! $request->hasFile('attachment')) return;
        $file = $request->file('attachment');
        $path = $file->store('crm-files/'.$activity->business_id, 'public');
        $activity->files()->create([
            'business_id' => $activity->business_id,
            'name' => pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME),
            'category' => 'activity',
            'path' => $path,
            'original_name' => $file->getClientOriginalName(),
            'mime_type' => $file->getMimeType(),
            'size' => $file->getSize(),
            'uploaded_by' => auth()->id(),
        ]);
    }

    private function createOutcomeFollowUp(Activity $activity): void
    {
        if ($activity->outcome !== 'follow_up_required' || $activity->next_action_type === 'follow_up') return;
        FollowUp::firstOrCreate(
            ['business_id' => $activity->business_id, 'previous_activity_id' => $activity->id],
            [
                'title' => 'Follow-up: '.$activity->title, 'related_type' => Activity::class,
                'related_id' => $activity->id, 'owner_id' => $activity->owner_id,
                'follow_up_at' => now()->addDay(), 'priority' => 'high', 'status' => 'pending',
                'remind_at' => now()->addDay()->subHour(), 'notes' => 'Automatically created from call outcome.',
            ]
        );
    }

    private function createCompletionNextAction(Activity $activity): void
    {
        if ($activity->lifecycle_status !== 'completed' || ! in_array($activity->next_action_type, ['follow_up', 'todo'], true) || ! $activity->next_action) return;
        $model = $activity->next_action_type === 'follow_up' ? FollowUp::class : Todo::class;
        $attributes = ['business_id' => $activity->business_id, 'owner_id' => $activity->owner_id, 'title' => $activity->next_action, 'related_type' => Activity::class, 'related_id' => $activity->id, 'status' => 'pending'];
        $values = $activity->next_action_type === 'follow_up'
            ? ['follow_up_at' => now()->addDay(), 'remind_at' => now()->addDay()->subHour(), 'priority' => 'medium', 'notes' => 'Created from completed activity #'.$activity->id]
            : ['due_at' => now()->addDay(), 'remind_at' => now()->addDay()->subHour(), 'priority' => 'medium', 'description' => 'Created from completed activity #'.$activity->id];
        $next = $activity->next_action_record_id ? $model::whereKey($activity->next_action_record_id)->where('business_id', $activity->business_id)->first() : null;
        $next ? $next->update(array_merge($attributes, $values)) : $next = $model::create(array_merge($attributes, $values));
        $activity->update(['next_action_record_id' => $next->id]);
    }

    private function sendMeetingInvitations(Activity $activity): void
    {
        $activity->load('attendees');
        $start = \Carbon\Carbon::parse($activity->start_date.' '.($activity->start_time ?: '09:00'));
        $end = \Carbon\Carbon::parse(($activity->end_date ?: $activity->start_date).' '.($activity->end_time ?: $start->copy()->addHour()->format('H:i')));
        $ics = implode("\r\n", ['BEGIN:VCALENDAR','VERSION:2.0','PRODID:-//YalCRM//Meeting//EN','METHOD:REQUEST',
            'BEGIN:VEVENT','UID:'.$activity->calendar_uid,'DTSTAMP:'.now()->utc()->format('Ymd\\THis\\Z'),
            'DTSTART:'.$start->utc()->format('Ymd\\THis\\Z'),'DTEND:'.$end->utc()->format('Ymd\\THis\\Z'),
            'SUMMARY:'.str_replace(["\r","\n"], ' ', $activity->title),
            'DESCRIPTION:'.str_replace(["\r","\n"], ' ', (string) $activity->agenda),
            'LOCATION:'.str_replace(["\r","\n"], ' ', (string) $activity->location),'END:VEVENT','END:VCALENDAR']);
        try {
            foreach ($activity->attendees as $attendee) {
                Mail::raw("You are invited to {$activity->title}. Respond in CRM: ".route('meeting-invitations.show', $activity), function ($message) use ($attendee, $activity, $ics) {
                    $message->to($attendee->email)->subject('Meeting invitation: '.$activity->title)
                        ->attachData($ics, 'meeting.ics', ['mime' => 'text/calendar']);
                });
            }
            $activity->update(['calendar_sync_status' => 'invited']);
        } catch (\Throwable $exception) {
            $activity->update(['calendar_sync_status' => 'failed', 'calendar_sync_error' => $exception->getMessage()]);
            report($exception);
        }
    }






    // public function show()
    // {
    //     $activities = Activity::all();

    //     $activityTypes = [
    //         1 => 'Call',
    //         2 => 'Appointment',
    //         3 => 'Task',
    //         4 => 'Event',
    //         5 => 'Deadline',
    //         6 => 'Other Activity',
    //         7 => 'Letter',
    //         8 => 'Fax',
    //         9 => 'Email',
    //         10 => 'Campaign',
    //     ];
    //     dd($activities);
    //     return view('applications.schedule-activity', compact('activities', 'activityTypes'));
    // }
}
