<?php

namespace App\Http\Controllers;

use App\Models\Activity;
use App\Models\Campaign;
use App\Models\Company;
use App\Models\Contact;
use App\Models\ContactEmail;
use App\Models\ContactLanguage;
use App\Models\ContactPhoneNum;
use App\Models\ContactSocialMedia;
use App\Models\Country;
use App\Models\Deal;
use App\Models\Language;
use App\Models\Lead;
use App\Models\MeetingThirdPartyIntegration;
use App\Models\Note;
use App\Models\Priority;
use App\Models\Repeat;
use App\Models\SocialMediaType;
use App\Models\Status;
use App\Models\User;
use App\Models\UserAccess;
use App\Models\AccessType;
use App\Models\Account;
use App\Models\CrmCase;
use App\Models\Project;
use App\Models\Survey;
use App\Models\TradeDocument;
use App\Models\CrmFile;
use App\Models\Product;
use App\Models\CampaignTarget;
use App\Services\ReportExportService;
use App\Support\CrmAccess;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

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

        $this->middleware('permission:list_contacts')->only(['index']);
        $this->middleware('permission:list_contacts')->only(['show']);
        $this->middleware('permission:create_contacts')->only(['create', 'store']);
        $this->middleware('permission:update_contacts')->only(['edit', 'update', 'assignCampaign', 'noteStore', 'updateStage']);
        $this->middleware('permission:assign_leads')->only(['assignLead']);
        $this->middleware('permission:assign_deals')->only(['assignDeal']);
        $this->middleware('permission:delete_contacts')->only(['destroy']);
        $this->middleware('permission:import_contacts')->only(['import', 'importTemplate']);
        $this->middleware('permission:export_contacts')->only(['export']);
    }

    public function index(Request $request)
    {
        $user = auth()->user();
        $businessId = $user->business_id;
        $this->useDefaultDateRange($request);

        $request->validate([
            'q'=>['nullable','string','max:100'],'status'=>['nullable',Rule::in(['active','inactive'])],
            'type'=>['nullable',Rule::in(['Customer','Vendor','Partner','Agent'])],
            'priority'=>['nullable',Rule::in(['High','Medium','Low'])],
            'date_from'=>['nullable','date'],'date_to'=>['nullable','date','after_or_equal:date_from'],
        ]);
        $search = trim((string) $request->input('q'));
        $contactPaginator = $this->getAccessibleContacts($user->id)
            ->when($request->filled('status'),fn($q)=>$q->where('status',$request->status))
            ->when($request->filled('type'),fn($q)=>$q->where('type',$request->type))
            ->when($request->filled('priority'),fn($q)=>$q->where('priority',$request->priority))
            ->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('first_name', 'like', "%{$search}%")
                ->orWhere('last_name', 'like', "%{$search}%")
                ->orWhere('job_title', 'like', "%{$search}%")
                ->orWhere('type', 'like', "%{$search}%")))
            ->paginate(25)->withQueryString();
        $contacts = collect($contactPaginator->items());
        $activeContacts = $contacts->where('status', 'active')->values();
        $inactiveContacts = $contacts->where('status', '!=', 'active')->values();

        $now=now();$today=$now->copy()->startOfDay();$tomorrow=$today->copy()->addDay();$yesterday=$today->copy()->subDay();
        $monthStart=$now->copy()->startOfMonth();$lastMonthStart=$monthStart->copy()->subMonth();
        $yearStart=$now->copy()->startOfYear();$lastYearStart=$yearStart->copy()->subYear();
        $stats=Contact::where('contact_owner_id',$user->id)->where('business_id',$businessId)
            ->selectRaw('COUNT(*) total_contacts,
                SUM(created_at>=? AND created_at<?) today_contacts,
                SUM(created_at>=? AND created_at<?) yesterday_contacts,
                SUM(created_at>=? AND created_at<?) month_contacts,
                SUM(created_at>=? AND created_at<?) last_month_contacts,
                SUM(created_at>=? AND created_at<?) year_contacts,
                SUM(created_at>=? AND created_at<?) last_year_contacts',[
                    $today,$tomorrow,$yesterday,$today,$monthStart,$tomorrow,$lastMonthStart,$monthStart,
                    $yearStart,$tomorrow,$lastYearStart,$yearStart,
                ])->first();
        $todayContacts=(int)$stats->today_contacts;$yesterdayContacts=(int)$stats->yesterday_contacts;

        $todayChange = $yesterdayContacts > 0
            ? (($todayContacts - $yesterdayContacts) / $yesterdayContacts) * 100
            : ($todayContacts > 0 ? 100 : 0);

        $monthContacts=(int)$stats->month_contacts;$lastMonthContacts=(int)$stats->last_month_contacts;

        $monthChange = $lastMonthContacts > 0
            ? (($monthContacts - $lastMonthContacts) / $lastMonthContacts) * 100
            : ($monthContacts > 0 ? 100 : 0);

        $yearContacts=(int)$stats->year_contacts;$lastYearContacts=(int)$stats->last_year_contacts;

        $yearChange = $lastYearContacts > 0
            ? (($yearContacts - $lastYearContacts) / $lastYearContacts) * 100
            : ($yearContacts > 0 ? 100 : 0);

        // -------------------------------
        // Total contacts (no change %)
        // -------------------------------
        $totalContacts=(int)$stats->total_contacts;

        $activities = collect();
        $priorities = Priority::all();
        $countries = Country::all();
        $meetings = MeetingThirdPartyIntegration::all();
        $eventStatuses = Status::all();
        $companies = Company::all();
        $repeats = Repeat::all();
        $users = $this->getAccessibleUsers();

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

        return view('contacts.contacts', compact(
            'activities',
            'activityTypes',
            'priorities',
            'countries',
            'meetings',
            'eventStatuses',
            'companies',
            'repeats',
            'contacts',
            'activeContacts',
            'inactiveContacts',
            'users',
            'todayContacts',
            'todayChange',
            'monthContacts',
            'monthChange',
            'yearContacts',
            'yearChange',
            'totalContacts',
            'contactPaginator'
        ));
    }

    public function export(Request $request, ReportExportService $export, string $format)
    {
        abort_unless(in_array($format, ['pdf', 'csv', 'xml', 'txt', 'xlsx'], true), 404);
        $request->validate([
            'q' => ['nullable', 'string', 'max:100'],
            'status' => ['nullable', Rule::in(['active', 'inactive'])],
            'type' => ['nullable', Rule::in(['Customer', 'Vendor', 'Partner', 'Agent'])],
            'priority' => ['nullable', Rule::in(['High', 'Medium', 'Low'])],
            'date_from' => ['nullable', 'date'], 'date_to' => ['nullable', 'date', 'after_or_equal:date_from'],
        ]);
        $search = trim((string) $request->input('q'));
        $query = $this->getAccessibleContacts(auth()->id())
            ->when($request->filled('status'), fn ($q) => $q->where('status', $request->status))
            ->when($request->filled('type'), fn ($q) => $q->where('type', $request->type))
            ->when($request->filled('priority'), fn ($q) => $q->where('priority', $request->priority))
            ->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 ($q) => $q->where(fn ($filter) => $filter
                ->where('first_name', 'like', "%{$search}%")
                ->orWhere('last_name', 'like', "%{$search}%")
                ->orWhere('job_title', 'like', "%{$search}%")
                ->orWhere('type', 'like', "%{$search}%")));

        $headers = ['Name', 'Job Title', 'Phone', 'Email', 'Company', 'Owner', 'Type', 'Priority', 'Status', 'Created'];
        $rows = $query->limit(10000)->get()->map(fn ($contact) => [
            trim($contact->first_name.' '.$contact->last_name),
            $contact->job_title,
            $contact->contactPhones->first()?->phone,
            $contact->contactEmails->first()?->email,
            $contact->company?->name,
            $contact->assignedUser?->name,
            $contact->type,
            $contact->priority,
            $contact->status,
            $contact->created_at?->format('Y-m-d H:i:s'),
        ])->all();
        $filename = 'contacts-'.now()->format('Ymd-His');

        if ($format === 'pdf') {
            return response($export->pdf('Contacts Export', $headers, $rows), 200, [
                'Content-Type' => 'application/pdf',
                'Content-Disposition' => "attachment; filename=\"{$filename}.pdf\"",
            ]);
        }
        if ($format === 'xlsx') {
            return response($export->xlsx('Contacts', $headers, $rows), 200, [
                'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'Content-Disposition' => "attachment; filename=\"{$filename}.xlsx\"",
            ]);
        }
        if ($format === 'xml') {
            $xml = '<?xml version="1.0" encoding="UTF-8"?><contacts>';
            foreach ($rows as $row) {
                $xml .= '<contact>';
                foreach (array_combine($headers, $row) as $key => $value) {
                    $tag = strtolower(str_replace(' ', '_', $key));
                    $xml .= "<{$tag}>".htmlspecialchars((string) $value, ENT_XML1)."</{$tag}>";
                }
                $xml .= '</contact>';
            }
            return response($xml.'</contacts>', 200, [
                'Content-Type' => 'application/xml',
                'Content-Disposition' => "attachment; filename=\"{$filename}.xml\"",
            ]);
        }
        if ($format === 'txt') {
            $lines = [implode("\t", $headers), ...array_map(fn ($row) => implode("\t", array_map(fn ($value) => str_replace(["\r", "\n", "\t"], ' ', (string) $value), $row)), $rows)];
            return response(implode(PHP_EOL, $lines), 200, [
                'Content-Type' => 'text/plain',
                'Content-Disposition' => "attachment; filename=\"{$filename}.txt\"",
            ]);
        }

        $handle = fopen('php://temp', 'r+');
        fputcsv($handle, $headers);
        foreach ($rows as $row) fputcsv($handle, $row);
        rewind($handle);
        $csv = stream_get_contents($handle);
        fclose($handle);
        return response($csv, 200, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => "attachment; filename=\"{$filename}.csv\"",
        ]);
    }

    public function importTemplate()
    {
        $csv = "first_name,last_name,email,phone,job_title,type,priority,status\n".
            "Alex,Morgan,alex@example.com,+1000000000,Sales Manager,Customer,High,active\n";

        return response($csv, 200, [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="contact-import-template.csv"',
        ]);
    }

    public function import(Request $request)
    {
        $request->validate([
            'contacts_file' => ['required', 'file', 'mimes:csv,txt', 'max:5120'],
        ]);

        $handle = fopen($request->file('contacts_file')->getRealPath(), 'r');
        abort_unless($handle !== false, 422, 'Unable to read the Contact import file.');
        $header = fgetcsv($handle);
        if (!$header) {
            fclose($handle);
            return back()->withErrors(['contacts_file' => 'The Contact import file is empty.']);
        }
        $header = array_map(fn ($column) => strtolower(trim(str_replace([' ', '-'], '_', ltrim((string) $column, "\xEF\xBB\xBF")))), $header);
        if (!in_array('first_name', $header, true) && !in_array('last_name', $header, true)) {
            fclose($handle);
            return back()->withErrors(['contacts_file' => 'The CSV must contain first_name or last_name.']);
        }

        $imported = 0;
        $skipped = 0;
        DB::transaction(function () use ($handle, $header, &$imported, &$skipped) {
            $rowNumber = 1;
            while (($values = fgetcsv($handle)) !== false && $rowNumber < 5001) {
                $rowNumber++;
                if (count(array_filter($values, fn ($value) => trim((string) $value) !== '')) === 0) continue;
                $values = array_pad($values, count($header), null);
                $row = array_combine($header, array_slice($values, 0, count($header)));
                $row = array_map(fn ($value) => trim((string) $value), $row);
                $row = array_merge([
                    'first_name' => '', 'last_name' => '', 'email' => '', 'phone' => '',
                    'job_title' => '', 'type' => '', 'priority' => '', 'status' => '',
                ], $row);
                $row['type'] = ucfirst(strtolower($row['type'] ?: 'Customer'));
                $row['priority'] = ucfirst(strtolower($row['priority'] ?: 'Medium'));
                $row['status'] = strtolower($row['status'] ?: 'active');
                $validator = Validator::make($row, [
                    'first_name' => ['nullable', 'string', 'max:255', 'required_without:last_name'],
                    'last_name' => ['nullable', 'string', 'max:255', 'required_without:first_name'],
                    'email' => ['nullable', 'email', 'max:255'],
                    'phone' => ['nullable', 'string', 'max:50'],
                    'job_title' => ['nullable', 'string', 'max:255'],
                    'type' => [Rule::in(['Customer', 'Vendor', 'Partner', 'Agent'])],
                    'priority' => [Rule::in(['High', 'Medium', 'Low'])],
                    'status' => [Rule::in(['active', 'inactive'])],
                ]);
                if ($validator->fails()) {
                    $skipped++;
                    continue;
                }

                $contact = Contact::create([
                    'business_id' => auth()->user()->business_id,
                    'contact_owner_id' => auth()->id(),
                    'first_name' => $row['first_name'] ?: null,
                    'last_name' => $row['last_name'] ?: null,
                    'job_title' => $row['job_title'] ?: null,
                    'type' => $row['type'],
                    'priority' => $row['priority'],
                    'status' => $row['status'],
                ]);
                if ($row['email']) ContactEmail::create([
                    'contact_id' => $contact->id, 'email_type_id' => 1, 'email' => $row['email'],
                ]);
                if ($row['phone']) ContactPhoneNum::create([
                    'contact_id' => $contact->id, 'phone_type_id' => 1, 'phone' => $row['phone'],
                ]);
                $imported++;
            }
        });
        fclose($handle);

        return redirect()->route('contacts')->with('success', "{$imported} Contact(s) imported".($skipped ? "; {$skipped} row(s) skipped." : '.'));
    }

    private function getAccessibleContacts($userId)
    {
        $user=User::find($userId);
        $query=Contact::with([
            'contactPhones',
            'contactEmails',
            'contactSocialMedia',
            'contactLanguages.language',
            'assignedUser', 'company', 'country', 'stage',
            'accounts:id,primary_contact_id,account_name',
            'deals:id,contact_id,name,grand_total,estimate_amount,currency_id',
            'latestActivity' => fn ($query) => $query->select('activities.*'),
            'notes' => fn ($query) => $query
                ->visibleTo(auth()->user())
                ->select('id', 'contact_id', 'title', 'description', 'created_at', 'owner_id', 'visibility', 'business_id')
                ->latest(),
        ])
            ->withCount('activities')
            ->withExists(['leads', 'deals'])
            ->where('business_id', auth()->user()->business_id)
            ->orderBy('first_name')
            ->orderBy('last_name');
        if(!$user?->is_admin)$query->whereIn('contact_owner_id',$this->getAccessibleUserIds($userId));
        return $query;
            
    }

    private function getAccessibleUserIds($currentUserId)
    {
        return CrmAccess::accessibleUserIds(User::findOrFail($currentUserId));
    }

    private function getAccessibleUsers()
    {
        if(auth()->user()->is_admin)return User::where('business_id',auth()->user()->business_id)->orderBy('name')->limit(250)->get();
        $accessibleUserIds = $this->getAccessibleUserIds(auth()->id());
        return User::whereIn('id', $accessibleUserIds)->orderBy('name')->limit(250)->get();
    }

    public function updateStage(Request $request)
    {
        try {
            $businessId = $request->user()->business_id;
            $data = $request->validate([
                'contact_id' => ['required', Rule::exists('contacts', 'id')->where('business_id', $businessId)],
                'stage_id' => 'required|integer|exists:stages,id'
            ]);

            $contact = $this->authorizedContact((int) $data['contact_id']);
            $contact->stage_id = $data['stage_id'];
            $contact->save();

            if ($request->ajax()) {
                return response()->json([
                    'success' => true,
                    'message' => 'Contact stage updated successfully!'
                ]);
            }

            return redirect()->back()->with('success', 'Contact marked as complete successfully!');
            
        } catch (\Exception $e) {
            if ($request->ajax()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Failed to update contact stage.'
                ], 500);
            }

            return redirect()->back()->with('error', 'Failed to update contact stage.');
        }
}

    public function create(Request $request)
    {
        $languages = Language::all();
        $socialMedias = SocialMediaType::all();
        $companies = Company::all();
        $countries = Country::all();
        $users = User::where('business_id', auth()->user()->business_id)->orderBy('name')->get();
        $accounts = Account::where('business_id', auth()->user()->business_id)->orderBy('account_name')->get();


        $ticketId = $request->query('ticketId');
        return view('contacts.contacts-create', compact('languages', 'socialMedias', 'companies', 'countries', 'users', 'ticketId', 'accounts'));
    }

    public function store(Request $request)
    {
        // dd($request);
        $validatedData = $request->validate([
            'first_name' => 'required|string|max:255',
            'contact_owner' => ['required', Rule::exists('users', 'id')->where('business_id', auth()->user()->business_id)],
            'type' => 'required|in:customer,vendor,partner,agent',
            'priority' => 'required|in:high,medium,low',
            'account_ids' => 'nullable|array',
            'account_ids.*' => [Rule::exists('accounts', 'id')->where(fn ($query) => $query->where('business_id', auth()->user()->business_id))],
        ]);

        if (!empty($request->dateofbirth)) {
            try {
                $formattedDate = Carbon::parse($request->dateofbirth)->format('Y-m-d');
            } catch (\Exception $e) {
                $formattedDate = null;
            }
        } else {
            $formattedDate = null; // or handle as needed
        }

        $contact = Contact::create([
            'business_id' => auth()->user()->business_id,
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'job_title' => $request->job_title,
            'type' => $validatedData['type'],
            'priority' => $validatedData['priority'],
            'company_id' => $request->company_id,
            'contact_owner_id' => $request->contact_owner,
            'marketing_source_id' => $request->lead_source,
            'department' => $request->department,
            'gender' => $request->gender,
            'date_of_birth' => $formattedDate,
            'address_1' => $request->address1,
            'address_2' => $request->address2,
            'city' => $request->city,
            'province' => $request->province,
            'zip_code' => $request->zipcode,
            'country_id' => $request->country_id,
            'marketing_source_id' => $request->lead_source,
            'industry_id' => 1,
            'description' => $request->about,
            'stage_id' => $request->stage_id,
            'status' => $request->status,
        ]);
        
        if ($request->hasFile('avatar')) {
            $avatarPath = $request->file('avatar')->store('avatars', 'public');
            $contact->avatar_url = $avatarPath;
            $contact->save();
        }
        $contact->accounts()->sync(collect($request->input('account_ids', []))->filter()->unique()->values());

        if ($request->filled('source_ticket_id')) {
            $sourceTicket = \App\Models\Ticket::where('id', $request->source_ticket_id)
                ->where('business_id', auth()->user()->business_id)->firstOrFail();
            $sourceTicket->update(['primary_contact_id' => $contact->id]);
            $sourceTicket->recordMove('contact', $contact, $request->input('move_reason'));
        }

        foreach ($request->input('phones', []) as $index => $phone) {
            if (!empty($phone)) { // only create if phone is not null or empty
                ContactPhoneNum::create([
                    'contact_id'    => $contact->id,
                    'phone_type_id' => $request->input('phone_types')[$index],
                    'phone'         => $phone,
                ]);
            }
        }

        // Store emails
        foreach ($request->input('emails', []) as $index => $email) {
            if (!empty($email)) {
                ContactEmail::create([
                    'contact_id' => $contact->id,
                    'email_type_id' => $request->input('email_types')[$index],
                    'email' => $email,
                ]);
            }
        }

        $socialMediaTypes = SocialMediaType::pluck('id', 'name')->toArray();


        foreach ($request->input('social_media_values', []) as $index => $social_media_value) {

            $socialMediaType = $request->input('social_media_types')[$index] ?? null;

            $socialMediaTypeId = $socialMediaTypes[$socialMediaType] ?? null;

            if ($socialMediaTypeId && $social_media_value !== null && trim($social_media_value) !== '') {
                ContactSocialMedia::create([
                    'contact_id' => $contact->id,
                    'social_media_type_id' => $socialMediaTypeId,
                    'value' => $social_media_value,
                ]);
            }
        }


        if (!empty($request->languages)) {
            foreach ($request->languages as $languageId) {
                ContactLanguage::create([
                    'contact_id'  => $contact->id,
                    'language_id' => $languageId,
                ]);
            }
        }



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

    public function show(Request $request)
    {

        $contactId = $request->query('id');
        $contact = Contact::with([
            'contactPhones',
            'contactEmails',
            'contactSocialMedia',
            'contactLanguages',
            'accounts',
            'deals.dealProductLine',
            'activities',
            'projects',
            'products',
            'surveys',
            'cases',
            'files.uploader',
            'moveHistories.actor',
        ])->where('business_id', auth()->user()->business_id)->findOrFail($contactId);

        abort_unless(in_array($contact->contact_owner_id, $this->getAccessibleUserIds(auth()->id())), 403);

        $activities = $contact->activities()->latest('start_date')->latest('created_at')->get();
        $activityTimeline = $activities->map(fn ($activity) => [
            'id' => $activity->id,
            'type' => $activity->activity_type_id,
            'title' => $activity->title ?: $activity->subject ?: $activity->regarding ?: 'Activity',
            'status' => $activity->lifecycle_status ?: $activity->status,
            'outcome' => $activity->outcome,
            'occurred_at' => $activity->start_date
                ? Carbon::parse($activity->start_date.' '.($activity->start_time ?: '00:00:00'))
                : $activity->created_at,
        ]);
        $invitedMeetings = $activities->filter(fn ($activity) =>
            (int) $activity->activity_type_id === 2 || filled($activity->meeting_type) || filled($activity->meeting_integration_id)
        );
        $leads = Lead::where('business_id', auth()->user()->business_id)->where('primary_contact_id', $contactId)->get();
        $deals = $contact->deals;
        $campaigns = Campaign::where('business_id', auth()->user()->business_id)
            ->where(fn ($query) => $query->where('contact_id', $contactId)
                ->orWhereHas('targets', fn ($targets) => $targets
                    ->where('target_type', Contact::class)->where('target_id', $contactId)))
            ->get();
        $notes = Note::visibleTo(auth()->user())->where('contact_id', $contactId)->get();
        $totalDealValue = $deals->sum(fn ($deal) => (float) ($deal->grand_total ?: $deal->estimate_amount ?: 0));
        $projectIds = $contact->projects->pluck('id')->merge(
            Project::where('business_id', auth()->user()->business_id)
                ->whereIn('deal_id', $deals->pluck('id'))->pluck('id')
        )->unique();
        $projects = Project::whereIn('id', $projectIds)->get();
        $productIds = $contact->products->pluck('id')->merge(
            \App\Models\DealProductLine::whereIn('deal_id', $deals->pluck('id'))->pluck('product_id')
        )->filter()->unique();
        $products = Product::whereIn('id', $productIds)->get();
        $tradeDocuments = TradeDocument::where('business_id', auth()->user()->business_id)
            ->whereIn('deal_id', $deals->pluck('id'))->latest()->get();
        $cases = $contact->cases()->where('business_id', auth()->user()->business_id)->latest()->get();
        $surveys = $contact->surveys()->where('surveys.business_id', auth()->user()->business_id)
            ->orderByDesc('surveys.created_at')->get();
        $files = $contact->files()->latest()->get();
        $moveHistories = $contact->moveHistories()->with('actor')->latest()->get();

        $businessId = auth()->user()->business_id;
        $allLeads = Lead::where('business_id', $businessId)
            ->whereNull('primary_contact_id')->whereNull('moved_at')->orderByDesc('created_at')->get();
        $allDeals = Deal::where('business_id', $businessId)
            ->whereNull('contact_id')->orderByDesc('created_at')->get();
        $allCampaigns = Campaign::where('business_id', $businessId)
            ->whereDoesntHave('targets', fn ($query) => $query
                ->where('target_type', Contact::class)->where('target_id', $contact->id))
            ->orderBy('campaign_name')->get();
        // dd($activities);
        return view('contacts.contacts-view', compact(
            'contact', 'activities', 'activityTimeline', 'invitedMeetings', 'leads', 'deals', 'campaigns',
            'allLeads', 'allDeals', 'allCampaigns', 'notes', 'totalDealValue', 'projects', 'products',
            'tradeDocuments', 'cases', 'surveys', 'files', 'moveHistories'
        ));
    }


    public function assignLead(Request $request)
    {
        $businessId = $request->user()->business_id;
        $data = $request->validate([
            'lead_id' => ['required', Rule::exists('leads', 'id')->where('business_id', $businessId)],
            'contact_id' => ['required', Rule::exists('contacts', 'id')->where('business_id', $businessId)],
            'priority_id' => 'required|exists:priorities,id',
            'stage_id' => 'required|exists:lead_stages,id',
        ]);

        $contact = $this->authorizedContact((int) $data['contact_id']);
        $lead = Lead::where('business_id', $businessId)->whereNull('moved_at')->findOrFail($data['lead_id']);
        $lead->update([
            'primary_contact_id' => $contact->id,
            'priority_id' => $data['priority_id'],
            'stage_id' => $data['stage_id'],
        ]);

        return redirect()->back()->with('success', 'Lead assigned successfully.');
    }

    public function assignDeal(Request $request)
    {
        $businessId = $request->user()->business_id;
        $data = $request->validate([
            'deal_id' => ['required', Rule::exists('deals', 'id')->where('business_id', $businessId)],
            'contact_id' => ['required', Rule::exists('contacts', 'id')->where('business_id', $businessId)],
            'priority_id' => 'required|exists:priorities,id',
            'stage_id' => 'required|exists:deal_stages,id',
        ]);

        $contact = $this->authorizedContact((int) $data['contact_id']);
        $deal = Deal::where('business_id', $businessId)->findOrFail($data['deal_id']);
        $deal->update([
            'contact_id' => $contact->id,
            'priority_id' => $data['priority_id'],
            'stage_id' => $data['stage_id'],
        ]);

        return redirect()->back()->with('success', 'Deal assigned successfully.');
    }

    public function assignCampaign(Request $request)
    {
        $businessId = $request->user()->business_id;
        $data = $request->validate([
            'campaign_id' => ['required', Rule::exists('campaigns', 'id')->where('business_id', $businessId)],
            'contact_id' => ['required', Rule::exists('contacts', 'id')->where('business_id', $businessId)],
        ]);

        $contact = $this->authorizedContact((int) $data['contact_id']);
        $campaign = Campaign::where('business_id', $businessId)->findOrFail($data['campaign_id']);
        CampaignTarget::firstOrCreate([
            'business_id' => $businessId,
            'campaign_id' => $campaign->id,
            'target_type' => Contact::class,
            'target_id' => $contact->id,
        ], ['delivery_status' => 'pending']);

        return redirect()->back()->with('success', 'Campaign assigned successfully.');
    }

    private function authorizedContact(int $id): Contact
    {
        $contact = Contact::where('business_id', auth()->user()->business_id)->findOrFail($id);
        abort_unless(in_array($contact->contact_owner_id, $this->getAccessibleUserIds(auth()->id())), 403);
        return $contact;
    }

    public function noteStore(Request $request)
    {
        $businessId = $request->user()->business_id;
        $validated = $request->validate([
            'noteTitle' => 'required|string|max:255',
            'noteDescription' => 'required|string',
            'visibility' => 'nullable|in:private,team,public',
            'contact_id' => ['nullable', Rule::exists('contacts', 'id')->where('business_id', $businessId)],
            'lead_id' => ['nullable', Rule::exists('leads', 'id')->where('business_id', $businessId)],
            'deal_id' => ['nullable', Rule::exists('deals', 'id')->where('business_id', $businessId)],
            'account_id' => ['nullable', Rule::exists('accounts', 'id')->where('business_id', $businessId)],
        ]);
        if (!empty($validated['contact_id'])) {
            $this->authorizedContact((int) $validated['contact_id']);
        }

        // Create a new note
        Note::create([
            'business_id' => auth()->user()->business_id,
            'title' => $validated['noteTitle'],
            'description' => $validated['noteDescription'],
            'owner_id' => auth()->id(),
            'contact_id' => $validated['contact_id'] ?? null,
            'lead_id' => $validated['lead_id'] ?? null,
            'deal_id' => $validated['deal_id'] ?? null,
            'account_id' => $validated['account_id'] ?? null,
            'visibility' => $validated['visibility'] ?? 'team',
        ]);

        return redirect()->back()->with('success', 'Note added successfully!');
    }

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

        $contact = $this->authorizedContact((int) $contactId);
        $contact->load(['contactPhones', 'contactEmails', 'contactSocialMedia', 'contactLanguages']);
        $languages = Language::all();
        $socialMedias = SocialMediaType::all();
        $companies = Company::all();
        $countries = Country::all();
        $users = User::where('business_id', auth()->user()->business_id)->orderBy('name')->get();
        $accounts = Account::where('business_id', auth()->user()->business_id)->orderBy('account_name')->get();


        $contact->load('accounts');
        return view('contacts.contacts-edit', compact('contact', 'languages', 'socialMedias', 'companies', 'countries', 'users', 'accounts'));
    }


    public function update(Request $request, $id)
    {
        $contact = $this->authorizedContact((int) $id);

        // Validate the incoming request
        $validatedData = $request->validate([
            'dateofbirth' => 'nullable|date',
            'type' => 'required|in:customer,vendor,partner,agent',
            'priority' => 'required|in:high,medium,low',
            'account_ids' => 'nullable|array',
            'account_ids.*' => [Rule::exists('accounts', 'id')->where(fn ($query) => $query->where('business_id', auth()->user()->business_id))],
            'contact_owner' => ['required', Rule::exists('users', 'id')->where('business_id', auth()->user()->business_id)],
        ]);

        // dd($request);

        // Format the date of birth
        if (!empty($request->input('dateofbirth'))) {
            try {
                $formattedDate = Carbon::parse($request->input('dateofbirth'))->format('Y-m-d');
            } catch (\Exception $e) {
                $formattedDate = null;
            }
        } else {
            $formattedDate = null;
        }

        // Update basic contact details
        $contact->first_name = $request->input('first_name');
        $contact->last_name = $request->input('last_name');
        $contact->job_title = $request->input('job_title');
        $contact->type = $validatedData['type'];
        $contact->priority = $validatedData['priority'];
        $contact->company_id = $request->input('company_id');
        $contact->contact_owner_id = $request->input('contact_owner');
        $contact->marketing_source_id = $request->input('lead_source');
        $contact->department = $request->input('department');
        $contact->gender = $request->input('gender');
        $contact->date_of_birth = $formattedDate;
        $contact->address_1 = $request->input('address1');
        $contact->address_2 = $request->input('address2');
        $contact->city = $request->input('city');
        $contact->province = $request->input('province');
        $contact->zip_code = $request->input('zipcode');
        $contact->country_id = $request->input('country_id');
        $contact->stage_id = $request->input('stage_id');
        $contact->status = $request->input('status');
        $contact->description = $request->input('about');
        $contact->business_id = auth()->user()->business_id;

        // Update the avatar if uploaded
        if ($request->hasFile('avatar')) {
            $avatarPath = $request->file('avatar')->store('avatars', 'public');
            $contact->avatar_url = $avatarPath;
        }

        // Save the contact changes
        $contact->save();
        $contact->accounts()->sync(collect($request->input('account_ids', []))->filter()->unique()->values());

        // Update phone numbers
        $contact->contactPhones()->delete(); // Clear old phone numbers
        if ($request->input('phones')) {
            foreach ($request->input('phones', []) as $index => $phone) {
                if (!empty($phone)) {
                    $contact->contactPhones()->create([
                        'phone' => $phone,
                        'phone_type_id' => $request->input('phone_types')[$index],
                    ]);
                }
            }
        }

        // Update email addresses
        $contact->contactEmails()->delete(); // Clear old email addresses
        if ($request->input('emails')) {
            foreach ($request->input('emails', []) as $index => $email) {
                if (!empty($email)) {
                    $contact->contactEmails()->create([
                        'email' => $email,
                        'email_type_id' => $request->input('email_types')[$index],
                    ]);
                }
            }
        }

        // Update social media links
        $contact->contactSocialMedia()->delete(); // Clear old social media links
        if ($request->input('social_media_values')) {
            $socialMediaTypes = SocialMediaType::pluck('id', 'name')->toArray();

            foreach ($request->input('social_media_values', []) as $index => $socialMediaValue) {
                $socialMediaType = $request->input('social_media_types')[$index] ?? null;
                $socialMediaTypeId = $socialMediaTypes[$socialMediaType] ?? null;

                if ($socialMediaTypeId && $socialMediaValue !== null && trim($socialMediaValue) !== '') {
                    $contact->contactSocialMedia()->create([
                        'social_media_type_id' => $socialMediaTypeId,
                        'value' => $socialMediaValue,
                    ]);
                }
            }
        }

        // Update languages
        $contact->contactLanguages()->delete(); // Clear old languages
        if ($request->input('languages')) {
            foreach ($request->input('languages') as $languageId) {
                $contact->contactLanguages()->create([
                    'language_id' => $languageId,
                ]);
            }
        }

        return redirect()->route('contacts')->with('success', 'Contact updated successfully.');
    }

    public function destroy($id)
    {
        $contact = $this->authorizedContact((int) $id);

        $contact->contactPhones()->delete();
        $contact->contactEmails()->delete();
        $contact->contactSocialMedia()->delete();
        $contact->contactLanguages()->delete();

        $contact->delete();

        return redirect()->route('contacts')->with('success', 'Contact deleted successfully!');
    }

    
}
