<?php

namespace App\Http\Controllers;

use App\Models\ChartOfAccount;
use App\Models\FiscalYear;
use App\Models\AccountingPeriod;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\FinancialStatementExport;

class FinancialStatementController extends Controller
{
    /**
     * عرض قائمة الدخل
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function incomeStatement(Request $request)
    {
        $companyId = Auth::user()->company_id;

        // الحصول على السنوات المالية
        $fiscalYears = FiscalYear::where('company_id', $companyId)
            ->orderBy('start_date', 'desc')
            ->get();

        $fiscalYearId = $request->input('fiscal_year_id', $fiscalYears->where('is_active', true)->first()->id ?? null);
        $startDate = $request->input('start_date');
        $endDate = $request->input('end_date');

        // إذا تم تحديد سنة مالية، نحصل على الفترات المحاسبية الخاصة بها
        $accountingPeriods = [];
        if ($fiscalYearId) {
            $accountingPeriods = AccountingPeriod::where('fiscal_year_id', $fiscalYearId)
                ->orderBy('start_date')
                ->get();

            $accountingPeriodId = $request->input('accounting_period_id');

            // إذا تم تحديد فترة محاسبية، نستخدم تواريخها
            if ($accountingPeriodId) {
                $period = $accountingPeriods->where('id', $accountingPeriodId)->first();
                if ($period) {
                    $startDate = $period->start_date;
                    $endDate = $period->end_date;
                }
            }
            // إذا لم يتم تحديد فترة محاسبية أو تواريخ، نستخدم تواريخ السنة المالية
            elseif (!$startDate || !$endDate) {
                $fiscalYear = $fiscalYears->where('id', $fiscalYearId)->first();
                if ($fiscalYear) {
                    $startDate = $fiscalYear->start_date;
                    $endDate = $fiscalYear->end_date;
                }
            }
        }

        // الحصول على بيانات قائمة الدخل
        $revenues = [];
        $expenses = [];
        $totalRevenue = 0;
        $totalExpense = 0;

        if ($startDate && $endDate) {
            // تحويل التواريخ إلى كائنات Carbon إذا كانت نصوص
            if (is_string($startDate)) {
                $startDate = \Carbon\Carbon::parse($startDate);
            }

            if (is_string($endDate)) {
                $endDate = \Carbon\Carbon::parse($endDate);
            }

            // الإيرادات
            $revenues = ChartOfAccount::where('company_id', $companyId)
                ->where('account_type', 'revenue')
                ->where('is_active', true)
                ->get()
                ->map(function ($account) use ($startDate, $endDate, &$totalRevenue) {
                    $movement = $account->getMovementBetweenDates($startDate, $endDate);
                    $balance = $movement['credit'] - $movement['debit']; // الإيرادات تزيد بالدائن
                    $totalRevenue += $balance;

                    return [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'balance' => $balance,
                        'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                    ];
                })
                ->filter(function ($account) {
                    return $account['balance'] != 0;
                })
                ->sortBy('code')
                ->values()
                ->toArray();

            // المصروفات
            $expenses = ChartOfAccount::where('company_id', $companyId)
                ->where('account_type', 'expense')
                ->where('is_active', true)
                ->get()
                ->map(function ($account) use ($startDate, $endDate, &$totalExpense) {
                    $movement = $account->getMovementBetweenDates($startDate, $endDate);
                    $balance = $movement['debit'] - $movement['credit']; // المصروفات تزيد بالمدين
                    $totalExpense += $balance;

                    return [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'balance' => $balance,
                        'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                    ];
                })
                ->filter(function ($account) {
                    return $account['balance'] != 0;
                })
                ->sortBy('code')
                ->values()
                ->toArray();
        }

        $netIncome = $totalRevenue - $totalExpense;

        return view('accounting.financial_statements.income_statement', compact(
            'fiscalYears',
            'fiscalYearId',
            'accountingPeriods',
            'startDate',
            'endDate',
            'revenues',
            'expenses',
            'totalRevenue',
            'totalExpense',
            'netIncome'
        ));
    }

    /**
     * عرض الميزانية العمومية
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function balanceSheet(Request $request)
    {
        $companyId = Auth::user()->company_id;

        // الحصول على التاريخ
        $date = $request->input('date', now()->format('Y-m-d'));

        // تحويل التاريخ إلى كائن Carbon إذا كان نص
        if (is_string($date)) {
            $date = \Carbon\Carbon::parse($date);
        }

        // الحصول على بيانات الميزانية العمومية
        $assets = [];
        $liabilities = [];
        $equity = [];
        $totalAssets = 0;
        $totalLiabilities = 0;
        $totalEquity = 0;

        // الأصول
        $assets = ChartOfAccount::where('company_id', $companyId)
            ->where('account_type', 'asset')
            ->where('is_active', true)
            ->get()
            ->map(function ($account) use ($date, &$totalAssets) {
                $balance = $account->getBalanceAtDate($date);
                $totalAssets += $balance;

                return [
                    'id' => $account->id,
                    'code' => $account->account_code,
                    'name' => $account->name,
                    'balance' => $balance,
                    'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                ];
            })
            ->filter(function ($account) {
                return $account['balance'] != 0;
            })
            ->sortBy('code')
            ->values()
            ->toArray();

        // الخصوم
        $liabilities = ChartOfAccount::where('company_id', $companyId)
            ->where('account_type', 'liability')
            ->where('is_active', true)
            ->get()
            ->map(function ($account) use ($date, &$totalLiabilities) {
                $balance = $account->getBalanceAtDate($date);
                $totalLiabilities += $balance;

                return [
                    'id' => $account->id,
                    'code' => $account->account_code,
                    'name' => $account->name,
                    'balance' => $balance,
                    'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                ];
            })
            ->filter(function ($account) {
                return $account['balance'] != 0;
            })
            ->sortBy('code')
            ->values()
            ->toArray();

        // حقوق الملكية
        $equity = ChartOfAccount::where('company_id', $companyId)
            ->where('account_type', 'equity')
            ->where('is_active', true)
            ->get()
            ->map(function ($account) use ($date, &$totalEquity) {
                $balance = $account->getBalanceAtDate($date);
                $totalEquity += $balance;

                return [
                    'id' => $account->id,
                    'code' => $account->account_code,
                    'name' => $account->name,
                    'balance' => $balance,
                    'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                ];
            })
            ->filter(function ($account) {
                return $account['balance'] != 0;
            })
            ->sortBy('code')
            ->values()
            ->toArray();

        return view('accounting.financial_statements.balance_sheet', compact(
            'date',
            'assets',
            'liabilities',
            'equity',
            'totalAssets',
            'totalLiabilities',
            'totalEquity'
        ));
    }

    /**
     * عرض قائمة التدفقات النقدية
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function cashFlow(Request $request)
    {
        $companyId = Auth::user()->company_id;

        // الحصول على السنوات المالية
        $fiscalYears = FiscalYear::where('company_id', $companyId)
            ->orderBy('start_date', 'desc')
            ->get();

        $fiscalYearId = $request->input('fiscal_year_id', $fiscalYears->where('is_active', true)->first()->id ?? null);
        $startDate = $request->input('start_date');
        $endDate = $request->input('end_date');

        // إذا تم تحديد سنة مالية، نحصل على الفترات المحاسبية الخاصة بها
        $accountingPeriods = [];
        if ($fiscalYearId) {
            $accountingPeriods = AccountingPeriod::where('fiscal_year_id', $fiscalYearId)
                ->orderBy('start_date')
                ->get();

            $accountingPeriodId = $request->input('accounting_period_id');

            // إذا تم تحديد فترة محاسبية، نستخدم تواريخها
            if ($accountingPeriodId) {
                $period = $accountingPeriods->where('id', $accountingPeriodId)->first();
                if ($period) {
                    $startDate = $period->start_date;
                    $endDate = $period->end_date;
                }
            }
            // إذا لم يتم تحديد فترة محاسبية أو تواريخ، نستخدم تواريخ السنة المالية
            elseif (!$startDate || !$endDate) {
                $fiscalYear = $fiscalYears->where('id', $fiscalYearId)->first();
                if ($fiscalYear) {
                    $startDate = $fiscalYear->start_date;
                    $endDate = $fiscalYear->end_date;
                }
            }
        }

        // الحصول على بيانات التدفقات النقدية
        $operatingActivities = [];
        $investingActivities = [];
        $financingActivities = [];
        $totalOperating = 0;
        $totalInvesting = 0;
        $totalFinancing = 0;
        $openingCashBalance = 0;
        $closingCashBalance = 0;

        if ($startDate && $endDate) {
            // تحويل التواريخ إلى كائنات Carbon إذا كانت نصوص
            if (is_string($startDate)) {
                $startDate = \Carbon\Carbon::parse($startDate);
            }

            if (is_string($endDate)) {
                $endDate = \Carbon\Carbon::parse($endDate);
            }

            // حسابات النقدية والبنوك
            $cashAccounts = ChartOfAccount::where('company_id', $companyId)
                ->where(function ($query) {
                    $query->where('is_cash_account', true)
                        ->orWhere('is_bank_account', true);
                })
                ->where('is_active', true)
                ->get();

            // الحصول على الرصيد الافتتاحي والختامي للنقدية

            foreach ($cashAccounts as $account) {
                $openingCashBalance += $account->getBalanceAtDate($startDate);
                $closingCashBalance += $account->getBalanceAtDate($endDate);
            }

            // حساب صافي التغير في النقدية
            $netCashChange = $closingCashBalance - $openingCashBalance;

            // الأنشطة التشغيلية (الإيرادات والمصروفات)
            $operatingAccounts = ChartOfAccount::where('company_id', $companyId)
                ->whereIn('account_type', ['revenue', 'expense'])
                ->where('is_active', true)
                ->get();

            foreach ($operatingAccounts as $account) {
                $movement = $account->getMovementBetweenDates($startDate, $endDate);
                $balance = 0;

                if ($account->account_type == 'revenue') {
                    $balance = $movement['credit'] - $movement['debit']; // الإيرادات تزيد بالدائن
                    $totalOperating += $balance;
                } else {
                    $balance = - ($movement['debit'] - $movement['credit']); // المصروفات تزيد بالمدين (نضع إشارة سالب)
                    $totalOperating += $balance;
                }

                if ($balance != 0) {
                    $operatingActivities[] = [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'balance' => $balance,
                        'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                    ];
                }
            }

            // الأنشطة الاستثمارية (الأصول طويلة الأجل)
            $investingAccounts = ChartOfAccount::where('company_id', $companyId)
                ->where('account_type', 'asset')
                ->where('sub_type', 'non_current')
                ->where('is_active', true)
                ->get();

            foreach ($investingAccounts as $account) {
                $movement = $account->getMovementBetweenDates($startDate, $endDate);
                $balance = - ($movement['debit'] - $movement['credit']); // الزيادة في الأصول تمثل تدفق نقدي خارج (سالب)
                $totalInvesting += $balance;

                if ($balance != 0) {
                    $investingActivities[] = [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'balance' => $balance,
                        'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                    ];
                }
            }

            // الأنشطة التمويلية (الخصوم طويلة الأجل وحقوق الملكية)
            $financingAccounts = ChartOfAccount::where('company_id', $companyId)
                ->where(function ($query) {
                    $query->where('account_type', 'liability')
                        ->where('sub_type', 'non_current')
                        ->orWhere('account_type', 'equity');
                })
                ->where('is_active', true)
                ->get();

            foreach ($financingAccounts as $account) {
                $movement = $account->getMovementBetweenDates($startDate, $endDate);
                $balance = $movement['credit'] - $movement['debit']; // الزيادة في الخصوم وحقوق الملكية تمثل تدفق نقدي داخل (موجب)
                $totalFinancing += $balance;

                if ($balance != 0) {
                    $financingActivities[] = [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'balance' => $balance,
                        'formatted_balance' => number_format($balance, 2) . ' ' . $account->currency
                    ];
                }
            }
        }

        $totalCashFlow = $totalOperating + $totalInvesting + $totalFinancing;

        return view('accounting.financial_statements.cash_flow', compact(
            'fiscalYears',
            'fiscalYearId',
            'accountingPeriods',
            'startDate',
            'endDate',
            'operatingActivities',
            'investingActivities',
            'financingActivities',
            'totalOperating',
            'totalInvesting',
            'totalFinancing',
            'totalCashFlow',
            'openingCashBalance',
            'closingCashBalance'
        ));
    }

    /**
     * عرض قائمة التغيرات في حقوق الملكية
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function equityChanges(Request $request)
    {
        $companyId = Auth::user()->company_id;

        // الحصول على السنوات المالية
        $fiscalYears = FiscalYear::where('company_id', $companyId)
            ->orderBy('start_date', 'desc')
            ->get();

        $fiscalYearId = $request->input('fiscal_year_id', $fiscalYears->where('is_active', true)->first()->id ?? null);

        // إذا تم تحديد سنة مالية، نحصل على تواريخها
        $startDate = null;
        $endDate = null;
        $fiscalYear = null;

        if ($fiscalYearId) {
            $fiscalYear = $fiscalYears->where('id', $fiscalYearId)->first();
            if ($fiscalYear) {
                $startDate = $fiscalYear->start_date;
                $endDate = $fiscalYear->end_date;
            }
        }

        // الحصول على بيانات حقوق الملكية
        $equityAccounts = [];
        $totalOpeningBalance = 0;
        $totalChanges = 0;
        $totalClosingBalance = 0;

        if ($startDate && $endDate) {
            $equityAccounts = ChartOfAccount::where('company_id', $companyId)
                ->where('account_type', 'equity')
                ->where('is_active', true)
                ->get()
                ->map(function ($account) use ($startDate, $endDate, &$totalOpeningBalance, &$totalChanges, &$totalClosingBalance) {
                    $openingBalance = $account->getBalanceAtDate($startDate);
                    $closingBalance = $account->getBalanceAtDate($endDate);
                    $changes = $closingBalance - $openingBalance;

                    $totalOpeningBalance += $openingBalance;
                    $totalChanges += $changes;
                    $totalClosingBalance += $closingBalance;

                    return [
                        'id' => $account->id,
                        'code' => $account->account_code,
                        'name' => $account->name,
                        'opening_balance' => $openingBalance,
                        'changes' => $changes,
                        'closing_balance' => $closingBalance,
                        'formatted_opening_balance' => number_format($openingBalance, 2) . ' ' . $account->currency,
                        'formatted_changes' => number_format($changes, 2) . ' ' . $account->currency,
                        'formatted_closing_balance' => number_format($closingBalance, 2) . ' ' . $account->currency
                    ];
                })
                ->filter(function ($account) {
                    return $account['opening_balance'] != 0 || $account['changes'] != 0 || $account['closing_balance'] != 0;
                })
                ->sortBy('code')
                ->values()
                ->toArray();
        }

        return view('accounting.financial_statements.equity_changes', compact(
            'fiscalYears',
            'fiscalYearId',
            'fiscalYear',
            'equityAccounts',
            'totalOpeningBalance',
            'totalChanges',
            'totalClosingBalance'
        ));
    }

    /**
     * تصدير التقارير المالية
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function export(Request $request)
    {
        $type = $request->input('type');
        $data = $request->except('_token', 'type');

        switch ($type) {
            case 'income_statement':
                return Excel::download(new FinancialStatementExport('income_statement', $data), 'income_statement.xlsx');
            case 'balance_sheet':
                return Excel::download(new FinancialStatementExport('balance_sheet', $data), 'balance_sheet.xlsx');
            case 'cash_flow':
                return Excel::download(new FinancialStatementExport('cash_flow', $data), 'cash_flow.xlsx');
            case 'equity_changes':
                return Excel::download(new FinancialStatementExport('equity_changes', $data), 'equity_changes.xlsx');
            default:
                return redirect()->back()->with('error', 'نوع التقرير غير صالح');
        }
    }
}
