<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\CurrencyType;
use App\Models\Currency;
use Sqids\Sqids;
use Illuminate\Support\Facades\Log;
use App\Models\Order;
use Carbon\Carbon;

class Dashboard extends Component
{
    public $currencyTypes;
    public $currencyId;
    public $currentCurrency;
    public $currentCurrencyTypeCode;
    public $rates;
    public $orderType = '';
    public $volume = 5;
    public $takeProfit = null;
    public $stopLoss = null;
    public $openOrders;
    public $closedOrders;
    public $selectedOrder = null;
    public $newTakeProfit = null;
    public $newStopLoss = null;
    public $modalType = null; // 'take_profit' or 'stop_loss'
    public $activeTab = null; // Track active tab
    public $showMoreDetails = false;
    public $search = '';
    public $filteredCurrencies = [];
    public $showCloseOrderModal = false;
    public $orderToClose = null;
    public $editingOrder = null;
    public $editVolume = null;
    public $editTakeProfit = null;
    public $editStopLoss = null;
    public $showEditOrderModal = false;

    protected $rules = [
        'volume' => 'required|numeric|min:0.1',
        'takeProfit' => 'nullable|numeric|min:0',
        'stopLoss' => 'nullable|numeric|min:0',
    ];

    protected $listeners = [
        'order-placed' => '$refresh'
    ];

    public function mount()
    {
        $this->currencyTypes = CurrencyType::ordered()->where('enabled', true)->get();
        $firstCurrencyType = $this->currencyTypes->first();
        $this->currentCurrency = $firstCurrencyType->currencies->first();
        $this->currencyId = $this->currentCurrency->id;
        $this->currentCurrencyTypeCode = $firstCurrencyType->code;
        $this->activeTab = 'open-orders';
        $this->loadOrders();
    }

    public function getOrderAmountProperty()
    {
        if (!$this->currentCurrency || !$this->volume) {
            return 0;
        }

        $price = $this->orderType == 'buy' ? $this->currentCurrency->bid : $this->currentCurrency->ask;
        return $this->volume * $price;
    }

    public function canPlaceOrder()
    {
        if (!$this->currentCurrency || !$this->volume || !$this->orderType) {
            return false;
        }

        $sharePerLot = 100;

        // Check if margin is more than free margin
        $margin = $this->orderAmount / $this->currentCurrency->leverage;
        if ($this->currentCurrency->type->code == 'currencies') {
            if (str_contains($this->currentCurrency->code, 'JPY')) {
                $margin = $margin * 1000;
            } else {
                $margin = $margin * 100000;
            }
        } else if ($this->currentCurrency->type->code == 'stocks') {
            $margin = ($this->orderAmount * $sharePerLot) / $this->currentCurrency->leverage;
        }

        if ($margin > auth()->user()->calculateFreeMargin()) {
            return false;
        }

        // Check take profit and stop loss conditions
        if ($this->orderType === 'buy') {
            if ($this->takeProfit && $this->takeProfit <= $this->currentCurrency->ask) {
                return false;
            }
            if ($this->stopLoss && $this->stopLoss >= $this->currentCurrency->bid) {
                return false;
            }
        } else {
            if ($this->takeProfit && $this->takeProfit >= $this->currentCurrency->bid) {
                return false;
            }
            if ($this->stopLoss && $this->stopLoss <= $this->currentCurrency->ask) {
                return false;
            }
        }

        return true;
    }

    public function getSpreadProperty()
    {
        if (!$this->currentCurrency) {
            return 0;
        }
        return $this->currentCurrency->ask - $this->currentCurrency->bid;
    }

    public function getSpreadPercentageProperty()
    {
        if (!$this->currentCurrency || !$this->currentCurrency->bid) {
            return 0;
        }
        return ($this->spread / $this->currentCurrency->bid) * 100;
    }

    public function getFeesProperty()
    {
        return $this->margin * 0.05;
    }

    public function getMarginProperty()
    {
        if (!$this->currentCurrency || !$this->orderAmount) {
            return 0;
        }

        $sharePerLot = 100;

        $margin = $this->orderAmount / $this->currentCurrency->leverage;
        if ($this->currentCurrency->type->code == 'currencies') {
            if (str_contains($this->currentCurrency->code, 'JPY')) {
                $margin = $margin * 1000;
            } else {
                $margin = $margin * 100000;
            }
        } else if ($this->currentCurrency->type->code == 'stocks') {
            $margin = ($this->orderAmount * $sharePerLot) / $this->currentCurrency->leverage;
        }

        return $margin;
    }

    public function getSwapProperty()
    {
        // Assuming 0.01% daily swap rate
        if (!$this->currentCurrency || !$this->orderAmount) {
            return 0;
        }
        return $this->orderAmount * 0.0001;
    }

    public function getPipValueProperty()
    {
        if (!$this->currentCurrency || !$this->volume) {
            return 0;
        }
        // Assuming 1 pip = 0.0001 for most crypto pairs
        return $this->volume * 0.1;
    }

    public function getVolumeInUnitsProperty()
    {
        if (!$this->currentCurrency || !$this->volume) {
            return 0;
        }
        return $this->volume;
    }

    public function getVolumeInUsdProperty()
    {
        return $this->orderAmount;
    }

    public function loadOrders()
    {
        $this->openOrders = Order::where('user_id', auth()->id())
            ->where('status', 'open')
            ->with('currency')
            ->latest()
            ->get();

        $this->closedOrders = Order::where('user_id', auth()->id())
            ->where('status', 'closed')
            ->with('currency')
            ->orderBy('close_time', 'desc')
            ->get();
    }

    public function clickCurrency($currencyId)
    {
        $this->currencyId = $currencyId;
        $this->currentCurrency = Currency::find($currencyId);
        $this->resetOrder();
        $this->dispatch('currency-changed', currentCurrency: $this->currentCurrency);
    }

    public function clickCurrencyType($id)
    {
        $this->currentCurrencyTypeCode = $id;
        $this->dispatch('currency-type-changed', currentCurrency: $this->currentCurrency);
    }

    public function clickOrderTypeButton($type)
    {
        $this->orderType = $type;
    }

    public function clickConfirmOrder()
    {
        $openPrice = $this->orderType == 'buy' ? $this->currentCurrency->bid : $this->currentCurrency->ask;
        $amount = $this->volume * $openPrice;
        
        $sharePerLot = 100;
        $margin = $this->orderAmount / $this->currentCurrency->leverage;

        if ($this->currentCurrency->type->code == 'currencies') {
            if (str_contains($this->currentCurrency->code, 'JPY')) {
                $margin = $margin * 1000;
            } else {
                $margin = $margin * 100000;
            }
        } else if ($this->currentCurrency->type->code == 'stocks') {
            $margin = ($this->orderAmount * $sharePerLot) / $this->currentCurrency->leverage;
        }


        $order = Order::create([
            'user_id' => auth()->user()->id,
            'type' => 'market',
            'side' => $this->orderType,
            'currency_id' => $this->currentCurrency->id,
            'open_price' => $openPrice,
            'volume' => $this->volume,
            'open_time' => Carbon::now(),
            'take_profit' => $this->takeProfit,
            'stop_loss' => $this->stopLoss,
            'amount' => $amount,
            'margin' => $margin,
            'fee' => $this->getFeesProperty()
        ]);

        $this->dispatch('alert', [
            'type' => 'success',
            'message' => 'Order placed successfully!'
        ]);

        $this->resetOrder();
        
        return redirect(request()->header('Referer'));
    }

    private function resetOrder()
    {
        $this->orderType = '';
        $this->volume = 5;
        $this->takeProfit = null;
        $this->stopLoss = null;
    }

    public function openTakeProfitModal($orderId)
    {
        $this->selectedOrder = Order::find($orderId);
        $this->newTakeProfit = $this->selectedOrder->take_profit;
        $this->modalType = 'take_profit';
    }

    public function openStopLossModal($orderId)
    {
        $this->selectedOrder = Order::find($orderId);
        $this->newStopLoss = $this->selectedOrder->stop_loss;
        $this->modalType = 'stop_loss';
    }

    public function updateTakeProfit()
    {
        $this->validate([
            'newTakeProfit' => 'required|numeric|min:0',
        ]);

        $this->selectedOrder->update([
            'take_profit' => $this->newTakeProfit
        ]);

        $this->dispatch('alert', [
            'type' => 'success',
            'message' => 'Take profit updated successfully!'
        ]);

        $this->loadOrders();
        $this->closeModal();
    }

    public function updateStopLoss()
    {
        $this->validate([
            'newStopLoss' => 'required|numeric|min:0',
        ]);

        $this->selectedOrder->update([
            'stop_loss' => $this->newStopLoss
        ]);

        $this->dispatch('alert', [
            'type' => 'success',
            'message' => 'Stop loss updated successfully!'
        ]);

        $this->loadOrders();
        $this->closeModal();
    }

    public function closeModal()
    {
        $this->selectedOrder = null;
        $this->newTakeProfit = null;
        $this->newStopLoss = null;
        $this->modalType = null;
    }

    public function switchTab($tab)
    {
        $this->activeTab = $tab;
    }

    public function closeOrder($orderId)
    {
        $order = Order::find($orderId);
        $order->close();

        $this->loadOrders();
    }
    
    public function setTakeProfit()
    {
        if ($this->orderType === 'buy') {
            return $this->currentCurrency->ask + 1;
        } else {
            return $this->currentCurrency->bid - 1;
        }
    }
    
    public function setStopLoss()
    {
        if ($this->orderType === 'buy') {
            return $this->currentCurrency->bid - 1;
        } else {
            return $this->currentCurrency->ask + 1;
        }
    }

    public function incrementTakeProfit()
    {
        if ($this->takeProfit === null) {
            $this->takeProfit = $this->setTakeProfit();
        } else {
            $this->takeProfit = round($this->takeProfit + 1, 2);
        }
    }

    public function decrementTakeProfit()
    {
        if ($this->takeProfit === null) {
            $this->takeProfit = $this->setTakeProfit();
        } else if ($this->takeProfit <= 0)
        {
            return;
        } else {
            $this->takeProfit = round($this->takeProfit - 1, 2);
        }
        
    }

    public function incrementStopLoss()
    {
        if ($this->stopLoss === null) {
            $this->stopLoss = $this->setStopLoss();
        } else {
            $this->stopLoss = round($this->stopLoss + 1, 2);
        }
    }

    public function decrementStopLoss()
    {
        if ($this->stopLoss === null) {
            $this->stopLoss = $this->setStopLoss();
        } else if ($this->stopLoss <= 0) {
            return;
        } else {
            $this->stopLoss = round($this->stopLoss - 1, 2);
        }
    }

    public function updatedVolume($value)
    {
        $this->validateOnly('volume');
    }

    public function incrementVolume()
    {
        $this->volume = round($this->volume + 0.1, 1);
        $this->validateOnly('volume');
    }

    public function decrementVolume()
    {
        if ($this->volume <= 0.1) {
            return;
        }
        $this->volume = round($this->volume - 0.1, 1);
        $this->validateOnly('volume');
    }

    public function updatedSearch()
    {
        if (empty($this->search)) {
            $this->filteredCurrencies = [];
            return;
        }

        $searchTerm = strtolower($this->search);
        $allCurrencies = collect();

        foreach ($this->currencyTypes as $currencyType) {
            $allCurrencies = $allCurrencies->merge($currencyType->currencies);
        }

        $this->filteredCurrencies = $allCurrencies->filter(function ($currency) use ($searchTerm) {
            return str_contains(strtolower($currency->name), $searchTerm) ||
                   str_contains(strtolower($currency->code), $searchTerm);
        })->values()->all();
    }

    public function confirmCloseOrder($orderId)
    {
        $this->orderToClose = $orderId;
        $this->showCloseOrderModal = true;
    }

    public function cancelCloseOrder()
    {
        $this->orderToClose = null;
        $this->showCloseOrderModal = false;
    }

    public function closeOrderConfirmed()
    {
        if ($this->orderToClose) {
            $this->closeOrder($this->orderToClose);
            $this->orderToClose = null;
            $this->showCloseOrderModal = false;
        }
    }

    public function openEditOrderModal($orderId)
    {
        $this->editingOrder = Order::find($orderId);
        $this->editVolume = floatval($this->editingOrder->volume);
        $this->editTakeProfit = $this->editingOrder->take_profit ? floatval($this->editingOrder->take_profit) : null;
        $this->editStopLoss = $this->editingOrder->stop_loss ? floatval($this->editingOrder->stop_loss) : null;
        $this->showEditOrderModal = true;
    }

    public function closeEditOrderModal()
    {
        $this->editingOrder = null;
        $this->editVolume = null;
        $this->editTakeProfit = null;
        $this->editStopLoss = null;
        $this->showEditOrderModal = false;
    }

    public function updateOrder()
    {
        $this->validate([
            'editVolume' => 'required|numeric|min:0.1',
            'editTakeProfit' => 'nullable|numeric|min:0',
            'editStopLoss' => 'nullable|numeric|min:0',
        ]);

        $this->editingOrder->update([
            'volume' => $this->editVolume,
            'take_profit' => $this->editTakeProfit ? $this->editTakeProfit : null,
            'stop_loss' => $this->editStopLoss ? $this->editStopLoss : null,
        ]);

        $this->dispatch('alert', [
            'type' => 'success',
            'message' => 'Order updated successfully!'
        ]);

        $this->loadOrders();
        $this->closeEditOrderModal();
    }

    public function canUpdateOrder()
    {
        if($this->editingOrder->side === 'buy' && $this->editTakeProfit && $this->editTakeProfit <= $this->editingOrder->currency->ask)
            return false;
        if($this->editingOrder->side === 'sell' && $this->editTakeProfit && $this->editTakeProfit >= $this->editingOrder->currency->bid)
            return false;
        if($this->editingOrder->side === 'sell' && $this->editStopLoss && $this->editStopLoss <= $this->editingOrder->currency->bid)
            return false;
        if($this->editingOrder->side === 'buy' && $this->editStopLoss && $this->editStopLoss >= $this->editingOrder->currency->ask)
            return false;
        return true;
    }

    public function canUpdateSelectedOrder()
    {
        if($this->selectedOrder->side === 'buy' && $this->newTakeProfit && $this->newTakeProfit <= $this->selectedOrder->currency->ask)
            return false;
        if($this->selectedOrder->side === 'sell' && $this->newTakeProfit && $this->newTakeProfit >= $this->selectedOrder->currency->bid)
            return false;
        if($this->selectedOrder->side === 'sell' && $this->newStopLoss && $this->newStopLoss <= $this->selectedOrder->currency->bid)
            return false;
        if($this->selectedOrder->side === 'buy' && $this->newStopLoss && $this->newStopLoss >= $this->selectedOrder->currency->ask)
            return false;
        return true;
    }

    public function render()
    {
        return view('livewire.dashboard');
    }
}
