<?php

namespace App\Actions\Promo;

use App\DTOs\PromoResultData;
use App\Models\PwPromo;
use App\Models\Streamer;
use App\Repositories\PaymentSettingsRepository;

final class ValidatePromoAction
{
    public function __construct(
        private PaymentSettingsRepository $settingsRepository,
    ) {}

    public function handle(string $code, int $amount, int $userId): PromoResultData
    {
        if (! $this->settingsRepository->hasAnyActive()) {
            return new PromoResultData(
                valid: false,
                type: 'none',
                message: 'Payment gateway service is currently not available.',
            );
        }

        $goldRate = $this->settingsRepository->getActiveGoldRate();

        $promo = PwPromo::byCode($code)->first();

        if ($promo) {
            return $this->validatePromo($promo, $amount, $userId, $goldRate);
        }

        $streamer = Streamer::active()->byCode($code)->with('user')->first();

        if ($streamer) {
            return new PromoResultData(
                valid: true,
                type: 'streamer',
                message: 'Streamer code applied! Supporting '.($streamer->user->truename ?? $streamer->user->name ?? 'Unknown'),
                streamer: [
                    'id' => $streamer->id,
                    'code' => $streamer->code,
                    'name' => $streamer->user->name ?? 'Unknown',
                    'truename' => $streamer->user->truename ?? null,
                    'photo_url' => $streamer->user->photo ? asset($streamer->user->photo) : null,
                    'percentage' => (float) $streamer->percentage,
                ],
            );
        }

        return new PromoResultData(
            valid: false,
            type: 'none',
            message: 'Code not found.',
        );
    }

    private function validatePromo(PwPromo $promo, int $amount, int $userId, int $goldRate): PromoResultData
    {
        if (! $promo->isValid()) {
            $message = match (true) {
                ! $promo->is_active => 'Promo code is inactive.',
                $promo->start_date && now()->lt($promo->start_date) => 'Promo code is not yet active.',
                $promo->end_date && now()->gt($promo->end_date) => 'Promo code has expired.',
                $promo->usage_limit && $promo->usage_count >= $promo->usage_limit => 'Promo code usage limit reached.',
                default => 'Promo code is not valid.',
            };

            return new PromoResultData(valid: false, type: 'promo', message: $message);
        }

        if (! $promo->canBeUsedByUser($userId)) {
            return new PromoResultData(
                valid: false,
                type: 'promo',
                message: 'You have already used this promo code.',
            );
        }

        if ($amount < $promo->min_amount) {
            return new PromoResultData(
                valid: false,
                type: 'promo',
                message: 'Minimum amount for this promo is Rp '.number_format($promo->min_amount),
            );
        }

        $discountInfo = $promo->calculateDiscount($amount, $goldRate);

        return new PromoResultData(
            valid: true,
            type: 'promo',
            message: 'Promo code applied successfully!',
            promo: [
                'id' => $promo->id,
                'code' => $promo->code,
                'name' => $promo->name,
                'discount_type' => $promo->discount_type,
                'discount_value' => (float) $promo->discount_value,
                'discount_amount' => $discountInfo['discount'],
                'bonus_gold' => $discountInfo['bonus_gold'],
            ],
        );
    }
}
