<?php

namespace App\Http\Controllers;

use App\Models\JournalEntry;
use App\Models\JournalEntryItem;
use App\Models\ChartOfAccount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class JournalEntryController extends Controller
{
    /**
     * জার্নাল এন্ট্রির তালিকা প্রদর্শন
     */
    public function index(Request $request)
    {
        $query = JournalEntry::with(['createdBy', 'items.chartOfAccount']);
        
        if ($request->filled('from_date')) {
            $query->where('entry_date', '>=', $request->from_date);
        }
        
        if ($request->filled('to_date')) {
            $query->where('entry_date', '<=', $request->to_date);
        }
        
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }
        
        if ($request->filled('voucher_no')) {
            $query->where('voucher_no', 'like', '%' . $request->voucher_no . '%');
        }
        
        $entries = $query->orderBy('entry_date', 'desc')
            ->orderBy('created_at', 'desc')
            ->paginate(20);
            
        $totalEntries = JournalEntry::count();
        $totalPosted = JournalEntry::posted()->count();
        
        return view('accounting.journal-entries.index', compact(
            'entries', 'totalEntries', 'totalPosted'
        ));
    }

    /**
     * নতুন জার্নাল এন্ট্রি তৈরির ফর্ম প্রদর্শন
     */
    public function create()
    {
        $accounts = ChartOfAccount::active()
            ->orderBy('code')
            ->get()
            ->groupBy('type');
            
        $voucherNo = 'JV-' . date('Ymd') . '-' . str_pad(
            JournalEntry::whereDate('created_at', today())->count() + 1, 
            3, '0', STR_PAD_LEFT
        );
        
        return view('accounting.journal-entries.create', compact('accounts', 'voucherNo'));
    }

    /**
     * নতুন জার্নাল এন্ট্রি সংরক্ষণ
     */
    public function store(Request $request)
    {
        $request->validate([
            'entry_date' => 'required|date',
            'voucher_no' => 'required|unique:journal_entries,voucher_no',
            'narration' => 'nullable|max:1000',
            'items' => 'required|array|min:2',
            'items.*.chart_of_account_id' => 'required|exists:chart_of_accounts,id',
            'items.*.debit' => 'required_without:items.*.credit|numeric|min:0',
            'items.*.credit' => 'required_without:items.*.debit|numeric|min:0',
            'items.*.description' => 'nullable|max:500'
        ]);

        try {
            DB::beginTransaction();
            
            $totalDebit = 0;
            $totalCredit = 0;
            
            foreach ($request->items as $item) {
                $totalDebit += $item['debit'] ?? 0;
                $totalCredit += $item['credit'] ?? 0;
            }
            
            if ($totalDebit != $totalCredit) {
                return back()->with('error', 'ডেবিট এবং ক্রেডিট সমান হতে হবে। ডেবিট: ' . $totalDebit . ', ক্রেডিট: ' . $totalCredit);
            }
            
            $entry = JournalEntry::create([
                'entry_date' => $request->entry_date,
                'voucher_no' => $request->voucher_no,
                'reference_no' => $request->reference_no,
                'narration' => $request->narration,
                'total_debit' => $totalDebit,
                'total_credit' => $totalCredit,
                'status' => $request->has('post_now') ? 'posted' : 'draft',
                'created_by' => auth()->id(),
                'posted_by' => $request->has('post_now') ? auth()->id() : null,
                'posted_at' => $request->has('post_now') ? now() : null
            ]);
            
            foreach ($request->items as $item) {
                if (($item['debit'] ?? 0) > 0 || ($item['credit'] ?? 0) > 0) {
                    JournalEntryItem::create([
                        'journal_entry_id' => $entry->id,
                        'chart_of_account_id' => $item['chart_of_account_id'],
                        'debit' => $item['debit'] ?? 0,
                        'credit' => $item['credit'] ?? 0,
                        'description' => $item['description'] ?? null
                    ]);
                    
                    // Update account balance if posted
                    if ($request->has('post_now')) {
                        $this->updateAccountBalance(
                            $item['chart_of_account_id'],
                            $item['debit'] ?? 0,
                            $item['credit'] ?? 0
                        );
                    }
                }
            }
            
            DB::commit();
            
            $message = $request->has('post_now') 
                ? 'জার্নাল এন্ট্রি সফলভাবে পোস্ট হয়েছে।' 
                : 'জার্নাল এন্ট্রি সফলভাবে ড্রাফট হিসেবে সংরক্ষণ হয়েছে।';
                
            return redirect()->route('accounting.journal.index')
                ->with('success', $message);
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'জার্নাল এন্ট্রি সংরক্ষণ করতে সমস্যা হয়েছে: ' . $e->getMessage());
        }
    }

    /**
     * জার্নাল এন্ট্রি প্রদর্শন
     */
    public function show(JournalEntry $journalEntry)
    {
        $journalEntry->load(['items.chartOfAccount', 'createdBy', 'postedBy']);
        
        return view('accounting.journal-entries.show', compact('journalEntry'));
    }

    /**
     * জার্নাল এন্ট্রি সম্পাদনার ফর্ম প্রদর্শন
     */
    public function edit(JournalEntry $journalEntry)
    {
        if ($journalEntry->isPosted()) {
            return back()->with('error', 'পোস্ট করা জার্নাল এন্ট্রি সম্পাদনা করা যাবে না।');
        }
        
        $accounts = ChartOfAccount::active()
            ->orderBy('code')
            ->get()
            ->groupBy('type');
            
        $journalEntry->load('items');
        
        return view('accounting.journal-entries.edit', compact('journalEntry', 'accounts'));
    }

    /**
     * জার্নাল এন্ট্রি আপডেট
     */
    public function update(Request $request, JournalEntry $journalEntry)
    {
        if ($journalEntry->isPosted()) {
            return back()->with('error', 'পোস্ট করা জার্নাল এন্ট্রি আপডেট করা যাবে না।');
        }
        
        $request->validate([
            'entry_date' => 'required|date',
            'narration' => 'nullable|max:1000',
            'items' => 'required|array|min:2',
            'items.*.chart_of_account_id' => 'required|exists:chart_of_accounts,id',
            'items.*.debit' => 'required_without:items.*.credit|numeric|min:0',
            'items.*.credit' => 'required_without:items.*.debit|numeric|min:0',
            'items.*.description' => 'nullable|max:500'
        ]);

        try {
            DB::beginTransaction();
            
            $totalDebit = 0;
            $totalCredit = 0;
            
            foreach ($request->items as $item) {
                $totalDebit += $item['debit'] ?? 0;
                $totalCredit += $item['credit'] ?? 0;
            }
            
            if ($totalDebit != $totalCredit) {
                return back()->with('error', 'ডেবিট এবং ক্রেডিট সমান হতে হবে। ডেবিট: ' . $totalDebit . ', ক্রেডিট: ' . $totalCredit);
            }
            
            $journalEntry->update([
                'entry_date' => $request->entry_date,
                'reference_no' => $request->reference_no,
                'narration' => $request->narration,
                'total_debit' => $totalDebit,
                'total_credit' => $totalCredit,
                'status' => $request->has('post_now') ? 'posted' : 'draft',
                'posted_by' => $request->has('post_now') ? auth()->id() : null,
                'posted_at' => $request->has('post_now') ? now() : null
            ]);
            
            // Delete old items
            $journalEntry->items()->delete();
            
            // Create new items
            foreach ($request->items as $item) {
                if (($item['debit'] ?? 0) > 0 || ($item['credit'] ?? 0) > 0) {
                    JournalEntryItem::create([
                        'journal_entry_id' => $journalEntry->id,
                        'chart_of_account_id' => $item['chart_of_account_id'],
                        'debit' => $item['debit'] ?? 0,
                        'credit' => $item['credit'] ?? 0,
                        'description' => $item['description'] ?? null
                    ]);
                    
                    // Update account balance if posted
                    if ($request->has('post_now')) {
                        $this->updateAccountBalance(
                            $item['chart_of_account_id'],
                            $item['debit'] ?? 0,
                            $item['credit'] ?? 0
                        );
                    }
                }
            }
            
            DB::commit();
            
            $message = $request->has('post_now') 
                ? 'জার্নাল এন্ট্রি সফলভাবে পোস্ট হয়েছে।' 
                : 'জার্নাল এন্ট্রি সফলভাবে আপডেট হয়েছে।';
                
            return redirect()->route('accounting.journal.index')
                ->with('success', $message);
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'জার্নাল এন্ট্রি আপডেট করতে সমস্যা হয়েছে: ' . $e->getMessage());
        }
    }

    /**
     * জার্নাল এন্ট্রি ডিলিট
     */
    public function destroy(JournalEntry $journalEntry)
    {
        if ($journalEntry->isPosted()) {
            return back()->with('error', 'পোস্ট করা জার্নাল এন্ট্রি ডিলিট করা যাবে না।');
        }
        
        try {
            $journalEntry->delete();
            
            return redirect()->route('accounting.journal.index')
                ->with('success', 'জার্নাল এন্ট্রি সফলভাবে ডিলিট হয়েছে।');
                
        } catch (\Exception $e) {
            return back()->with('error', 'জার্নাল এন্ট্রি ডিলিট করতে সমস্যা হয়েছে: ' . $e->getMessage());
        }
    }

    /**
     * জার্নাল এন্ট্রি পোস্ট
     */
    public function post(JournalEntry $journalEntry)
    {
        if ($journalEntry->isPosted()) {
            return back()->with('error', 'এই জার্নাল এন্ট্রি ইতিমধ্যে পোস্ট করা হয়েছে।');
        }
        
        try {
            DB::beginTransaction();
            
            $journalEntry->update([
                'status' => 'posted',
                'posted_by' => auth()->id(),
                'posted_at' => now()
            ]);
            
            // Update account balances
            foreach ($journalEntry->items as $item) {
                $this->updateAccountBalance(
                    $item->chart_of_account_id,
                    $item->debit,
                    $item->credit
                );
            }
            
            DB::commit();
            
            return back()->with('success', 'জার্নাল এন্ট্রি সফলভাবে পোস্ট হয়েছে।');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'জার্নাল এন্ট্রি পোস্ট করতে সমস্যা হয়েছে: ' . $e->getMessage());
        }
    }

    /**
     * জার্নাল এন্ট্রি আনপোস্ট
     */
    public function unpost(JournalEntry $journalEntry)
    {
        if (!$journalEntry->isPosted()) {
            return back()->with('error', 'এই জার্নাল এন্ট্রি পোস্ট করা হয়নি।');
        }
        
        try {
            DB::beginTransaction();
            
            // Reverse account balances
            foreach ($journalEntry->items as $item) {
                $this->updateAccountBalance(
                    $item->chart_of_account_id,
                    $item->credit, // Reverse: debit becomes credit
                    $item->debit   // Reverse: credit becomes debit
                );
            }
            
            $journalEntry->update([
                'status' => 'draft',
                'posted_by' => null,
                'posted_at' => null
            ]);
            
            DB::commit();
            
            return back()->with('success', 'জার্নাল এন্ট্রি সফলভাবে আনপোস্ট হয়েছে।');
                
        } catch (\Exception $e) {
            DB::rollBack();
            return back()->with('error', 'জার্নাল এন্ট্রি আনপোস্ট করতে সমস্যা হয়েছে: ' . $e->getMessage());
        }
    }

    /**
     * জার্নাল এন্ট্রি প্রিন্ট
     */
    public function print(JournalEntry $journalEntry)
    {
        $journalEntry->load(['items.chartOfAccount', 'createdBy', 'postedBy']);
        
        return view('accounting.journal-entries.print', compact('journalEntry'));
    }

    /**
     * ডে বুক রিপোর্ট
     */
    public function dayBook(Request $request)
    {
        $date = $request->get('date', now()->format('Y-m-d'));
        
        $entries = JournalEntry::with(['items.chartOfAccount', 'createdBy'])
            ->where('entry_date', $date)
            ->where('status', 'posted')
            ->orderBy('created_at')
            ->get();
            
        $totalDebit = $entries->sum('total_debit');
        $totalCredit = $entries->sum('total_credit');
        
        return view('accounting.journal-entries.day-book', compact(
            'entries', 'totalDebit', 'totalCredit', 'date'
        ));
    }

    /**
     * ক্যাশ বুক রিপোর্ট
     */
    public function cashBook(Request $request)
    {
        $fromDate = $request->get('from_date', now()->startOfMonth()->format('Y-m-d'));
        $toDate = $request->get('to_date', now()->format('Y-m-d'));
        
        // Find cash account
        $cashAccount = ChartOfAccount::where('code', 'like', '1001%')->first();
        
        if (!$cashAccount) {
            return back()->with('error', 'ক্যাশ অ্যাকাউন্ট খুঁজে পাওয়া যায়নি।');
        }
        
        return redirect()->route('accounting.coa.ledger', [
            'chartOfAccount' => $cashAccount->id,
            'from_date' => $fromDate,
            'to_date' => $toDate
        ]);
    }

    /**
     * ব্যাংক বুক রিপোর্ট
     */
    public function bankBook(Request $request)
    {
        $fromDate = $request->get('from_date', now()->startOfMonth()->format('Y-m-d'));
        $toDate = $request->get('to_date', now()->format('Y-m-d'));
        
        // Find bank accounts
        $bankAccounts = ChartOfAccount::where('code', 'like', '1002%')->get();
        
        if ($bankAccounts->isEmpty()) {
            return back()->with('error', 'ব্যাংক অ্যাকাউন্ট খুঁজে পাওয়া যায়নি।');
        }
        
        return view('accounting.journal-entries.bank-book', compact(
            'bankAccounts', 'fromDate', 'toDate'
        ));
    }

    /**
     * অ্যাকাউন্ট ব্যালেন্স আপডেট হেল্পার
     */
    private function updateAccountBalance($accountId, $debit, $credit)
    {
        $account = ChartOfAccount::find($accountId);
        
        if (!$account) return;
        
        if ($account->type == 'asset' || $account->type == 'expense') {
            // Assets and expenses: debit increases, credit decreases
            $account->current_balance += $debit;
            $account->current_balance -= $credit;
        } else {
            // Liabilities, equity, and income: credit increases, debit decreases
            $account->current_balance -= $debit;
            $account->current_balance += $credit;
        }
        
        $account->save();
    }
}