<?php

namespace App\Services;

use App\Models\PurchaseReturn;
use App\Models\JournalEntry;
use App\Models\JournalEntryItem;
use App\Models\ChartOfAccount;
use App\Models\Supplier;
use App\Models\FiscalYear;
use App\Models\AccountingPeriod;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

class PurchaseReturnJournalService
{
    /**
     * إنشاء قيد محاسبي لمرتجع المشتريات
     *
     * @param PurchaseReturn $return مرتجع المشتريات
     * @return JournalEntry|null القيد المحاسبي أو null في حالة الفشل
     */
    public function createPurchaseReturnJournalEntry(PurchaseReturn $return)
    {
        try {
            DB::beginTransaction();

            // البحث عن السنة المالية والفترة المحاسبية النشطة
            $fiscalYear = FiscalYear::where('company_id', $return->company_id)
                ->where('is_active', true)
                ->where('is_closed', false)
                ->first();

            if (!$fiscalYear) {
                throw new \Exception('لا توجد سنة مالية نشطة');
            }

            $entryDate = $return->return_date;

            $accountingPeriod = AccountingPeriod::where('fiscal_year_id', $fiscalYear->id)
                ->where('is_closed', false)
                ->where('start_date', '<=', $entryDate)
                ->where('end_date', '>=', $entryDate)
                ->first();

            if (!$accountingPeriod) {
                throw new \Exception('لا توجد فترة محاسبية نشطة للتاريخ المحدد');
            }

            // إنشاء القيد المحاسبي
            $entry = new JournalEntry();
            $entry->company_id = $return->company_id;
            $entry->fiscal_year_id = $fiscalYear->id;
            $entry->accounting_period_id = $accountingPeriod->id;
            $entry->entry_number = JournalEntry::generateEntryNumber($return->company_id);
            $entry->entry_date = $entryDate;
            $entry->reference_type = 'App\Models\PurchaseReturn';
            $entry->reference_id = $return->id;
            $entry->description = 'قيد مرتجع مشتريات رقم: ' . $return->return_number;
            $entry->is_posted = false;
            $entry->is_approved = false;
            $entry->created_by = $return->created_by;
            $entry->save();

            // إنشاء بنود القيد المحاسبي
            $this->createPurchaseReturnJournalEntryItems($entry, $return);

            // ترحيل القيد المحاسبي
            $entry->post();

            DB::commit();

            return $entry;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('فشل في إنشاء قيد محاسبي لمرتجع المشتريات: ' . $e->getMessage(), [
                'return_id' => $return->id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }

    /**
     * إنشاء بنود القيد المحاسبي لمرتجع المشتريات
     *
     * @param JournalEntry $entry القيد المحاسبي
     * @param PurchaseReturn $return مرتجع المشتريات
     * @return void
     */
    private function createPurchaseReturnJournalEntryItems(JournalEntry $entry, PurchaseReturn $return)
    {
        // 1. حساب المخزون (دائن) - عكس القيد الأصلي
        $inventoryAccount = $this->getOrCreateInventoryAccount($return->company_id);

        // 2. حساب الدائنين (ذمم الموردين) (مدين) - عكس القيد الأصلي
        $accountPayable = $this->getOrCreateAccountPayable($return->company_id, $return->supplier);

        // 3. حساب ضريبة القيمة المضافة (دائن) - عكس القيد الأصلي
        $vatAccount = $this->getOrCreateVatAccount($return->company_id);

        // إنشاء بند دائن (المخزون) - عكس القيد الأصلي
        $creditItem = new JournalEntryItem();
        $creditItem->journal_entry_id = $entry->id;
        $creditItem->account_id = $inventoryAccount->id;
        $creditItem->description = 'مرتجع مشتريات رقم: ' . $return->return_number . ' - مخزون';
        $creditItem->debit = 0;
        $creditItem->credit = $return->subtotal - $return->discount_amount;
        $creditItem->save();

        // إنشاء بند دائن (ضريبة القيمة المضافة) - عكس القيد الأصلي
        if ($return->tax_amount > 0) {
            $vatItem = new JournalEntryItem();
            $vatItem->journal_entry_id = $entry->id;
            $vatItem->account_id = $vatAccount->id;
            $vatItem->description = 'مرتجع مشتريات رقم: ' . $return->return_number . ' - ضريبة القيمة المضافة';
            $vatItem->debit = 0;
            $vatItem->credit = $return->tax_amount;
            $vatItem->save();
        }

        // إنشاء بند مدين (ذمم الموردين) - عكس القيد الأصلي
        $debitItem = new JournalEntryItem();
        $debitItem->journal_entry_id = $entry->id;
        $debitItem->account_id = $accountPayable->id;
        $debitItem->description = 'مرتجع مشتريات رقم: ' . $return->return_number . ' - ' . $return->supplier->name;
        $debitItem->debit = $return->total_amount;
        $debitItem->credit = 0;
        $debitItem->save();
    }

    /**
     * الحصول على أو إنشاء حساب المخزون
     *
     * @param int $companyId معرف الشركة
     * @return ChartOfAccount حساب المخزون
     */
    private function getOrCreateInventoryAccount($companyId)
    {
        // البحث عن حساب المخزون (1300)
        $inventoryAccount = ChartOfAccount::where('company_id', $companyId)
            ->where('account_code', '1300')
            ->first();

        // إذا لم يوجد حساب المخزون، نقوم بإنشائه
        if (!$inventoryAccount) {
            // البحث عن حساب الأصول المتداولة
            $currentAssetsAccount = ChartOfAccount::where('account_code', '1100')
                ->where('company_id', $companyId)
                ->first();

            if (!$currentAssetsAccount) {
                // إذا لم يوجد حساب الأصول المتداولة، نبحث عن حساب الأصول
                $assetsAccount = ChartOfAccount::where('account_code', '1000')
                    ->where('company_id', $companyId)
                    ->first();

                if (!$assetsAccount) {
                    // إنشاء حساب الأصول الرئيسي
                    $assetsAccount = new ChartOfAccount();
                    $assetsAccount->company_id = $companyId;
                    $assetsAccount->account_code = '1000';
                    $assetsAccount->name = 'الأصول';
                    $assetsAccount->name_en = 'Assets';
                    $assetsAccount->account_type = 'asset';
                    $assetsAccount->sub_type = 'assets';
                    $assetsAccount->parent_id = null;
                    $assetsAccount->description = 'حساب الأصول الرئيسي';
                    $assetsAccount->is_active = true;
                    $assetsAccount->is_system = true;
                    $assetsAccount->opening_balance = 0;
                    $assetsAccount->current_balance = 0;
                    $assetsAccount->currency = 'SAR';
                    $assetsAccount->balance_type = 'debit';
                    $assetsAccount->is_cash_account = false;
                    $assetsAccount->is_bank_account = false;
                    $assetsAccount->level = 1;
                    $assetsAccount->is_parent = true;
                    $assetsAccount->save();
                }

                // إنشاء حساب الأصول المتداولة
                $currentAssetsAccount = new ChartOfAccount();
                $currentAssetsAccount->company_id = $companyId;
                $currentAssetsAccount->account_code = '1100';
                $currentAssetsAccount->name = 'الأصول المتداولة';
                $currentAssetsAccount->name_en = 'Current Assets';
                $currentAssetsAccount->account_type = 'asset';
                $currentAssetsAccount->sub_type = 'current_assets';
                $currentAssetsAccount->parent_id = $assetsAccount->id;
                $currentAssetsAccount->description = 'حساب الأصول المتداولة';
                $currentAssetsAccount->is_active = true;
                $currentAssetsAccount->is_system = true;
                $currentAssetsAccount->opening_balance = 0;
                $currentAssetsAccount->current_balance = 0;
                $currentAssetsAccount->currency = 'SAR';
                $currentAssetsAccount->balance_type = 'debit';
                $currentAssetsAccount->is_cash_account = false;
                $currentAssetsAccount->is_bank_account = false;
                $currentAssetsAccount->level = 2;
                $currentAssetsAccount->is_parent = true;
                $currentAssetsAccount->save();
            }

            // إنشاء حساب المخزون
            $inventoryAccount = new ChartOfAccount();
            $inventoryAccount->company_id = $companyId;
            $inventoryAccount->account_code = '1300';
            $inventoryAccount->name = 'المخزون';
            $inventoryAccount->name_en = 'Inventory';
            $inventoryAccount->account_type = 'asset';
            $inventoryAccount->sub_type = 'inventory';
            $inventoryAccount->parent_id = $currentAssetsAccount->id;
            $inventoryAccount->description = 'حساب المخزون';
            $inventoryAccount->is_active = true;
            $inventoryAccount->is_system = true;
            $inventoryAccount->opening_balance = 0;
            $inventoryAccount->current_balance = 0;
            $inventoryAccount->currency = 'SAR';
            $inventoryAccount->balance_type = 'debit';
            $inventoryAccount->is_cash_account = false;
            $inventoryAccount->is_bank_account = false;
            $inventoryAccount->level = 3;
            $inventoryAccount->is_parent = false;
            $inventoryAccount->save();
        }

        return $inventoryAccount;
    }

    /**
     * الحصول على أو إنشاء حساب الدائنين (ذمم الموردين)
     *
     * @param int $companyId معرف الشركة
     * @param Supplier $supplier المورد
     * @return ChartOfAccount حساب الدائنين
     */
    private function getOrCreateAccountPayable($companyId, Supplier $supplier)
    {
        // البحث عن حساب الذمم الدائنة الرئيسي (2100)
        $mainAccountPayable = ChartOfAccount::where('company_id', $companyId)
            ->where('account_code', '2100')
            ->first();

        // إذا لم يوجد حساب الذمم الدائنة (2100)، نقوم بإنشائه
        if (!$mainAccountPayable) {
            // البحث عن حساب الخصوم
            $liabilitiesAccount = ChartOfAccount::where('account_code', '2000')
                ->where('company_id', $companyId)
                ->first();

            if (!$liabilitiesAccount) {
                // إنشاء حساب الخصوم الرئيسي
                $liabilitiesAccount = new ChartOfAccount();
                $liabilitiesAccount->company_id = $companyId;
                $liabilitiesAccount->account_code = '2000';
                $liabilitiesAccount->name = 'الخصوم';
                $liabilitiesAccount->name_en = 'Liabilities';
                $liabilitiesAccount->account_type = 'liability';
                $liabilitiesAccount->sub_type = 'liabilities';
                $liabilitiesAccount->parent_id = null;
                $liabilitiesAccount->description = 'حساب الخصوم الرئيسي';
                $liabilitiesAccount->is_active = true;
                $liabilitiesAccount->is_system = true;
                $liabilitiesAccount->opening_balance = 0;
                $liabilitiesAccount->current_balance = 0;
                $liabilitiesAccount->currency = 'SAR';
                $liabilitiesAccount->balance_type = 'credit';
                $liabilitiesAccount->is_cash_account = false;
                $liabilitiesAccount->is_bank_account = false;
                $liabilitiesAccount->level = 1;
                $liabilitiesAccount->is_parent = true;
                $liabilitiesAccount->save();
            }

            // إنشاء حساب الذمم الدائنة (2100) تحت حساب الخصوم
            $mainAccountPayable = new ChartOfAccount();
            $mainAccountPayable->company_id = $companyId;
            $mainAccountPayable->account_code = '2100';
            $mainAccountPayable->name = 'ذمم الموردين';
            $mainAccountPayable->name_en = 'Accounts Payable';
            $mainAccountPayable->account_type = 'liability';
            $mainAccountPayable->sub_type = 'accounts_payable';
            $mainAccountPayable->parent_id = $liabilitiesAccount->id;
            $mainAccountPayable->description = 'حساب ذمم الموردين الرئيسي';
            $mainAccountPayable->is_active = true;
            $mainAccountPayable->is_system = true;
            $mainAccountPayable->opening_balance = 0;
            $mainAccountPayable->current_balance = 0;
            $mainAccountPayable->currency = 'SAR';
            $mainAccountPayable->balance_type = 'credit';
            $mainAccountPayable->is_cash_account = false;
            $mainAccountPayable->is_bank_account = false;
            $mainAccountPayable->level = 2;
            $mainAccountPayable->is_parent = true;
            $mainAccountPayable->save();
        }

        // البحث عن حساب المورد تحت حساب الذمم الدائنة (2100)
        $supplierAccount = ChartOfAccount::where('company_id', $companyId)
            ->where('parent_id', $mainAccountPayable->id)
            ->where('name', 'like', '%' . $supplier->name . '%')
            ->first();

        // إنشاء حساب للمورد إذا لم يكن موجوداً
        if (!$supplierAccount) {
            // توليد رمز حساب فريد
            $lastAccountCode = ChartOfAccount::where('parent_id', $mainAccountPayable->id)
                ->orderBy('account_code', 'desc')
                ->value('account_code');

            $newAccountCode = $lastAccountCode ? (intval($lastAccountCode) + 1) : ($mainAccountPayable->account_code . '01');

            $supplierAccount = new ChartOfAccount();
            $supplierAccount->company_id = $companyId;
            $supplierAccount->account_code = $newAccountCode;
            $supplierAccount->name = 'حساب المورد: ' . $supplier->name;
            $supplierAccount->name_en = 'Supplier Account: ' . $supplier->name;
            $supplierAccount->account_type = 'liability';
            $supplierAccount->sub_type = 'supplier_payable';
            $supplierAccount->parent_id = $mainAccountPayable->id;
            $supplierAccount->description = 'حساب ذمم المورد: ' . $supplier->name;
            $supplierAccount->is_active = true;
            $supplierAccount->is_system = false;
            $supplierAccount->opening_balance = 0;
            $supplierAccount->current_balance = 0;
            $supplierAccount->currency = 'SAR';
            $supplierAccount->balance_type = 'credit';
            $supplierAccount->is_cash_account = false;
            $supplierAccount->is_bank_account = false;
            $supplierAccount->level = $mainAccountPayable->level + 1;
            $supplierAccount->is_parent = false;
            $supplierAccount->save();
        }

        return $supplierAccount;
    }

    /**
     * الحصول على أو إنشاء حساب ضريبة القيمة المضافة
     *
     * @param int $companyId معرف الشركة
     * @return ChartOfAccount حساب ضريبة القيمة المضافة
     */
    private function getOrCreateVatAccount($companyId)
    {
        // البحث عن حساب ضريبة القيمة المضافة المدخلة
        $vatAccount = ChartOfAccount::where('company_id', $companyId)
            ->where('account_type', 'asset')
            ->where('sub_type', 'vat_input')
            ->first();

        // إنشاء حساب ضريبة القيمة المضافة المدخلة إذا لم يكن موجوداً
        if (!$vatAccount) {
            // البحث عن حساب الأصول المتداولة
            $currentAssetsAccount = ChartOfAccount::where('account_code', '1100')
                ->where('company_id', $companyId)
                ->first();

            if (!$currentAssetsAccount) {
                // إذا لم يوجد حساب الأصول المتداولة، نبحث عن حساب الأصول
                $assetsAccount = ChartOfAccount::where('account_code', '1000')
                    ->where('company_id', $companyId)
                    ->first();

                if (!$assetsAccount) {
                    // إنشاء حساب الأصول الرئيسي
                    $assetsAccount = new ChartOfAccount();
                    $assetsAccount->company_id = $companyId;
                    $assetsAccount->account_code = '1000';
                    $assetsAccount->name = 'الأصول';
                    $assetsAccount->name_en = 'Assets';
                    $assetsAccount->account_type = 'asset';
                    $assetsAccount->sub_type = 'assets';
                    $assetsAccount->parent_id = null;
                    $assetsAccount->description = 'حساب الأصول الرئيسي';
                    $assetsAccount->is_active = true;
                    $assetsAccount->is_system = true;
                    $assetsAccount->opening_balance = 0;
                    $assetsAccount->current_balance = 0;
                    $assetsAccount->currency = 'SAR';
                    $assetsAccount->balance_type = 'debit';
                    $assetsAccount->is_cash_account = false;
                    $assetsAccount->is_bank_account = false;
                    $assetsAccount->level = 1;
                    $assetsAccount->is_parent = true;
                    $assetsAccount->save();
                }

                // إنشاء حساب الأصول المتداولة
                $currentAssetsAccount = new ChartOfAccount();
                $currentAssetsAccount->company_id = $companyId;
                $currentAssetsAccount->account_code = '1100';
                $currentAssetsAccount->name = 'الأصول المتداولة';
                $currentAssetsAccount->name_en = 'Current Assets';
                $currentAssetsAccount->account_type = 'asset';
                $currentAssetsAccount->sub_type = 'current_assets';
                $currentAssetsAccount->parent_id = $assetsAccount->id;
                $currentAssetsAccount->description = 'حساب الأصول المتداولة';
                $currentAssetsAccount->is_active = true;
                $currentAssetsAccount->is_system = true;
                $currentAssetsAccount->opening_balance = 0;
                $currentAssetsAccount->current_balance = 0;
                $currentAssetsAccount->currency = 'SAR';
                $currentAssetsAccount->balance_type = 'debit';
                $currentAssetsAccount->is_cash_account = false;
                $currentAssetsAccount->is_bank_account = false;
                $currentAssetsAccount->level = 2;
                $currentAssetsAccount->is_parent = true;
                $currentAssetsAccount->save();
            }

            // إنشاء حساب ضريبة القيمة المضافة المدخلة
            $vatAccount = new ChartOfAccount();
            $vatAccount->company_id = $companyId;
            $vatAccount->account_code = '1400';
            $vatAccount->name = 'ضريبة القيمة المضافة المدخلة';
            $vatAccount->name_en = 'VAT Input Tax';
            $vatAccount->account_type = 'asset';
            $vatAccount->sub_type = 'vat_input';
            $vatAccount->parent_id = $currentAssetsAccount->id;
            $vatAccount->description = 'حساب ضريبة القيمة المضافة المدخلة';
            $vatAccount->is_active = true;
            $vatAccount->is_system = true;
            $vatAccount->opening_balance = 0;
            $vatAccount->current_balance = 0;
            $vatAccount->currency = 'SAR';
            $vatAccount->balance_type = 'debit';
            $vatAccount->is_cash_account = false;
            $vatAccount->is_bank_account = false;
            $vatAccount->level = 3;
            $vatAccount->is_parent = false;
            $vatAccount->save();
        }

        return $vatAccount;
    }

    /**
     * تحديث القيد المحاسبي لمرتجع المشتريات
     *
     * @param PurchaseReturn $return مرتجع المشتريات
     * @return JournalEntry|null القيد المحاسبي أو null في حالة الفشل
     */
    public function updatePurchaseReturnJournalEntry(PurchaseReturn $return)
    {
        try {
            DB::beginTransaction();

            // البحث عن القيد المحاسبي الحالي للمرتجع
            $entry = JournalEntry::where('reference_type', 'App\Models\PurchaseReturn')
                ->where('reference_id', $return->id)
                ->first();

            // إذا لم يكن هناك قيد محاسبي، نقوم بإنشاء واحد جديد
            if (!$entry) {
                return $this->createPurchaseReturnJournalEntry($return);
            }

            // التحقق من أن القيد غير معتمد
            if ($entry->is_approved) {
                throw new \Exception('لا يمكن تحديث القيد المحاسبي لأنه معتمد');
            }

            // حذف بنود القيد الحالية
            $entry->items()->delete();

            // تحديث بيانات القيد
            $entry->entry_date = $return->return_date;
            $entry->description = 'قيد مرتجع مشتريات رقم: ' . $return->return_number;
            $entry->save();

            // إنشاء بنود القيد المحاسبي الجديدة
            $this->createPurchaseReturnJournalEntryItems($entry, $return);

            // ترحيل القيد المحاسبي
            $entry->post();

            DB::commit();

            return $entry;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('فشل في تحديث قيد محاسبي لمرتجع المشتريات: ' . $e->getMessage(), [
                'return_id' => $return->id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return null;
        }
    }
}
