<?php

namespace App\Http\Controllers;

use App\Models\ContactList;
use App\Models\Tag;
use App\Models\Webhook;
use App\Services\ContactFieldRegistry;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Inertia\Inertia;

class WebhookController extends Controller
{
    public function index()
    {
        $webhooks = Webhook::when(request('search'), fn ($q, $s) => $q->where('name', 'like', "%{$s}%"))
            ->with(['lists:id,title,color', 'tags:id,title,color'])
            ->withCount('logs')
            ->latest()
            ->paginate(10)
            ->withQueryString()
            ->through(fn ($w) => [
                'id'                   => $w->id,
                'name'                 => $w->name,
                'receive_url'          => $w->receiveUrl(),
                'has_secret'           => !empty($w->getRawOriginal('secret')),
                'default_status'       => $w->default_status,
                'duplicate_handling'   => $w->duplicate_handling,
                'success_redirect_url' => $w->success_redirect_url,
                'is_active'            => $w->is_active,
                'total_received'       => $w->total_received,
                'last_triggered_at'    => $w->last_triggered_at?->toISOString(),
                'created_at'           => $w->created_at->toISOString(),
                'lists'                => $w->lists,
                'tags'                 => $w->tags,
                'list_ids'             => $w->lists->pluck('id'),
                'tag_ids'              => $w->tags->pluck('id'),
                'logs_count'           => $w->logs_count,
            ]);

        return Inertia::render('Audience/Webhooks', [
            'webhooks'      => $webhooks,
            'fieldRegistry' => ContactFieldRegistry::FIELDS,
            'allLists'      => ContactList::orderBy('title')->get(['id', 'title', 'color']),
            'allTags'       => Tag::orderBy('title')->get(['id', 'title', 'color']),
        ]);
    }

    private function rules(): array
    {
        return [
            'name'                 => 'required|string|max:255',
            'list_ids'             => 'nullable|array',
            'list_ids.*'           => 'exists:lists,id',
            'tag_ids'              => 'nullable|array',
            'tag_ids.*'            => 'exists:tags,id',
            'default_status'       => 'required|in:subscribed,unsubscribed',
            'duplicate_handling'   => 'required|in:skip,update',
            'success_redirect_url' => 'nullable|url|max:500',
            'is_active'            => 'boolean',
            'use_secret'           => 'boolean',
        ];
    }

    public function store(Request $request)
    {
        $data = $request->validate($this->rules());

        $secret = !empty($data['use_secret']) ? Str::random(40) : null;

        $webhook = Webhook::create([
            'name'                 => $data['name'],
            'default_status'       => $data['default_status'],
            'duplicate_handling'   => $data['duplicate_handling'],
            'success_redirect_url' => $data['success_redirect_url'] ?? null,
            'is_active'            => $data['is_active'] ?? true,
            'secret'               => $secret,
            'user_id'              => auth()->id(),
        ]);

        $webhook->lists()->sync($data['list_ids'] ?? []);
        $webhook->tags()->sync($data['tag_ids'] ?? []);

        return redirect()->route('webhooks.index')
            ->with('success', 'Webhook created successfully.')
            ->with('plainSecret', $secret);
    }

    public function update(Request $request, Webhook $webhook)
    {
        $data = $request->validate($this->rules());

        $newSecret = null;

        if (!empty($data['use_secret'])) {
            // Only generate a new secret if this webhook didn't already have one
            if (empty($webhook->getRawOriginal('secret'))) {
                $newSecret = Str::random(40);
            }
        } else {
            $webhook->secret = null;
        }

        if ($newSecret) {
            $webhook->secret = $newSecret;
        }

        $webhook->fill([
            'name'                 => $data['name'],
            'default_status'       => $data['default_status'],
            'duplicate_handling'   => $data['duplicate_handling'],
            'success_redirect_url' => $data['success_redirect_url'] ?? null,
            'is_active'            => $data['is_active'] ?? true,
        ])->save();

        $webhook->lists()->sync($data['list_ids'] ?? []);
        $webhook->tags()->sync($data['tag_ids'] ?? []);

        if ($request->wantsJson()) {
            return response()->json([
                'success' => true,
                'webhook' => $webhook->load(['lists:id,title,color', 'tags:id,title,color'])
            ]);
        }

        return redirect()->route('webhooks.index')
            ->with('success', 'Webhook updated successfully.')
            ->with('plainSecret', $newSecret);
    }

    public function destroy(Webhook $webhook)
    {
        $webhook->delete();

        return redirect()->route('webhooks.index')->with('success', 'Webhook deleted successfully.');
    }

    public function regenerateSecret(Webhook $webhook)
    {
        $secret = Str::random(40);
        $webhook->update(['secret' => $secret]);

        return back()
            ->with('success', 'Webhook secret regenerated - the old secret no longer works.')
            ->with('plainSecret', $secret);
    }

    public function logs(Webhook $webhook)
    {
        return response()->json(
            $webhook->logs()->with('contact:id,first_name,last_name,email')->paginate(15)
        );
    }

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

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

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

    public function bulkToggleStatus(Request $request)
    {
        $data = $request->validate([
            'ids' => 'required|array',
            'ids.*' => 'exists:webhooks,id',
            'is_active' => 'required|boolean',
        ]);

        Webhook::whereIn('id', $data['ids'])->update(['is_active' => $data['is_active']]);

        return redirect()->route('webhooks.index')->with('success', 'Webhooks status updated.');
    }
}
