<?php

namespace App\Services;

use App\Models\Invoice;
use App\Models\MaintenanceContract;
use App\Models\InvoiceTemplate;
use App\Models\TaxReport;
use App\Models\Customer;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class InvoiceService
{
    /**
     * إنشاء فواتير تلقائية من عقود الصيانة
     *
     * @param string|null $specificDate تاريخ محدد لإنشاء الفواتير (Y-m-d)
     * @return array نتائج العملية
     */
    public function generateInvoicesFromContracts($specificDate = null)
    {
        $today = $specificDate ? Carbon::parse($specificDate) : Carbon::today();
        $results = [
            'success' => 0,
            'failed' => 0,
            'skipped' => 0,
            'invoices' => [],
        ];

        // البحث عن العقود النشطة
        $contracts = MaintenanceContract::where('status', 'active')
            ->where('start_date', '<=', $today)
            ->where('end_date', '>=', $today)
            ->get();

        foreach ($contracts as $contract) {
            // التحقق من دورة الفوترة وما إذا كان يجب إنشاء فاتورة اليوم
            $shouldCreateInvoice = $this->shouldCreateInvoiceToday($contract, $today);

            if (!$shouldCreateInvoice) {
                $results['skipped']++;
                continue;
            }

            try {
                DB::beginTransaction();

                $invoice = Invoice::generateFromContract($contract, $today->format('Y-m-d'));

                // إذا كان العقد متكرر، نجعل الفاتورة متكررة أيضاً
                if ($contract->billing_cycle !== 'one_time') {
                    $invoice->makeRecurring($contract->billing_cycle);
                }

                DB::commit();

                $results['success']++;
                $results['invoices'][] = [
                    'id' => $invoice->id,
                    'invoice_number' => $invoice->invoice_number,
                    'customer' => $invoice->customer->name,
                    'amount' => $invoice->total_amount,
                ];
            } catch (\Exception $e) {
                DB::rollBack();
                $results['failed']++;
                \Log::error('فشل إنشاء فاتورة للعقد #' . $contract->id . ': ' . $e->getMessage());
            }
        }

        return $results;
    }

    /**
     * التحقق مما إذا كان يجب إنشاء فاتورة اليوم لهذا العقد
     *
     * @param MaintenanceContract $contract
     * @param Carbon $today
     * @return bool
     */
    protected function shouldCreateInvoiceToday($contract, $today)
    {
        // الحصول على آخر فاتورة لهذا العقد
        $lastInvoice = $contract->invoices()->latest('invoice_date')->first();

        if (!$lastInvoice) {
            // لم يتم إنشاء فواتير سابقة، نتحقق إذا كان اليوم هو تاريخ بدء العقد
            return $contract->start_date->format('Y-m-d') === $today->format('Y-m-d');
        }

        // تحديد الفترة بناءً على دورة الفوترة
        $nextBillingDate = null;

        switch ($contract->billing_cycle) {
            case 'monthly':
                $nextBillingDate = Carbon::parse($lastInvoice->invoice_date)->addMonth();
                break;
            case 'quarterly':
                $nextBillingDate = Carbon::parse($lastInvoice->invoice_date)->addMonths(3);
                break;
            case 'semi_annually':
                $nextBillingDate = Carbon::parse($lastInvoice->invoice_date)->addMonths(6);
                break;
            case 'annually':
                $nextBillingDate = Carbon::parse($lastInvoice->invoice_date)->addYear();
                break;
            default:
                return false; // عقد لمرة واحدة
        }

        // التحقق إذا كان اليوم هو تاريخ الفوترة التالي
        return $nextBillingDate->format('Y-m-d') === $today->format('Y-m-d');
    }

    /**
     * إنشاء الفواتير المتكررة المستحقة
     *
     * @return array نتائج العملية
     */
    public function generateRecurringInvoices()
    {
        $today = Carbon::today();
        $results = [
            'success' => 0,
            'failed' => 0,
            'invoices' => [],
        ];

        // البحث عن الفواتير المتكررة التي حان موعد إنشاء نسخة جديدة منها
        $recurringInvoices = Invoice::where('is_recurring', true)
            ->whereDate('next_recurring_date', '<=', $today)
            ->get();

        foreach ($recurringInvoices as $invoice) {
            try {
                DB::beginTransaction();

                $newInvoice = $invoice->generateNextRecurringInvoice();

                if ($newInvoice) {
                    $results['success']++;
                    $results['invoices'][] = [
                        'id' => $newInvoice->id,
                        'invoice_number' => $newInvoice->invoice_number,
                        'customer' => $newInvoice->customer->name,
                        'amount' => $newInvoice->total_amount,
                    ];
                }

                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();
                $results['failed']++;
                \Log::error('فشل إنشاء فاتورة متكررة من الفاتورة #' . $invoice->id . ': ' . $e->getMessage());
            }
        }

        return $results;
    }

    /**
     * تحديث حالة الفواتير (المتأخرة، المدفوعة جزئياً، إلخ)
     *
     * @return array نتائج العملية
     */
    public function updateInvoiceStatuses()
    {
        $today = Carbon::today();
        $results = [
            'updated' => 0,
            'overdue' => 0,
            'partially_paid' => 0,
            'paid' => 0,
        ];

        // البحث عن الفواتير التي تحتاج إلى تحديث حالتها
        $invoices = Invoice::whereNotIn('status', ['paid', 'cancelled'])
            ->get();

        foreach ($invoices as $invoice) {
            $oldStatus = $invoice->status;
            $newStatus = $oldStatus;

            // التحقق من حالة الدفع
            if ($invoice->due_amount <= 0) {
                $newStatus = 'paid';
                $results['paid']++;
            } elseif ($invoice->paid_amount > 0) {
                $newStatus = 'partially_paid';
                $results['partially_paid']++;
            } elseif ($invoice->due_date < $today && $invoice->status !== 'overdue') {
                $newStatus = 'overdue';
                $results['overdue']++;
            }

            // تحديث الحالة إذا تغيرت
            if ($newStatus !== $oldStatus) {
                $invoice->status = $newStatus;
                $invoice->save();
                $results['updated']++;
            }
        }

        return $results;
    }

    /**
     * إنشاء تقرير ضريبة القيمة المضافة
     *
     * @param int $companyId
     * @param string $startDate (Y-m-d)
     * @param string $endDate (Y-m-d)
     * @return TaxReport
     */
    public function generateTaxReport($companyId, $startDate, $endDate)
    {
        $startDate = Carbon::parse($startDate)->startOfDay();
        $endDate = Carbon::parse($endDate)->endOfDay();

        // حساب إجمالي الضرائب المحصلة من الفواتير
        $totalTaxCollected = Invoice::where('company_id', $companyId)
            ->whereBetween('invoice_date', [$startDate, $endDate])
            ->sum('tax_amount');

        // يمكن إضافة حساب الضرائب المدفوعة (على المشتريات) إذا كان هناك نظام مشتريات
        $totalTaxPaid = 0;

        // حساب صافي الضريبة
        $netTax = $totalTaxCollected - $totalTaxPaid;

        // إنشاء رقم التقرير
        $reportNumber = 'TAX-' . $companyId . '-' . $startDate->format('Ymd') . '-' . $endDate->format('Ymd');

        // إنشاء تقرير الضريبة
        $taxReport = TaxReport::create([
            'company_id' => $companyId,
            'report_number' => $reportNumber,
            'start_date' => $startDate,
            'end_date' => $endDate,
            'total_tax_collected' => $totalTaxCollected,
            'total_tax_paid' => $totalTaxPaid,
            'net_tax' => $netTax,
            'status' => 'draft',
            'notes' => 'تقرير ضريبة القيمة المضافة للفترة من ' . $startDate->format('Y-m-d') . ' إلى ' . $endDate->format('Y-m-d'),
            'created_by' => auth()->id(),
        ]);

        return $taxReport;
    }

    /**
     * إنشاء كشف حساب للعميل
     *
     * @param int $customerId
     * @param string $startDate (Y-m-d)
     * @param string $endDate (Y-m-d)
     * @return array بيانات كشف الحساب
     */
    public function generateCustomerStatement($customerId, $startDate, $endDate)
    {
        $startDate = Carbon::parse($startDate)->startOfDay();
        $endDate = Carbon::parse($endDate)->endOfDay();
        $customer = Customer::findOrFail($customerId);

        // طريقة جديدة: استخدام جدول customer_statements مباشرة
        // الحصول على آخر رصيد قبل تاريخ البداية
        $lastStatement = DB::table('customer_statements')
            ->where('customer_id', $customerId)
            ->where('transaction_date', '<', $startDate)
            ->orderBy('transaction_date', 'desc')
            ->orderBy('id', 'desc')
            ->first();

        // تحديد الرصيد الافتتاحي
        $openingBalance = $lastStatement ? $lastStatement->balance : 0;

        // الحصول على جميع المعاملات خلال الفترة من جدول customer_statements
        $statements = DB::table('customer_statements')
            ->where('customer_id', $customerId)
            ->whereBetween('transaction_date', [$startDate, $endDate])
            ->orderBy('transaction_date')
            ->orderBy('id')
            ->get();

        // إنشاء سجل المعاملات
        $transactions = [];
        $balance = $openingBalance;

        // إضافة الرصيد الافتتاحي
        $transactions[] = [
            'date' => $startDate->format('Y-m-d'),
            'type' => 'opening_balance',
            'description' => 'الرصيد الافتتاحي',
            'reference' => '',
            'debit' => $openingBalance > 0 ? $openingBalance : 0,
            'credit' => $openingBalance < 0 ? abs($openingBalance) : 0,
            'balance' => $balance,
        ];

        // إضافة المعاملات من جدول customer_statements
        $totalDebit = 0;
        $totalCredit = 0;

        foreach ($statements as $stmt) {
            // تحديث الرصيد
            $balance = $stmt->balance;

            // تحديد نوع المعاملة
            $type = 'other';
            if (strpos($stmt->reference_type, 'Invoice') !== false) {
                $type = 'invoice';
            } elseif (strpos($stmt->reference_type, 'Payment') !== false) {
                $type = 'payment';
            } elseif (strpos($stmt->reference_type, 'JournalEntry') !== false) {
                $type = 'journal_entry';
            }

            $transactions[] = [
                'date' => Carbon::parse($stmt->transaction_date)->format('Y-m-d'),
                'type' => $type,
                'description' => $stmt->description,
                'reference' => $stmt->reference_number,
                'debit' => $stmt->debit,
                'credit' => $stmt->credit,
                'balance' => $stmt->balance,
            ];

            $totalDebit += $stmt->debit;
            $totalCredit += $stmt->credit;
        }

        // في حالة عدم وجود معاملات، نستخدم الطريقة القديمة
        if (count($statements) == 0) {
            // الحصول على الفواتير خلال الفترة
            $invoices = Invoice::where('customer_id', $customerId)
                ->whereBetween('invoice_date', [$startDate, $endDate])
                ->orderBy('invoice_date')
                ->get();

            // الحصول على المدفوعات خلال الفترة
            $payments = DB::table('payments')
                ->join('invoices', 'payments.invoice_id', '=', 'invoices.id')
                ->where('invoices.customer_id', $customerId)
                ->whereBetween('payments.payment_date', [$startDate, $endDate])
                ->select('payments.*', 'invoices.invoice_number')
                ->orderBy('payments.payment_date')
                ->get();

            // إضافة الفواتير
            foreach ($invoices as $invoice) {
                $balance += $invoice->total_amount;
                $transactions[] = [
                    'date' => $invoice->invoice_date->format('Y-m-d'),
                    'type' => 'invoice',
                    'description' => 'فاتورة رقم ' . $invoice->invoice_number,
                    'reference' => $invoice->invoice_number,
                    'debit' => $invoice->total_amount,
                    'credit' => 0,
                    'balance' => $balance,
                ];
                $totalDebit += $invoice->total_amount;
            }

            // إضافة المدفوعات
            foreach ($payments as $payment) {
                $balance -= $payment->amount;
                $transactions[] = [
                    'date' => Carbon::parse($payment->payment_date)->format('Y-m-d'),
                    'type' => 'payment',
                    'description' => 'دفعة للفاتورة رقم ' . $payment->invoice_number,
                    'reference' => $payment->reference_number,
                    'debit' => 0,
                    'credit' => $payment->amount,
                    'balance' => $balance,
                ];
                $totalCredit += $payment->amount;
            }
        }

        // ترتيب المعاملات حسب التاريخ
        usort($transactions, function ($a, $b) {
            $dateCompare = strcmp($a['date'], $b['date']);
            if ($dateCompare === 0) {
                // إذا كان التاريخ متطابق، نرتب حسب النوع (الفواتير أولاً ثم القيود ثم المدفوعات)
                $typeOrder = ['opening_balance' => 0, 'invoice' => 1, 'journal_entry' => 2, 'payment' => 3, 'other' => 4];
                return $typeOrder[$a['type']] - $typeOrder[$b['type']];
            }
            return $dateCompare;
        });

        // الرصيد الختامي هو آخر رصيد في المعاملات
        $closingBalance = count($transactions) > 0 ? end($transactions)['balance'] : $openingBalance;

        // إنشاء كشف الحساب
        $statement = [
            'customer' => [
                'id' => $customer->id,
                'name' => $customer->name,
                'address' => $customer->address,
                'phone' => $customer->phone,
                'email' => $customer->email,
            ],
            'period' => [
                'start_date' => $startDate->format('Y-m-d'),
                'end_date' => $endDate->format('Y-m-d'),
            ],
            'opening_balance' => $openingBalance,
            'closing_balance' => $closingBalance,
            'transactions' => $transactions,
            'summary' => [
                'total_invoiced' => $totalDebit,
                'total_paid' => $totalCredit,
                'balance_due' => $closingBalance,
            ],
        ];

        return $statement;
    }

    /**
     * إنشاء تقرير الإيرادات والمصروفات
     *
     * @param int $companyId
     * @param string $startDate (Y-m-d)
     * @param string $endDate (Y-m-d)
     * @return array بيانات التقرير
     */
    public function generateIncomeExpenseReport($companyId, $startDate, $endDate)
    {
        $startDate = Carbon::parse($startDate)->startOfDay();
        $endDate = Carbon::parse($endDate)->endOfDay();

        // حساب الإيرادات (مجموع الفواتير)
        $totalInvoiced = Invoice::where('company_id', $companyId)
            ->whereBetween('invoice_date', [$startDate, $endDate])
            ->sum('total_amount');

        $totalPaid = DB::table('payments')
            ->where('company_id', $companyId)
            ->whereBetween('payment_date', [$startDate, $endDate])
            ->sum('amount');

        // يمكن إضافة حساب المصروفات إذا كان هناك نظام مصروفات
        $totalExpenses = 0;

        // حساب صافي الدخل
        $netIncome = $totalPaid - $totalExpenses;

        // إنشاء التقرير
        $report = [
            'period' => [
                'start_date' => $startDate->format('Y-m-d'),
                'end_date' => $endDate->format('Y-m-d'),
            ],
            'income' => [
                'total_invoiced' => $totalInvoiced,
                'total_paid' => $totalPaid,
                'details' => [
                    // يمكن إضافة تفاصيل الإيرادات حسب النوع أو العميل
                ],
            ],
            'expenses' => [
                'total' => $totalExpenses,
                'details' => [
                    // يمكن إضافة تفاصيل المصروفات حسب النوع
                ],
            ],
            'summary' => [
                'net_income' => $netIncome,
                'profit_margin' => $totalPaid > 0 ? ($netIncome / $totalPaid) * 100 : 0,
            ],
        ];

        return $report;
    }

    /**
     * إنشاء تقرير الربحية حسب العميل
     *
     * @param int $companyId
     * @param string $startDate (Y-m-d)
     * @param string $endDate (Y-m-d)
     * @return array بيانات التقرير
     */
    public function generateProfitabilityByCustomerReport($companyId, $startDate, $endDate)
    {
        $startDate = Carbon::parse($startDate)->startOfDay();
        $endDate = Carbon::parse($endDate)->endOfDay();

        // الحصول على العملاء مع إجمالي الفواتير والمدفوعات
        $customers = Customer::where('company_id', $companyId)
            ->withCount(['invoices' => function ($query) use ($startDate, $endDate) {
                $query->whereBetween('invoice_date', [$startDate, $endDate]);
            }])
            ->withSum(['invoices' => function ($query) use ($startDate, $endDate) {
                $query->whereBetween('invoice_date', [$startDate, $endDate]);
            }], 'total_amount')
            ->get();

        $customerData = [];

        foreach ($customers as $customer) {
            // حساب إجمالي المدفوعات لهذا العميل
            $totalPaid = DB::table('payments')
                ->join('invoices', 'payments.invoice_id', '=', 'invoices.id')
                ->where('invoices.customer_id', $customer->id)
                ->whereBetween('payments.payment_date', [$startDate, $endDate])
                ->sum('payments.amount');

            // يمكن إضافة حساب التكاليف المباشرة لهذا العميل إذا كان هناك نظام تكاليف
            $directCosts = 0;

            // حساب الربحية
            $profit = $totalPaid - $directCosts;
            $profitMargin = $totalPaid > 0 ? ($profit / $totalPaid) * 100 : 0;

            $customerData[] = [
                'customer_id' => $customer->id,
                'customer_name' => $customer->name,
                'invoices_count' => $customer->invoices_count,
                'total_invoiced' => $customer->invoices_sum_total_amount ?? 0,
                'total_paid' => $totalPaid,
                'direct_costs' => $directCosts,
                'profit' => $profit,
                'profit_margin' => $profitMargin,
            ];
        }

        // ترتيب العملاء حسب الربحية (تنازلياً)
        usort($customerData, function ($a, $b) {
            return $b['profit'] - $a['profit'];
        });

        // إنشاء التقرير
        $report = [
            'period' => [
                'start_date' => $startDate->format('Y-m-d'),
                'end_date' => $endDate->format('Y-m-d'),
            ],
            'customers' => $customerData,
            'summary' => [
                'total_customers' => count($customerData),
                'total_invoiced' => array_sum(array_column($customerData, 'total_invoiced')),
                'total_paid' => array_sum(array_column($customerData, 'total_paid')),
                'total_profit' => array_sum(array_column($customerData, 'profit')),
                'average_profit_margin' => array_sum(array_column($customerData, 'profit_margin')) / (count($customerData) ?: 1),
            ],
        ];

        return $report;
    }
}
