<?php

namespace App\Http\Controllers;

use App\Models\ManualPaymentGateway;
use App\Models\ManualPaymentSubmission;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class ManualPaymentSubmissionController extends Controller
{
    public function store(Request $request)
    {
        $baseRules = [
            'manual_payment_gateway_id' => ['required', 'exists:manual_payment_gateways,id'],
            'order_id' => ['nullable', 'exists:orders,id'],
            'amount' => ['required', 'numeric', 'min:1', 'max:999999'],
            'payer_name' => ['required', 'string', 'max:120'],
            'payer_phone' => ['required', 'string', 'max:40'],
            'reference_number' => ['nullable', 'string', 'max:120'],
            'payer_identifier_type' => ['nullable', Rule::in(['phone', 'username', 'email', 'reference', 'other'])],
            'payer_identifier' => ['nullable', 'string', 'max:190'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ];

        $gateway = ManualPaymentGateway::where('is_active', true)->findOrFail($request->input('manual_payment_gateway_id'));
        $proofMaxKb = max(1, (int) ($gateway->proof_max_mb ?: 6)) * 1024;
        $baseRules['proof'] = [
            $gateway->requires_proof && $gateway->proof_is_required ? 'required' : 'nullable',
            'image',
            'max:'.$proofMaxKb,
        ];
        $dynamicRules = $this->dynamicRules($gateway);
        $data = $request->validate(array_merge($baseRules, $dynamicRules));

        $order = null;
        if (! empty($data['order_id'])) {
            $order = Order::whereKey($data['order_id'])
                ->where('user_id', $request->user()->id)
                ->where('payment_method', 'manual')
                ->where('payment_status', '!=', 'paid')
                ->firstOrFail();

            if ($order->manualPaymentSubmissions()->whereIn('status', ['pending', 'info_requested', 'approved'])->exists()) {
                return back()->withErrors(['manual_payment' => 'يوجد طلب تحويل مرسل بالفعل لهذا الأوردر.'])->withInput();
            }
        }

        $amountMinor = $order ? (int) $order->total_minor : (int) round(((float) $data['amount']) * 100);

        if ($gateway->min_amount_minor && $amountMinor < $gateway->min_amount_minor) {
            return back()->withErrors(['amount' => 'المبلغ أقل من الحد الأدنى لهذه الوسيلة.'])->withInput();
        }

        if ($gateway->max_amount_minor && $amountMinor > $gateway->max_amount_minor) {
            return back()->withErrors(['amount' => 'المبلغ أكبر من الحد الأقصى لهذه الوسيلة.'])->withInput();
        }

        $proofPath = null;
        $proofHash = null;

        if ($request->hasFile('proof')) {
            $directory = public_path('images/payment-proofs');
            if (! is_dir($directory)) {
                mkdir($directory, 0755, true);
            }

            $file = $request->file('proof');
            $proofHash = hash_file('sha256', $file->getRealPath());
            $filename = 'proof-'.Str::random(14).'.'.$file->getClientOriginalExtension();
            $file->move($directory, $filename);
            $proofPath = 'images/payment-proofs/'.$filename;
        }

        $dynamicFields = $this->dynamicPayload($request, $gateway);
        [$riskScore, $riskFlags] = $this->riskSnapshot($gateway, $data, $proofHash);

        ManualPaymentSubmission::create([
            'uuid' => (string) Str::uuid(),
            'user_id' => $request->user()->id,
            'manual_payment_gateway_id' => $gateway->id,
            'order_id' => $order?->id,
            'submission_type' => $order ? 'order_payment' : 'wallet_topup',
            'amount_minor' => $amountMinor,
            'currency_code' => $order?->currency_code ?: ($gateway->supported_currencies[0] ?? 'EGP'),
            'payer_name' => $data['payer_name'],
            'payer_phone' => $data['payer_phone'],
            'reference_number' => $data['reference_number'] ?? null,
            'payer_identifier_type' => $data['payer_identifier_type'] ?? null,
            'payer_identifier' => $data['payer_identifier'] ?? null,
            'dynamic_fields' => $dynamicFields ?: null,
            'proof_path' => $proofPath,
            'proof_hash' => $proofHash,
            'risk_score' => $riskScore,
            'risk_flags' => $riskFlags ?: null,
            'notes' => $data['notes'] ?? null,
            'status' => 'pending',
            'expires_at' => now()->addMinutes(max(10, (int) ($gateway->expires_after_minutes ?: 1440))),
        ]);

        return back()->with('status', $order
            ? 'تم إرسال إثبات الدفع للطلب، وسيتم مراجعته قريبًا.'
            : 'تم إرسال طلب إضافة الرصيد، وسيتم مراجعته قريبًا.');
    }

    private function dynamicRules(ManualPaymentGateway $gateway): array
    {
        return collect($gateway->required_fields ?? [])
            ->mapWithKeys(function ($field) {
                $rules = [$field['required'] ?? false ? 'required' : 'nullable', 'string', 'max:190'];

                if (($field['type'] ?? 'text') === 'email') {
                    $rules[] = 'email';
                }

                if (($field['validation'] ?? null) === 'numeric') {
                    $rules[] = 'regex:/^[0-9\\s\\-\\+]+$/';
                }

                return ['dynamic_fields.'.($field['key'] ?? 'field') => $rules];
            })
            ->all();
    }

    private function dynamicPayload(Request $request, ManualPaymentGateway $gateway): array
    {
        return collect($gateway->required_fields ?? [])
            ->mapWithKeys(fn ($field) => [
                $field['key'] => [
                    'label' => $field['label'] ?? $field['key'],
                    'value' => $request->input('dynamic_fields.'.$field['key']),
                    'type' => $field['type'] ?? 'text',
                ],
            ])
            ->filter(fn ($entry) => filled($entry['value']))
            ->all();
    }

    private function riskSnapshot(ManualPaymentGateway $gateway, array $data, ?string $proofHash): array
    {
        $score = 0;
        $flags = [];

        if (filled($data['reference_number'] ?? null) && ManualPaymentSubmission::where('reference_number', $data['reference_number'])->exists()) {
            $score += 35;
            $flags[] = 'مرجع التحويل مستخدم من قبل';
        }

        if (filled($data['payer_identifier'] ?? null) && ManualPaymentSubmission::where('payer_identifier', $data['payer_identifier'])->exists()) {
            $score += 20;
            $flags[] = 'بيانات المحوّل تكررت في طلب سابق';
        }

        if ($proofHash && ManualPaymentSubmission::where('proof_hash', $proofHash)->exists()) {
            $score += 45;
            $flags[] = 'صورة الإثبات مكررة';
        }

        if ($gateway->proof_is_required && ! $proofHash) {
            $score += 50;
            $flags[] = 'لا يوجد إثبات تحويل';
        }

        return [min(100, $score), $flags];
    }
}
