<?php

namespace App\Http\Controllers\VendorShip;

use App\Http\Controllers\Controller;
use App\Models\GeneralSetting;
use App\Models\Setting;
use App\Models\User;
use App\Models\VendorProfile;
use App\Services\VoucherTransactionService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class VendorApplicationController extends Controller
{
    public function index()
    {
        $profile = VendorProfile::where('user_id', auth()->id())->first();

        $settings = GeneralSetting::first();
        $serviceCharge = max(0, (float) ($settings->vendor_service_charge ?? 0));
        $chargeDue = $serviceCharge > 0 && (!$profile || !$profile->service_charge_paid_at);
        $serviceChargeTitle = trim((string) (Setting::getValue('vendor_service_charge_title') ?? ''));
        $serviceChargeNote = trim((string) (Setting::getValue('vendor_service_charge_note') ?? ''));

        if ($serviceChargeTitle === '') {
            $serviceChargeTitle = 'Vendor Service Charge:';
        }

        if ($serviceChargeNote === '') {
            $serviceChargeNote = 'এপ্লাই করার সময় ভাউচার ব্যালেন্স থেকে কাটা হবে।';
        }

        return view('vendor_ship.apply', compact(
            'profile',
            'serviceCharge',
            'chargeDue',
            'serviceChargeTitle',
            'serviceChargeNote'
        ));
    }

    public function submit(Request $request)
    {
        $profile = VendorProfile::where('user_id', auth()->id())->first();

        if ($profile && $profile->status === 'approved') {
            return redirect()->route('vendor-ship.profile')
                ->with('success', 'Your vendor profile is already approved.');
        }

        $settings = GeneralSetting::first();
        $serviceCharge = max(0, (float) ($settings->vendor_service_charge ?? 0));
        $chargeDue = $serviceCharge > 0 && (!$profile || !$profile->service_charge_paid_at);

        if ($chargeDue) {
            $user = User::findOrFail(auth()->id());
            if ((float) ($user->voucher_balance ?? 0) < $serviceCharge) {
                return back()
                    ->with('error', 'ভাউচার ব্যালেন্স পর্যাপ্ত নয়।')
                    ->withInput($request->except('image'));
            }
        }

        $rules = [
            'vendor_name' => 'required|string|max:191',
            'address' => 'required|string|max:500',
            'image' => ($profile ? 'nullable|file' : 'required|file'),
        ];

        $data = $request->validate($rules);

        $imagePath = $profile?->image_path;
        if ($request->hasFile('image')) {
            if ($imagePath) {
                $old = public_path(ltrim($imagePath, '/'));
                if (is_file($old)) {
                    @unlink($old);
                }
                $webOld = rtrim($this->detectWebRoot(), '/\\') . '/' . ltrim($imagePath, '/');
                if (is_file($webOld) && realpath($webOld) !== realpath($old)) {
                    @unlink($webOld);
                }
            }

            $imagePath = $this->uploadImage($request->file('image'));
        }

        try {
            DB::transaction(function () use ($data, $imagePath, $serviceCharge) {
                $userId = (int) auth()->id();

                $profile = VendorProfile::where('user_id', $userId)->lockForUpdate()->first();

                $payload = [
                    'image_path' => $imagePath,
                    'vendor_name' => $data['vendor_name'],
                    'address' => $data['address'],
                    'status' => 'pending',
                    'admin_note' => null,
                    'reviewed_by' => null,
                    'reviewed_at' => null,
                ];

                $profile = VendorProfile::updateOrCreate(
                    ['user_id' => $userId],
                    $payload
                );

                $needsCharge = $serviceCharge > 0 && (!$profile->service_charge_paid_at);

                if ($needsCharge) {
                    $user = User::lockForUpdate()->findOrFail($userId);
                    $before = (float) ($user->voucher_balance ?? 0);
                    if ($before < $serviceCharge) {
                        throw new \Exception('ভাউচার ব্যালেন্স পর্যাপ্ত নয়।');
                    }

                    $after = $before - $serviceCharge;
                    $user->voucher_balance = $after;
                    $user->save();

                    $txn = VoucherTransactionService::record(
                        userId: $userId,
                        direction: 'debit',
                        amount: $serviceCharge,
                        before: $before,
                        after: $after,
                        source: 'vendor_service_charge',
                        description: 'ভেন্ডর এপ্লাই সার্ভিস চার্জ কাটা হয়েছে।',
                        referenceType: 'vendor_profile',
                        referenceId: $profile->id
                    );

                    $profile->service_charge_amount = $serviceCharge;
                    $profile->service_charge_paid_at = now();
                    $profile->service_charge_txn_id = $txn?->txn_id;
                    $profile->save();
                }
            });
        } catch (\Throwable $e) {
            return back()
                ->with('error', $e->getMessage())
                ->withInput($request->except('image'));
        }

        return redirect()->route('vendor-ship.apply')
            ->with('success', 'Application submitted. Status: Pending. We will contact you within 3 days.');
    }

    private function uploadImage($file): string
    {
        $dir = public_path('images/vendor-ship/vendors');
        if (!is_dir($dir)) {
            File::makeDirectory($dir, 0755, true);
        }

        $ext = strtolower($file->getClientOriginalExtension() ?: 'jpg');
        $filename = now()->format('Ymd_His') . '_' . Str::random(10) . '.' . $ext;
        $file->move($dir, $filename);
        optimize_uploaded_image($dir . DIRECTORY_SEPARATOR . $filename);
        $this->mirrorToWebRootIfNeeded($dir . DIRECTORY_SEPARATOR . $filename, 'images/vendor-ship/vendors/' . $filename);

        return '/images/vendor-ship/vendors/' . $filename;
    }

    private function mirrorToWebRootIfNeeded(string $sourceAbsPath, string $relativeTargetPath): void
    {
        if (!is_file($sourceAbsPath)) {
            return;
        }

        $webRoot = rtrim($this->detectWebRoot(), '/\\');
        $targetAbs = $webRoot . '/' . ltrim($relativeTargetPath, '/');
        if (is_file($targetAbs)) {
            return;
        }

        if (!is_dir(dirname($targetAbs))) {
            @mkdir(dirname($targetAbs), 0755, true);
        }
        @copy($sourceAbsPath, $targetAbs);
    }

    private function detectWebRoot(): string
    {
        $candidates = [
            isset($_SERVER['SCRIPT_FILENAME']) ? realpath(dirname((string) $_SERVER['SCRIPT_FILENAME'])) : null,
            realpath($_SERVER['DOCUMENT_ROOT'] ?? '') ?: null,
            is_dir(public_path()) ? public_path() : null,
            is_dir(base_path()) ? base_path() : null,
        ];

        foreach (array_filter($candidates) as $root) {
            if (is_dir($root) && is_writable($root)) {
                return rtrim($root, '/\\');
            }
        }

        return rtrim(public_path(), '/\\');
    }
}
