<?php

namespace App\Services\Auction;

use App\Models\AuctionVehicle;
use App\Models\Bid;
use App\Models\BidHistory;
use App\Models\Order;
use App\Models\OrderStatusHistory;
use App\Models\Invoice;
use App\Models\User;
use App\Services\Calculator\BangladeshLandedCostCalculator;
use App\Services\Notification\NotificationDispatcher;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class AuctionService
{
    protected AuctionProviderInterface $provider;
    protected BangladeshLandedCostCalculator $calculator;
    protected NotificationDispatcher $notifications;

    public function __construct(
        BangladeshLandedCostCalculator $calculator,
        NotificationDispatcher $notifications
    ) {
        $this->calculator = $calculator;
        $this->notifications = $notifications;
        $this->provider = $this->resolveProvider();
    }

    protected function resolveProvider(): AuctionProviderInterface
    {
        $providerType = config('motosolution.auction.provider', 'mock');
        
        return match ($providerType) {
            'generic_api' => new GenericJapaneseAuctionProvider(),
            default => new MockJapanAuctionProvider(),
        };
    }

    public function getProvider(): AuctionProviderInterface
    {
        return $this->provider;
    }

    /**
     * Customer submits their authorized Maximum Bid
     * Status starts as 'pending' for MotoSolution admin review!
     */
    public function submitCustomerBid(User $user, AuctionVehicle $vehicle, float $maxBidJpy, array $metadata = []): array
    {
        // Validation: auction not ended
        if (!$vehicle->isBiddingOpen()) {
            return [
                'success' => false,
                'message' => 'This auction has ended or is no longer accepting bids.',
            ];
        }

        // Validation: minimum bid
        if ($maxBidJpy < $vehicle->starting_bid_jpy) {
            return [
                'success' => false,
                'message' => "Your maximum bid must be at least the starting bid of ¥" . number_format($vehicle->starting_bid_jpy, 0),
            ];
        }

        // Calculate Bangladesh Landed Cost estimate
        $calculation = $this->calculator->calculate([
            'price_jpy' => $maxBidJpy,
            'engine_cc' => $vehicle->engine_cc,
            'fuel_type' => $vehicle->fuel_type,
            'is_hybrid' => str_contains(strtolower($vehicle->fuel_type), 'hybrid'),
            'year' => $vehicle->year,
        ]);

        $bidCode = 'MS-BID-' . strtoupper(Str::random(6));

        $bid = DB::transaction(function () use ($user, $vehicle, $maxBidJpy, $calculation, $bidCode, $metadata) {
            $bid = Bid::create([
                'bid_code' => $bidCode,
                'user_id' => $user->id,
                'auction_vehicle_id' => $vehicle->id,
                'max_bid_jpy' => $maxBidJpy,
                'exchange_rate' => $calculation['exchange_rate'],
                'estimated_bd_cost_bdt' => $calculation['total_landed_cost_bdt'],
                'currency' => 'JPY',
                'cost_breakdown_snapshot' => $calculation,
                'status' => 'pending', // Awaiting admin review!
                'terms_accepted' => true,
                'terms_accepted_at' => now(),
                'ip_address' => request()->ip(),
                'user_agent' => request()->userAgent(),
                'admin_notes' => $metadata['notes'] ?? null,
            ]);

            BidHistory::create([
                'bid_id' => $bid->id,
                'user_id' => $user->id,
                'action' => 'created',
                'from_status' => null,
                'to_status' => 'pending',
                'notes' => 'Customer authorized maximum bid of ¥' . number_format($maxBidJpy, 0) . ' submitted for MotoSolution admin review.',
                'ip_address' => request()->ip(),
            ]);

            // Update stats
            $vehicle->increment('bids_count');
            if ($user->customer) {
                $user->customer->increment('total_bids');
                $user->customer->increment('active_bids');
            }

            return $bid;
        });

        // Send internal notification to admin
        $this->notifications->notifyAdmins(
            'New Customer Bid Pending Review',
            "Customer {$user->name} placed an authorized bid of ¥" . number_format($maxBidJpy, 0) . " on {$vehicle->full_name} (Lot #{$vehicle->lot_number}).",
            route('admin.bids.show', $bid->id)
        );

        // Notify customer
        $this->notifications->notifyUser(
            $user,
            'Bid Authorization Received',
            "Your maximum bid of ¥" . number_format($maxBidJpy, 0) . " on {$vehicle->full_name} has been received. Our auction team is reviewing it before submitting to the Japan auction floor.",
            route('customer.bids.index')
        );

        return [
            'success' => true,
            'bid' => $bid,
            'calculation' => $calculation,
            'message' => 'Your maximum authorized bid has been registered and sent to MotoSolution auction team for review.',
        ];
    }

    /**
     * Admin approves bid and sends to Japan auction floor via API adapter
     */
    public function approveAndSendToJapan(Bid $bid, User $admin, ?string $notes = null): array
    {
        if (!in_array($bid->status, ['pending', 'approved'])) {
            return [
                'success' => false,
                'message' => 'Only pending or approved bids can be submitted to Japan.',
            ];
        }

        // Call provider adapter
        $apiResult = $this->provider->placeBid(
            $bid->auctionVehicle->lot_number,
            (float) $bid->max_bid_jpy,
            ['bid_code' => $bid->bid_code]
        );

        $newStatus = ($apiResult['success'] ?? false) ? 'submitted' : 'approved';

        DB::transaction(function () use ($bid, $admin, $notes, $apiResult, $newStatus) {
            $bid->update([
                'status' => $newStatus,
                'reviewed_by' => $admin->id,
                'reviewed_at' => now(),
                'admin_notes' => $notes,
                'japan_api_provider' => get_class($this->provider),
                'japan_api_bid_id' => $apiResult['transaction_id'] ?? null,
                'japan_api_status' => $apiResult['status'] ?? 'PENDING_SUBMISSION',
                'japan_api_submitted_at' => now(),
                'japan_api_response' => $apiResult,
            ]);

            BidHistory::create([
                'bid_id' => $bid->id,
                'user_id' => $admin->id,
                'action' => 'approved_and_submitted_to_japan',
                'from_status' => 'pending',
                'to_status' => $newStatus,
                'notes' => $notes ?? 'Bid verified, approved, and successfully routed to Japanese auction API.',
                'ip_address' => request()->ip(),
            ]);
        });

        // Notify customer
        $this->notifications->notifyUser(
            $bid->user,
            'Bid Approved & Dispatched to Japan Auction Floor',
            "Great news! Your maximum authorized bid on {$bid->auctionVehicle->full_name} has been verified and registered on the live Japan auction floor.",
            route('customer.bids.index')
        );

        return [
            'success' => true,
            'bid' => $bid->fresh(),
            'api_result' => $apiResult,
            'message' => 'Bid approved and successfully transmitted to Japan auction provider.',
        ];
    }

    /**
     * Mark bid as Won: automatically creates Order and begins Import Tracking
     */
    public function markBidAsWon(Bid $bid, float $hammerPriceJpy, ?string $notes = null): Order
    {
        return DB::transaction(function () use ($bid, $hammerPriceJpy, $notes) {
            // Re-calculate actual landed cost based on actual hammer price
            $calc = $this->calculator->calculate([
                'price_jpy' => $hammerPriceJpy,
                'engine_cc' => $bid->auctionVehicle->engine_cc,
                'fuel_type' => $bid->auctionVehicle->fuel_type,
                'is_hybrid' => str_contains(strtolower($bid->auctionVehicle->fuel_type), 'hybrid'),
                'year' => $bid->auctionVehicle->year,
            ]);

            $finalBdCost = $calc['total_landed_cost_bdt'];

            $bid->update([
                'status' => 'won',
                'won_hammer_price_jpy' => $hammerPriceJpy,
                'final_bd_cost_bdt' => $finalBdCost,
            ]);

            $bid->auctionVehicle->update([
                'status' => 'ended',
                'result_status' => 'won',
                'final_hammer_price_jpy' => $hammerPriceJpy,
            ]);

            BidHistory::create([
                'bid_id' => $bid->id,
                'user_id' => auth()->id(),
                'action' => 'won',
                'from_status' => $bid->status,
                'to_status' => 'won',
                'notes' => "Won at Japanese auction! Hammer price: ¥" . number_format($hammerPriceJpy, 0) . ". Total estimated landed cost: ৳" . number_format($finalBdCost, 0),
            ]);

            // Create Order
            $orderNumber = 'MS-ORD-' . date('Y') . '-' . strtoupper(Str::random(5));
            $order = Order::create([
                'order_number' => $orderNumber,
                'user_id' => $bid->user_id,
                'auction_vehicle_id' => $bid->auction_vehicle_id,
                'bid_id' => $bid->id,
                'order_type' => 'auction_preorder',
                'total_amount_bdt' => $finalBdCost,
                'paid_amount_bdt' => 0,
                'due_amount_bdt' => $finalBdCost,
                'hammer_price_jpy' => $hammerPriceJpy,
                'status' => 'auction_won',
                'port_of_loading' => 'Yokohama, Japan',
                'port_of_discharge' => 'Chittagong Port, Bangladesh',
                'internal_notes' => $notes,
            ]);

            OrderStatusHistory::create([
                'order_id' => $order->id,
                'status' => 'auction_won',
                'title' => 'Vehicle Secured at Auction',
                'description' => "Vehicle was won at Japanese auction floor for ¥" . number_format($hammerPriceJpy, 0) . ". Import preparation initiated.",
                'location' => $bid->auctionVehicle->auctionHouse->city . ', Japan',
                'updated_by' => auth()->id(),
            ]);

            // Generate booking deposit invoice (20%)
            $depositAmount = round($finalBdCost * 0.20, -2);
            Invoice::create([
                'invoice_number' => 'MS-INV-' . strtoupper(Str::random(6)),
                'order_id' => $order->id,
                'user_id' => $bid->user_id,
                'title' => 'Initial Import Booking Deposit (20%)',
                'amount_bdt' => $depositAmount,
                'paid_bdt' => 0,
                'due_bdt' => $depositAmount,
                'due_date' => Carbon::now()->addDays(3),
                'status' => 'unpaid',
                'notes' => 'Required to commence Japanese yard processing and export documentation.',
            ]);

            // Update customer record
            if ($bid->user->customer) {
                $bid->user->customer->increment('won_bids');
                $bid->user->customer->decrement('active_bids');
                $bid->user->customer->increment('total_orders');
            }

            // Notify Customer
            $this->notifications->notifyUser(
                $bid->user,
                '🎉 Congratulations! Auction Won in Japan!',
                "Your authorized bid on {$bid->auctionVehicle->full_name} has WON at hammer price ¥" . number_format($hammerPriceJpy, 0) . "! Order #{$order->order_number} has been created with live import tracking.",
                route('customer.orders.show', $order->id)
            );

            return $order;
        });
    }

    /**
     * Mark bid as Lost
     */
    public function markBidAsLost(Bid $bid, ?string $reason = null): void
    {
        DB::transaction(function () use ($bid, $reason) {
            $bid->update(['status' => 'lost']);
            $bid->auctionVehicle->update([
                'status' => 'ended',
                'result_status' => 'lost',
            ]);

            BidHistory::create([
                'bid_id' => $bid->id,
                'user_id' => auth()->id(),
                'action' => 'lost',
                'from_status' => $bid->status,
                'to_status' => 'lost',
                'notes' => $reason ?? 'Floor bids exceeded authorized ceiling threshold.',
            ]);

            if ($bid->user->customer) {
                $bid->user->customer->increment('lost_bids');
                $bid->user->customer->decrement('active_bids');
            }

            $this->notifications->notifyUser(
                $bid->user,
                'Auction Result Update: Lot Closed',
                "The auction for {$bid->auctionVehicle->full_name} has concluded above your authorized ceiling. Our team will assist you in locating upcoming comparable Japanese lots.",
                route('customer.bids.index')
            );
        });
    }
}
