<?php

namespace App\Services;

use App\Models\Order;
use App\Models\User;
use App\Models\Transaction;
use App\Models\Metal;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;

class OrderLifecycleService
{
    public function __construct(
        protected MoneyBalanceService $moneyBalanceService,
        protected SmsNotificationService $smsNotificationService,
        protected ProductService $productService,
    ) {
    }

    public function confirm(Order $order, User $user): void
    {
        if ($order->status !== 'DRAFT') {
            throw ValidationException::withMessages([
                'status' => ['فقط سفارش‌های در حالت پیش‌نویس قابل تایید هستند'],
            ]);
        }

        // Validate order has required fields
        if (!$order->user_id) {
            throw ValidationException::withMessages([
                'user_id' => ['مشتری باید مشخص شود'],
            ]);
        }

        if (!$order->order_type) {
            throw ValidationException::withMessages([
                'order_type' => ['نوع سفارش باید مشخص شود'],
            ]);
        }

        if (empty($order->money_amount)) {
            throw ValidationException::withMessages([
                'money_amount' => ['مبلغ ریالی باید وارد شود'],
            ]);
        }

        DB::transaction(function () use ($order, $user) {
            $order->status = 'IN_PROGRESS';
            $order->confirmed_at = now();
            $order->confirmed_by = $user->id;
            $order->save();
            // موجودی محصول فقط با تراکنش فلز (تحویل/دریافت) به‌روز می‌شود، نه با تایید سفارش.
        });

        // Send SMS notification (outside transaction)
        $order->load('user');
        $this->smsNotificationService->notifyOrderStatusChange($order, 'IN_PROGRESS');
    }

    public function close(Order $order, User $user): void
    {
        if ($order->status !== 'IN_PROGRESS') {
            throw ValidationException::withMessages([
                'status' => ['فقط سفارش‌های در حال پردازش قابل تکمیل هستند'],
            ]);
        }

        $order->status = 'COMPLETED';
        $order->closed_at = now();
        $order->closed_by = $user->id;
        $order->save();

        // Send SMS notification
        $order->load('user');
        $this->smsNotificationService->notifyOrderStatusChange($order, 'COMPLETED');
    }

    /**
     * Check if order is balanced (both money and metal) and auto-complete if so.
     */
    public function checkAndAutoComplete(Order $order, ?User $user = null): bool
    {
        // Only check orders that are in progress
        if ($order->status !== 'IN_PROGRESS') {
            return false;
        }

        // فقط تراکنش‌های به‌حساب‌نشسته در محاسبهٔ مبلغ تسویه‌شده لحاظ می‌شوند
        $totalMoneyAmount = (float) ($order->money_amount ?? 0);
        $transactedMoney = (float) Transaction::where('order_id', $order->id)
            ->whereIn('status', ['SETTLED', 'CONFIRMED'])
            ->sum('amount');
        $remainingMoney = max(0, $totalMoneyAmount - $transactedMoney);

        // Check if money is balanced (remaining <= 0.01)
        $moneyBalanced = $remainingMoney <= 0.01;

        // Calculate metal remaining
        $order->load('lines.product');
        $metalBalanced = true;
        
        foreach ($order->lines as $line) {
            $productId = $line->product_id;
            if (!$productId) {
                continue;
            }

            $lineGrams = (float) $line->grams;
            $transactedGrams = (float) Metal::where('order_id', $order->id)
                ->where('product_id', $productId)
                ->sum('grams');
            
            $remainingGrams = max(0, $lineGrams - $transactedGrams);
            
            // If any product has remaining grams > 0.001, metal is not balanced
            if ($remainingGrams > 0.001) {
                $metalBalanced = false;
                break;
            }
        }

        // If both are balanced, auto-complete the order
        if ($moneyBalanced && $metalBalanced) {
            DB::transaction(function () use ($order, $user) {
                $order->status = 'COMPLETED';
                $order->closed_at = now();
                if ($user) {
                    $order->closed_by = $user->id;
                }
                $order->save();
            });

            // Send SMS notification (outside transaction)
            $order->load('user');
            $this->smsNotificationService->notifyOrderStatusChange($order, 'COMPLETED');

            return true;
        }

        return false;
    }

    /**
     * اگر سفارش تکمیل‌شده (COMPLETED) است ولی بعد از حذف/تغییر تراکنش دیگر متعادل نیست، وضعیت را به «در حال پردازش» برگردان.
     */
    public function revertToInProgressIfUnbalanced(Order $order): bool
    {
        if (! in_array($order->status, ['COMPLETED', 'CLOSED'])) {
            return false;
        }

        // فقط تراکنش‌های به‌حساب‌نشسته در تشخیص متعادل بودن لحاظ می‌شوند
        $totalMoneyAmount = (float) ($order->money_amount ?? 0);
        $transactedMoney = (float) Transaction::where('order_id', $order->id)
            ->whereIn('status', ['SETTLED', 'CONFIRMED'])
            ->sum('amount');
        $remainingMoney = max(0, $totalMoneyAmount - $transactedMoney);
        $moneyBalanced = $remainingMoney <= 0.01;

        $order->load('lines.product');
        $metalBalanced = true;
        foreach ($order->lines as $line) {
            if (! $line->product_id) {
                continue;
            }
            $lineGrams = (float) $line->grams;
            $transactedGrams = (float) Metal::where('order_id', $order->id)
                ->where('product_id', $line->product_id)
                ->sum('grams');
            if (max(0, $lineGrams - $transactedGrams) > 0.001) {
                $metalBalanced = false;
                break;
            }
        }

        if ($moneyBalanced && $metalBalanced) {
            return false;
        }

        DB::transaction(function () use ($order) {
            $order->status = 'IN_PROGRESS';
            $order->closed_at = null;
            $order->closed_by = null;
            $order->save();
        });

        $order->load('user');
        $this->smsNotificationService->notifyOrderStatusChange($order, 'IN_PROGRESS');

        return true;
    }

    /**
     * به‌روزرسانی money_status سفارش بر اساس فقط تراکنش‌های مستقیم (order_id = این سفارش).
     * وقتی با تراکنش سفارش دیگر بالانس شده، money_status همچنان UNSETTLED می‌ماند تا دکمهٔ تراکنش مالی فعال بماند.
     */
    public function updateOrderMoneyStatus(Order $order): void
    {
        $total = (float) ($order->money_amount ?? 0);
        if ($total < 0.01 || ! $order->user_id) {
            return;
        }

        // فقط تراکنش‌های به‌حساب‌نشسته در money_status سفارش لحاظ می‌شوند
        $directSum = (float) Transaction::where('order_id', $order->id)
            ->whereIn('status', ['SETTLED', 'CONFIRMED'])
            ->when($order->order_type === 'SELL', fn ($q) => $q->where('from_user_id', $order->user_id))
            ->when($order->order_type === 'BUY', fn ($q) => $q->where('to_user_id', $order->user_id))
            ->sum('amount');

        $remaining = max(0, $total - $directSum);
        $status = $remaining <= 0.01 ? 'SETTLED' : ($directSum > 0.01 ? 'PARTIAL' : 'UNSETTLED');

        if ($order->money_status !== $status) {
            $order->money_status = $status;
            $order->save();
        }
    }
}
