<?php

namespace App\Http\Controllers;

use App\Models\Activity;
use App\Models\Company;
use App\Models\Contact;
use App\Models\Deal;
use App\Models\User;
use App\Support\CrmModuleManager;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class ActivityController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Activity::class, 'activity');
    }

    public function index(Request $request): View
    {
        $type = $request->input('type');
        $userId = $request->integer('user_id');

        $activities = Activity::query()
            ->with(['user', 'deal', 'company', 'contact'])
            ->when($type, fn ($query) => $query->where('type', $type))
            ->when($userId, fn ($query) => $query->where('user_id', $userId))
            ->latest('occurred_at')
            ->paginate(20)
            ->withQueryString();

        $users = User::query()->orderBy('name')->get();

        return view('activities.index', compact('activities', 'users', 'type', 'userId'));
    }

    public function create(): View
    {
        return view('activities.create', $this->formData());
    }

    public function store(Request $request, CrmModuleManager $moduleManager): RedirectResponse
    {
        $payload = $this->validatedData($request);
        $payload['user_id'] = $request->user()->id;
        $payload = $moduleManager->applyPayloadHooks('activities.store', $payload, [
            'hook' => 'activities.store',
            'user_id' => $request->user()->id,
        ], array_keys($payload));

        $activity = Activity::create($payload);

        if ($activity->deal_id) {
            $activity->deal()->update(['last_activity_at' => $activity->occurred_at]);
        }

        return redirect()
            ->route('activities.show', $activity)
            ->with('success', 'Activity added.');
    }

    public function show(Activity $activity): View
    {
        $activity->load(['user', 'deal', 'company', 'contact']);

        return view('activities.show', compact('activity'));
    }

    public function edit(Activity $activity): View
    {
        return view('activities.edit', [
            ...$this->formData(),
            'activity' => $activity,
        ]);
    }

    public function update(Request $request, Activity $activity, CrmModuleManager $moduleManager): RedirectResponse
    {
        $payload = $this->validatedData($request);
        $payload = $moduleManager->applyPayloadHooks('activities.update', $payload, [
            'hook' => 'activities.update',
            'user_id' => $request->user()->id,
            'activity_id' => $activity->id,
        ], array_keys($payload));

        $activity->update($payload);

        if ($activity->deal_id) {
            $activity->deal()->update(['last_activity_at' => $activity->occurred_at]);
        }

        return redirect()
            ->route('activities.show', $activity)
            ->with('success', 'Activity updated.');
    }

    public function destroy(Activity $activity): RedirectResponse
    {
        $activity->delete();

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

    /**
     * @return array<string, mixed>
     */
    private function validatedData(Request $request): array
    {
        $validated = $request->validate([
            'type' => ['required', Rule::in(['call', 'email', 'meeting', 'note', 'task_update'])],
            'direction' => ['required', Rule::in(['inbound', 'outbound', 'internal'])],
            'subject' => ['required', 'string', 'max:255'],
            'details' => ['nullable', 'string'],
            'outcome' => ['nullable', 'string', 'max:255'],
            'deal_id' => ['nullable', 'exists:deals,id'],
            'company_id' => ['nullable', 'exists:companies,id'],
            'contact_id' => ['nullable', 'exists:contacts,id'],
            'occurred_at' => ['required', 'date'],
        ]);

        $validated['meta'] = [
            'created_from' => 'crm_ui',
        ];

        return $validated;
    }

    /**
     * @return array<string, mixed>
     */
    private function formData(): array
    {
        $deals = Deal::query()->latest()->limit(200)->get();
        $companies = Company::query()->orderBy('name')->get();
        $contacts = Contact::query()->orderBy('first_name')->orderBy('last_name')->get();

        return compact('deals', 'companies', 'contacts');
    }
}
