<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\Campaign;
use Illuminate\Http\Request;
use App\Rules\OfferUrlTemplate;

class OffersController extends Controller
{
    public function index(Request $request)
    {
        $offers = Campaign::with('offerwall')
            ->when($request->filled('status'), fn ($query) => $query->where('status', $request->query('status')))
            ->latest()
            ->paginate(min(100, max(1, (int) $request->query('per_page', 25))));

        return response()->json([
            'data' => collect($offers->items())->map(fn (Campaign $campaign) => $this->resource($campaign)),
            'meta' => [
                'current_page' => $offers->currentPage(),
                'last_page' => $offers->lastPage(),
                'per_page' => $offers->perPage(),
                'total' => $offers->total(),
            ],
        ]);
    }

    public function show(Campaign $campaign)
    {
        return response()->json(['data' => $this->resource($campaign->load('offerwall'))]);
    }

    public function store(Request $request)
    {
        $campaign = Campaign::create($this->validated($request));

        return response()->json(['data' => $this->resource($campaign->load('offerwall'))], 201);
    }

    public function update(Request $request, Campaign $campaign)
    {
        $campaign->update($this->validated($request, true));

        return response()->json(['data' => $this->resource($campaign->fresh('offerwall'))]);
    }

    public function destroy(Campaign $campaign)
    {
        $campaign->delete();

        return response()->json(null, 204);
    }

    private function validated(Request $request, bool $partial = false): array
    {
        $presence = $partial ? 'sometimes' : 'required';

        return $request->validate([
            'offerwall_id' => ['nullable', 'exists:offerwalls,id'],
            'name' => [$presence, 'string', 'max:140'],
            'description' => ['nullable', 'string', 'max:1000'],
            'reward_points' => [$presence, 'numeric', 'min:0', 'max:'.config('rewards.max_offer_reward_points')],
            'payout' => [$presence, 'numeric', 'min:0'],
            'status' => [$presence, 'in:draft,active,paused,ended'],
            'featured' => ['sometimes', 'boolean'],
            'is_hot' => ['sometimes', 'boolean'],
            'curation_locked' => ['sometimes', 'boolean'],
            'category' => [$presence, 'in:games,other,surveys,partners'],
            'device' => [$presence, 'in:all,desktop,mobile,android,ios'],
            'countries' => ['nullable', 'string', 'max:180'],
            'direct_url' => [$partial ? 'sometimes' : 'required_without:offerwall_id', 'nullable', new OfferUrlTemplate, 'max:2000'],
            'direct_launch_mode' => [$presence, 'in:iframe,external'],
            'starts_at' => ['nullable', 'date'],
            'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'],
        ]);
    }

    private function resource(Campaign $campaign): array
    {
        return [
            'id' => $campaign->id,
            'name' => $campaign->name,
            'description' => $campaign->description,
            'provider' => optional($campaign->offerwall)->name,
            'offerwall_id' => $campaign->offerwall_id,
            'reward_points' => (float) $campaign->reward_points,
            'reward_usd' => coins_to_usd($campaign->reward_points),
            'payout' => (float) $campaign->payout,
            'status' => $campaign->status,
            'category' => $campaign->category,
            'device' => $campaign->device,
            'countries' => $campaign->countries,
            'direct_url' => $campaign->direct_url,
            'direct_launch_mode' => $campaign->direct_launch_mode,
            'featured' => (bool) $campaign->featured,
            'is_hot' => (bool) $campaign->is_hot,
            'starts_at' => optional($campaign->starts_at)->toIso8601String(),
            'ends_at' => optional($campaign->ends_at)->toIso8601String(),
            'postback_url' => route('api.v1.postback.custom'),
            'created_at' => optional($campaign->created_at)->toIso8601String(),
            'updated_at' => optional($campaign->updated_at)->toIso8601String(),
        ];
    }
}
