<?php

namespace App\Http\Controllers;

use App\Models\ManualPaymentGateway;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class AdminManualPaymentGatewayController extends Controller
{
    public function index()
    {
        return view('admin.manual-payments.gateways', [
            'gateways' => ManualPaymentGateway::withCount([
                'submissions',
                'submissions as pending_submissions_count' => fn ($query) => $query->where('status', 'pending'),
            ])->orderBy('sort_order')->get(),
        ]);
    }

    public function store(Request $request)
    {
        $data = $this->validatePayload($request);
        unset($data['icon']);
        unset($data['min_amount'], $data['max_amount']);
        $data = array_merge($data, $this->structuredPayload($request));
        $data['is_active'] = $request->boolean('is_active');
        $data['icon_path'] = $this->storeIcon($request) ?? $data['icon_path'] ?? null;

        ManualPaymentGateway::create($data);

        return back()->with('status', 'تم إضافة بوابة الدفع.');
    }

    public function update(Request $request, ManualPaymentGateway $manualPaymentGateway)
    {
        $data = $this->validatePayload($request);
        unset($data['icon']);
        unset($data['min_amount'], $data['max_amount']);
        $data = array_merge($data, $this->structuredPayload($request));
        $data['is_active'] = $request->boolean('is_active');
        $data['icon_path'] = $this->storeIcon($request) ?? $data['icon_path'] ?? $manualPaymentGateway->icon_path;

        $manualPaymentGateway->update($data);

        return back()->with('status', 'تم تحديث بوابة الدفع.');
    }

    public function destroy(ManualPaymentGateway $manualPaymentGateway)
    {
        $manualPaymentGateway->delete();

        return back()->with('status', 'تم حذف بوابة الدفع.');
    }

    private function validatePayload(Request $request): array
    {
        return $request->validate([
            'name_ar' => ['required', 'string', 'max:120'],
            'name_en' => ['nullable', 'string', 'max:120'],
            'slug' => ['nullable', 'string', 'max:120'],
            'description_ar' => ['nullable', 'string', 'max:2000'],
            'description_en' => ['nullable', 'string', 'max:2000'],
            'account_label_ar' => ['nullable', 'string', 'max:120'],
            'account_label_en' => ['nullable', 'string', 'max:120'],
            'account_number' => ['required', 'string', 'max:190'],
            'instructions_ar' => ['nullable', 'string', 'max:2000'],
            'instructions_en' => ['nullable', 'string', 'max:2000'],
            'proof_instructions_ar' => ['nullable', 'string', 'max:2000'],
            'proof_instructions_en' => ['nullable', 'string', 'max:2000'],
            'icon_path' => ['nullable', 'string', 'max:255'],
            'icon' => ['nullable', 'image', 'max:2048'],
            'sort_order' => ['nullable', 'integer', 'min:1', 'max:999'],
            'min_amount' => ['nullable', 'numeric', 'min:0', 'max:999999'],
            'max_amount' => ['nullable', 'numeric', 'min:0', 'max:999999'],
            'fee_type' => ['nullable', 'in:none,fixed,percent'],
            'fee_value' => ['nullable', 'integer', 'min:0', 'max:1000000'],
            'proof_max_mb' => ['nullable', 'integer', 'min:1', 'max:20'],
            'review_sla_minutes' => ['nullable', 'integer', 'min:1', 'max:10080'],
            'expires_after_minutes' => ['nullable', 'integer', 'min:10', 'max:43200'],
        ]);
    }

    private function structuredPayload(Request $request): array
    {
        $receiverData = collect($request->input('receiver_label', []))
            ->map(function ($label, $index) use ($request) {
                $value = $request->input("receiver_value.{$index}");

                if (blank($label) && blank($value)) {
                    return null;
                }

                return [
                    'label' => trim((string) $label),
                    'value' => trim((string) $value),
                    'type' => $request->input("receiver_type.{$index}", 'text'),
                    'copyable' => $request->boolean("receiver_copyable.{$index}", true),
                ];
            })
            ->filter()
            ->values()
            ->all();

        $requiredFields = collect($request->input('field_key', []))
            ->map(function ($key, $index) use ($request) {
                $label = $request->input("field_label.{$index}");

                if (blank($key) && blank($label)) {
                    return null;
                }

                return [
                    'key' => str($key ?: $label)->slug('_')->toString(),
                    'label' => trim((string) ($label ?: $key)),
                    'type' => $request->input("field_type.{$index}", 'text'),
                    'required' => $request->boolean("field_required.{$index}"),
                    'placeholder' => $request->input("field_placeholder.{$index}"),
                    'options' => collect(explode("\n", (string) $request->input("field_options.{$index}")))
                        ->map(fn ($option) => trim($option))
                        ->filter()
                        ->values()
                        ->all(),
                    'validation' => $request->input("field_validation.{$index}"),
                ];
            })
            ->filter(fn ($field) => filled($field['key']))
            ->values()
            ->all();

        $currencies = collect(explode(',', (string) $request->input('supported_currencies', 'EGP')))
            ->map(fn ($code) => strtoupper(trim($code)))
            ->filter()
            ->values()
            ->all();

        return [
            'receiver_data' => $receiverData ?: null,
            'required_fields' => $requiredFields ?: null,
            'supported_currencies' => $currencies ?: ['EGP'],
            'min_amount_minor' => filled($request->input('min_amount')) ? (int) round(((float) $request->input('min_amount')) * 100) : null,
            'max_amount_minor' => filled($request->input('max_amount')) ? (int) round(((float) $request->input('max_amount')) * 100) : null,
            'fee_type' => $request->input('fee_type', 'none'),
            'fee_value' => (int) $request->input('fee_value', 0),
            'requires_proof' => $request->boolean('requires_proof', true),
            'proof_is_required' => $request->boolean('proof_is_required', true),
            'proof_max_mb' => (int) $request->input('proof_max_mb', 6),
            'review_sla_minutes' => (int) $request->input('review_sla_minutes', 60),
            'expires_after_minutes' => (int) $request->input('expires_after_minutes', 1440),
            'country_codes' => collect(explode(',', (string) $request->input('country_codes')))
                ->map(fn ($code) => strtoupper(trim($code)))
                ->filter()
                ->values()
                ->all() ?: null,
            'risk_rules' => [
                'duplicate_reference' => true,
                'duplicate_proof' => true,
                'duplicate_identifier' => true,
            ],
        ];
    }

    private function storeIcon(Request $request): ?string
    {
        if (! $request->hasFile('icon')) {
            return null;
        }

        $directory = public_path('images/payment-gateways');
        if (! is_dir($directory)) {
            mkdir($directory, 0755, true);
        }

        $file = $request->file('icon');
        $filename = 'gateway-'.Str::random(10).'.'.$file->getClientOriginalExtension();
        $file->move($directory, $filename);

        return 'images/payment-gateways/'.$filename;
    }
}
