<?php

namespace App\Http\Controllers;

use App\Models\Contact;
use App\Models\ContactList;
use App\Models\Tag;
use App\Services\ContactFieldRegistry;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;

class ContactController extends Controller
{
    public function index(Request $request)
    {
        $query = Contact::with(['lists:id,title,color', 'tags:id,title,color'])
            ->when($request->search, fn($q, $s) => $q->where(function ($q) use ($s) {
                $q->where('email', 'like', "%{$s}%")
                  ->orWhere('first_name', 'like', "%{$s}%")
                  ->orWhere('last_name', 'like', "%{$s}%");
            }))
            ->when($request->list_id, fn($q, $id) => $q->whereHas('lists', fn($q) => $q->where('lists.id', $id)))
            ->when($request->tag_id,  fn($q, $id) => $q->whereHas('tags',  fn($q) => $q->where('tags.id',  $id)))
            ->when($request->status,  fn($q, $s)  => $q->where('status', $s))
            ->latest()
            ->orderByDesc('id');

        $contacts = $query->paginate(15)->withQueryString();

        return Inertia::render('Audience/Contacts', [
            'contacts'      => $contacts,
            'allLists'      => ContactList::orderBy('title')->get(['id', 'title', 'color']),
            'allTags'       => Tag::orderBy('title')->get(['id', 'title', 'color']),
            'filters'       => $request->only(['search', 'list_id', 'tag_id', 'status']),
            'fieldRegistry' => ContactFieldRegistry::FIELDS,
        ]);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'prefix'     => 'nullable|string|max:20',
            'first_name' => 'nullable|string|max:100',
            'last_name'  => 'nullable|string|max:100',
            'email'      => [
                'required',
                'email',
                Rule::unique('contacts', 'email')->where(function ($query) {
                    return $query->where('user_id', auth()->id());
                }),
            ],
            'phone'      => 'nullable|string|max:30',
            'status'     => 'nullable|string|max:50',
            'contact_type' => 'nullable|string|max:50',
            'date_of_birth' => 'nullable|date',
            'address_line_1' => 'nullable|string',
            'address_line_2' => 'nullable|string',
            'city'       => 'nullable|string|max:100',
            'state'      => 'nullable|string|max:100',
            'postal_code' => 'nullable|string|max:20',
            'country'    => 'nullable|string|max:100',
            'list_ids'   => 'nullable|array',
            'list_ids.*' => 'exists:lists,id',
            'tag_ids'    => 'nullable|array',
            'tag_ids.*'  => 'exists:tags,id',
        ]);

        $listIds = $validated['list_ids'] ?? [];
        $tagIds  = $validated['tag_ids']  ?? [];
        unset($validated['list_ids'], $validated['tag_ids']);

        $validated['status']       = $validated['status']       ?? 'subscribed';
        $validated['contact_type'] = $validated['contact_type'] ?? 'lead';

        $contact = Contact::create($validated);
        $contact->lists()->sync($listIds);
        $contact->tags()->sync($tagIds);
        $contact->logActivity('created', 'Contact created');

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

    public function show(Contact $contact)
    {
        $contact->load([
            'lists:id,title,color',
            'tags:id,title,color',
            'notes',
            'activities',
        ]);

        return Inertia::render('Audience/ContactDetail', [
            'contact'  => $contact->append(['full_name', 'initials']),
            'allLists' => ContactList::orderBy('title')->get(['id', 'title', 'color']),
            'allTags'  => Tag::orderBy('title')->get(['id', 'title', 'color']),
        ]);
    }

    public function update(Request $request, Contact $contact)
    {
        $validated = $request->validate([
            'prefix'         => 'nullable|string|max:20',
            'first_name'     => 'nullable|string|max:100',
            'last_name'      => 'nullable|string|max:100',
            'email'          => [
                'sometimes',
                'required',
                'email',
                Rule::unique('contacts', 'email')
                    ->ignore($contact->id)
                    ->where(function ($query) {
                        return $query->where('user_id', auth()->id());
                    }),
            ],
            'phone'          => 'nullable|string|max:30',
            'status'         => 'nullable|string|max:50',
            'contact_type'   => 'nullable|string|max:50',
            'date_of_birth'  => 'nullable|date',
            'address_line_1' => 'nullable|string',
            'address_line_2' => 'nullable|string',
            'city'           => 'nullable|string|max:100',
            'state'          => 'nullable|string|max:100',
            'postal_code'    => 'nullable|string|max:20',
            'country'        => 'nullable|string|max:100',
        ]);

        $oldStatus = $contact->status;
        $contact->update($validated);

        if (isset($validated['status']) && $validated['status'] !== $oldStatus) {
            $contact->logActivity('status_changed', "Status changed from {$oldStatus} to {$validated['status']} (manual update)");
        } else {
            $contact->logActivity('updated', 'Contact information updated');
        }

        return back()->with('success', 'Contact updated successfully.');
    }

    public function destroy(Contact $contact)
    {
        $contact->delete();
        return redirect()->route('contacts.index')->with('success', 'Contact deleted.');
    }

    public function attachList(Contact $contact, ContactList $list)
    {
        $contact->lists()->syncWithoutDetaching([$list->id]);
        $contact->logActivity('list_added', "Added to list: {$list->title}");
        return back()->with('success', "Added to \"{$list->title}\".");
    }

    public function detachList(Contact $contact, ContactList $list)
    {
        $contact->lists()->detach($list->id);
        $contact->logActivity('list_removed', "Removed from list: {$list->title}");
        return back()->with('success', "Removed from \"{$list->title}\".");
    }

    public function attachTag(Contact $contact, Tag $tag)
    {
        $contact->tags()->syncWithoutDetaching([$tag->id]);
        $contact->logActivity('tag_added', "Tag added: {$tag->title}");
        return back()->with('success', "Tag \"{$tag->title}\" added.");
    }

    public function detachTag(Contact $contact, Tag $tag)
    {
        $contact->tags()->detach($tag->id);
        $contact->logActivity('tag_removed', "Tag removed: {$tag->title}");
        return back()->with('success', "Tag \"{$tag->title}\" removed.");
    }

    public function bulkDestroy(Request $request)
    {
        $ids = $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'exists:contacts,id'
        ])['ids'];

        Contact::whereIn('id', $ids)->delete();

        return redirect()->route('contacts.index')->with('success', 'Selected contacts deleted.');
    }

    public function bulkAddTags(Request $request)
    {
        $data = $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'exists:contacts,id',
            'tag_ids' => 'required|array',
            'tag_ids.*' => 'exists:tags,id',
        ]);

        foreach ($data['ids'] as $contactId) {
            $contact = Contact::find($contactId);
            if ($contact) {
                $contact->tags()->syncWithoutDetaching($data['tag_ids']);
                $contact->logActivity('tag_added', 'Bulk tags added');
            }
        }

        return redirect()->route('contacts.index')->with('success', 'Tags added to selected contacts.');
    }

    public function bulkAddLists(Request $request)
    {
        $data = $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'exists:contacts,id',
            'list_ids' => 'required|array',
            'list_ids.*' => 'exists:lists,id',
        ]);

        foreach ($data['ids'] as $contactId) {
            $contact = Contact::find($contactId);
            if ($contact) {
                $contact->lists()->syncWithoutDetaching($data['list_ids']);
                $contact->logActivity('list_added', 'Bulk lists added');
            }
        }

        return redirect()->route('contacts.index')->with('success', 'Selected contacts enrolled in lists.');
    }

    public function bulkUpdateStatus(Request $request)
    {
        $data = $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'exists:contacts,id',
            'status' => 'required|string|in:subscribed,unsubscribed,bounced,spam_reported',
        ]);

        foreach ($data['ids'] as $contactId) {
            $contact = Contact::find($contactId);
            if ($contact) {
                $oldStatus = $contact->status;
                if ($oldStatus !== $data['status']) {
                    $contact->update(['status' => $data['status']]);
                    $contact->logActivity('status_changed', "Bulk status changed from {$oldStatus} to {$data['status']}");
                }
            }
        }

        return redirect()->route('contacts.index')->with('success', 'Status updated for selected contacts.');
    }
}
