<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Models\AccountLedger;
use App\Models\AccountTransfer;
use App\Models\OwnerTransaction;
use App\Models\UserAccount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class UserAccountController extends Controller
{
    public function index(Request $request)
    {
        $query = UserAccount::query()
            ->where('user_id', auth()->id());

        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('search')) {
            $search = trim($request->search);
            $query->where(function ($q) use ($search) {
                $q->where('name', 'like', "%{$search}%")
                    ->orWhere('account_number', 'like', "%{$search}%");
            });
        }

        $accounts = $query
            ->withSum('ledgers as total_debit', 'debit')
            ->withSum('ledgers as total_credit', 'credit')
            ->latest()
            ->paginate(12)
            ->withQueryString();

        $accounts->getCollection()->transform(function ($account) {
            $debit = (float) ($account->total_debit ?? 0);
            $credit = (float) ($account->total_credit ?? 0);
            $account->current_balance_calc = (float) $account->opening_balance + $debit - $credit;
            return $account;
        });

        $allAccounts = UserAccount::query()
            ->where('user_id', auth()->id())
            ->withSum('ledgers as total_debit', 'debit')
            ->withSum('ledgers as total_credit', 'credit')
            ->orderBy('name')
            ->get()
            ->map(function ($account) {
                $debit = (float) ($account->total_debit ?? 0);
                $credit = (float) ($account->total_credit ?? 0);
                $account->current_balance_calc = (float) $account->opening_balance + $debit - $credit;
                return $account;
            });

        $summary = [
            'total_accounts'    => $allAccounts->count(),
            'active_accounts'   => $allAccounts->where('status', 'active')->count(),
            'inactive_accounts' => $allAccounts->where('status', 'inactive')->count(),
            'total_balance'     => $allAccounts->sum('current_balance_calc'),
            'bank_balance'      => $allAccounts->where('type', 'bank')->sum('current_balance_calc'),
            'mfs_balance'       => $allAccounts->where('type', 'mfs')->sum('current_balance_calc'),
            'cash_balance'      => $allAccounts->where('type', 'cash')->sum('current_balance_calc'),
        ];

        return view('user.accounts.index', compact('accounts', 'summary', 'allAccounts'));
    }

    public function create()
    {
        return view('user.accounts.create');
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'name'            => ['required', 'string', 'max:255'],
            'account_number'  => ['nullable', 'string', 'max:255'],
            'type'            => ['required', 'in:bank,mfs,cash'],
            'opening_balance' => ['nullable', 'numeric', 'min:0'],
            'status'          => ['required', 'in:active,inactive'],
        ]);

        DB::transaction(function () use ($data) {
            $account = UserAccount::create([
                'user_id'         => auth()->id(),
                'name'            => $data['name'],
                'account_number'  => $data['account_number'] ?? null,
                'type'            => $data['type'],
                'opening_balance' => $data['opening_balance'] ?? 0,
                'status'          => $data['status'],
            ]);

            $this->syncOpeningBalanceOwnerTransaction($account);
        });

        return redirect()->route('user.accounts.index')
            ->with('ok', __('Account_Controller.messages.account_created_successfully'));
    }

    public function show($id)
    {
        $account = UserAccount::where('user_id', auth()->id())
            ->findOrFail($id);

        return redirect()->route('user.accounts.ledger.index', $account);
    }

    public function edit($id)
    {
        $account = UserAccount::where('user_id', auth()->id())
            ->findOrFail($id);

        return view('user.accounts.edit', compact('account'));
    }

    public function update(Request $request, $id)
    {
        $account = UserAccount::where('user_id', auth()->id())
            ->findOrFail($id);

        $data = $request->validate([
            'name'            => ['required', 'string', 'max:255'],
            'account_number'  => ['nullable', 'string', 'max:255'],
            'type'            => ['required', 'in:bank,mfs,cash'],
            'opening_balance' => ['nullable', 'numeric', 'min:0'],
            'status'          => ['required', 'in:active,inactive'],
        ]);

        DB::transaction(function () use ($data, $account) {
            $account->update([
                'name'            => $data['name'],
                'account_number'  => $data['account_number'] ?? null,
                'type'            => $data['type'],
                'opening_balance' => $data['opening_balance'] ?? 0,
                'status'          => $data['status'],
            ]);

            $this->syncOpeningBalanceOwnerTransaction($account);
        });

        return redirect()->route('user.accounts.index')
            ->with('ok', __('Account_Controller.messages.account_updated_successfully'));
    }

    public function destroy($id)
    {
        $account = UserAccount::where('user_id', auth()->id())
            ->findOrFail($id);

        $hasLedger = AccountLedger::where('user_id', auth()->id())
            ->where('user_account_id', $account->id)
            ->exists();

        $hasTransfer = AccountTransfer::where('user_id', auth()->id())
            ->where(function ($q) use ($account) {
                $q->where('from_account_id', $account->id)
                    ->orWhere('to_account_id', $account->id);
            })
            ->exists();

        if ($hasLedger || $hasTransfer) {
            return back()->with('err', __('Account_Controller.messages.account_delete_blocked'));
        }

        DB::transaction(function () use ($account) {
            $this->deleteOpeningBalanceOwnerTransaction($account);
            $account->delete();
        });

        return redirect()->route('user.accounts.index')
            ->with('ok', __('Account_Controller.messages.account_deleted_successfully'));
    }

    protected function syncOpeningBalanceOwnerTransaction(UserAccount $account): void
    {
        $openingBalance = (float) ($account->opening_balance ?? 0);

        $openingOwnerTx = OwnerTransaction::where('user_id', $account->user_id)
            ->where('user_account_id', $account->id)
            ->where('trx_no', $this->openingTrxNo($account))
            ->first();

        if ($openingBalance > 0) {
            if ($openingOwnerTx) {
                $openingOwnerTx->update([
                    'type' => 'investment',
                    'amount' => $openingBalance,
                    'note' => __('Account_Controller.messages.opening_balance_capital_for_account') . $account->name,
                    'posted_at' => $openingOwnerTx->posted_at ?? now(),
                ]);
            } else {
                OwnerTransaction::create([
                    'user_id' => $account->user_id,
                    'user_account_id' => $account->id,
                    'type' => 'investment',
                    'trx_no' => $this->openingTrxNo($account),
                    'amount' => $openingBalance,
                    'note' => __('Account_Controller.messages.opening_balance_capital_for_account') . $account->name,
                    'posted_at' => now(),
                ]);
            }
            return;
        }

        if ($openingOwnerTx) {
            $openingOwnerTx->delete();
        }
    }

    protected function deleteOpeningBalanceOwnerTransaction(UserAccount $account): void
    {
        OwnerTransaction::where('user_id', $account->user_id)
            ->where('user_account_id', $account->id)
            ->where('trx_no', $this->openingTrxNo($account))
            ->delete();
    }

    protected function openingTrxNo(UserAccount $account): string
    {
        return 'OPEN-ACC-' . $account->id;
    }
}