<?php

namespace App\Http\Controllers;

use App\Http\Requests\Paddle\PaddleCheckoutRequest;
use App\Models\CheckoutSession;
use App\Models\Package;
use App\Services\Checkout\CheckoutSessionService;
use App\Services\Coupons\CouponService;
use App\Services\Paddle\PaddleCheckoutService;
use App\Support\CheckoutRequestContext;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class PaddleCheckoutController extends Controller
{
    public function __construct(
        private readonly PaddleCheckoutService $checkout,
        private readonly CheckoutSessionService $sessions,
        private readonly CouponService $coupons,
    ) {}

    public function create(PaddleCheckoutRequest $request): JsonResponse
    {
        $data = $request->validated();

        $user = Auth::user();
        $tenant = $user?->tenant;

        if (! $tenant) {
            throw ValidationException::withMessages(['tenant' => 'Tenant context missing.']);
        }

        $package = Package::findOrFail((int) $data['package_id']);

        if (! $package->paddle_price_id) {
            throw ValidationException::withMessages(['package_id' => 'Package is not linked to a Paddle price.']);
        }

        $session = $this->sessions->createOrResume($user, $package, array_merge(
            CheckoutRequestContext::fromRequest($request),
            [
                'tenant' => $tenant,
            ]
        ));

        $this->sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);

        $now = now();

        $session->forceFill([
            'accepted_terms_at' => $now,
            'accepted_privacy_at' => $now,
            'accepted_withdrawal_notice_at' => $now,
            'digital_content_waiver_at' => null,
            'legal_version' => $this->resolveLegalVersion(),
        ])->save();

        $couponCode = Str::upper(trim((string) ($data['coupon_code'] ?? '')));
        $discountId = null;

        if ($couponCode !== '') {
            $preview = $this->coupons->preview($couponCode, $package, $tenant);
            $this->sessions->applyCoupon($session, $preview['coupon'], $preview['pricing']);
            $discountId = $preview['coupon']->paddle_discount_id;
        }

        if ($request->boolean('inline') && $discountId === null) {
            $metadata = array_merge($session->provider_metadata ?? [], [
                'mode' => 'inline',
            ]);

            $session->forceFill([
                'provider_metadata' => $metadata,
            ])->save();

            return response()->json([
                'checkout_session_id' => $session->id,
                'mode' => 'inline',
                'items' => [
                    [
                        'priceId' => $package->paddle_price_id,
                        'quantity' => 1,
                    ],
                ],
                'custom_data' => [
                    'tenant_id' => (string) $tenant->id,
                    'package_id' => (string) $package->id,
                    'checkout_session_id' => (string) $session->id,
                    'legal_version' => $session->legal_version,
                    'accepted_terms' => '1',
                ],
                'customer' => array_filter([
                    'email' => $user->email,
                    'name' => trim(($user->first_name ?? '').' '.($user->last_name ?? '')) ?: ($user->name ?? null),
                ]),
            ]);
        }

        $checkout = $this->checkout->createCheckout($tenant, $package, [
            'success_url' => $data['success_url'] ?? null,
            'return_url' => $data['return_url'] ?? null,
            'metadata' => [
                'checkout_session_id' => $session->id,
                'coupon_code' => $couponCode ?: null,
                'legal_version' => $session->legal_version,
                'accepted_terms' => true,
            ],
            'discount_id' => $discountId,
        ]);

        $session->forceFill([
            'paddle_checkout_id' => $checkout['id'] ?? $session->paddle_checkout_id,
            'provider_metadata' => array_merge($session->provider_metadata ?? [], array_filter([
                'paddle_checkout_id' => $checkout['id'] ?? null,
                'paddle_checkout_url' => $checkout['checkout_url'] ?? null,
                'paddle_expires_at' => $checkout['expires_at'] ?? null,
            ])),
        ])->save();

        return response()->json(array_merge($checkout, [
            'checkout_session_id' => $session->id,
        ]));
    }

    protected function resolveLegalVersion(): string
    {
        return config('app.legal_version', now()->toDateString());
    }
}
