<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\PricingChange;
use App\Models\PricingPlan;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class AdminPricingController extends Controller
{
    private function authorizeAdmin(Request $request): ?JsonResponse
    {
        $adminToken = (string) config('dewemoji.admin.token', '');
        $provided = trim((string) $request->header('X-Admin-Token', ''));
        if ($adminToken === '' || $provided === '' || ! hash_equals($adminToken, $provided)) {
            return response()->json(['ok' => false, 'error' => 'unauthorized'], 401);
        }

        return null;
    }

    public function index(Request $request): JsonResponse
    {
        if ($res = $this->authorizeAdmin($request)) {
            return $res;
        }

        $plans = PricingPlan::orderBy('id')->get();

        return response()->json([
            'ok' => true,
            'plans' => $plans,
        ]);
    }

    public function changes(Request $request): JsonResponse
    {
        if ($res = $this->authorizeAdmin($request)) {
            return $res;
        }

        $limit = max((int) $request->query('limit', 20), 1);
        $items = PricingChange::orderByDesc('id')
            ->limit($limit)
            ->get();

        return response()->json([
            'ok' => true,
            'items' => $items,
        ]);
    }

    public function update(Request $request): JsonResponse
    {
        if ($res = $this->authorizeAdmin($request)) {
            return $res;
        }

        $data = $request->validate([
            'admin_ref' => 'nullable|string|max:120',
            'plans' => 'required|array|min:1',
            'plans.*.code' => 'required|string|max:30',
            'plans.*.name' => 'required|string|max:50',
            'plans.*.currency' => 'required|string|max:10',
            'plans.*.amount' => 'required|integer|min:0',
            'plans.*.period' => 'nullable|string|max:20',
            'plans.*.status' => 'nullable|string|max:20',
            'plans.*.meta' => 'nullable|array',
        ]);

        $before = PricingPlan::orderBy('id')->get()->toArray();

        DB::transaction(function () use ($data): void {
            foreach ($data['plans'] as $plan) {
                PricingPlan::updateOrCreate(
                    ['code' => $plan['code']],
                    [
                        'name' => $plan['name'],
                        'currency' => $plan['currency'],
                        'amount' => $plan['amount'],
                        'period' => $plan['period'] ?? null,
                        'status' => $plan['status'] ?? 'active',
                        'meta' => $plan['meta'] ?? null,
                    ]
                );
            }
        });

        $after = PricingPlan::orderBy('id')->get()->toArray();
        PricingChange::create([
            'admin_ref' => $data['admin_ref'] ?? null,
            'before' => $before,
            'after' => $after,
        ]);

        return response()->json([
            'ok' => true,
            'plans' => $after,
        ]);
    }

    public function reset(Request $request): JsonResponse
    {
        if ($res = $this->authorizeAdmin($request)) {
            return $res;
        }

        $defaults = config('dewemoji.pricing.defaults', []);
        $before = PricingPlan::orderBy('id')->get()->toArray();

        DB::transaction(function () use ($defaults): void {
            PricingPlan::query()->delete();
            foreach ($defaults as $plan) {
                PricingPlan::create([
                    'code' => $plan['code'],
                    'name' => $plan['name'],
                    'currency' => $plan['currency'],
                    'amount' => $plan['amount'],
                    'period' => $plan['period'],
                    'status' => $plan['status'],
                    'meta' => $plan['meta'] ?? null,
                ]);
            }
        });

        $after = PricingPlan::orderBy('id')->get()->toArray();
        PricingChange::create([
            'admin_ref' => (string) $request->header('X-Admin-Ref', ''),
            'before' => $before,
            'after' => $after,
        ]);

        return response()->json([
            'ok' => true,
            'plans' => $after,
        ]);
    }
}
