<?php

namespace App\Http\Controllers;

use App\Models\Loan;
use App\Models\LoanDeposit;
use App\Models\LoanInstallment;
use App\Models\WithdrawRequest;
use App\Models\LoanAmountOption;
use App\Models\LoanTenureOption;
use App\Models\LoanPurpose;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

use App\Services\DepositCalculator;

class LoanController extends Controller
{
    protected function getAmountOptions(): array
    {
        $fromDb = LoanAmountOption::active()
            ->orderBy('sort_order')
            ->orderBy('amount')
            ->pluck('amount')
            ->toArray();

        return !empty($fromDb)
            ? $fromDb
            : [5000, 10000, 15000, 20000, 30000, 50000];
    }

    protected function getTenureOptions(): array
    {
        $fromDb = LoanTenureOption::active()
            ->orderBy('sort_order')
            ->orderBy('months')
            ->pluck('months')
            ->toArray();

        return !empty($fromDb)
            ? $fromDb
            : [3, 6, 9, 12];
    }

    protected function getPurposes(): array
    {
        $fromDb = LoanPurpose::active()
            ->orderBy('sort_order')
            ->pluck('label_bn', 'key')
            ->toArray();

        return !empty($fromDb)
            ? $fromDb
            : [
                'business' => 'ব্যবসা',
                'study'    => 'পড়াশোনা',
                'home'     => 'বাড়ি',
                'other'    => 'অন্যান্য',
            ];
    }

    public function create()
    {
        $user = Auth::user();
        if (!$user) {
            abort(401);
        }

        $baseAmountOptions = $this->getAmountOptions();
        $tenureOptions     = $this->getTenureOptions();
        $purposes          = $this->getPurposes();

        $loanLimit      = !empty($user->loan_limit) ? (int) $user->loan_limit : null;
        $amountOptions  = $baseAmountOptions;
        $availableLimit = null;

        if (!is_null($loanLimit) && $loanLimit > 0) {
            $usedAmount = Loan::where('user_id', $user->id)
                ->whereIn('status', [
                    'draft',
                    'summary_confirmed',
                    'nid_uploaded',
                    'pending_deposit',
                    'pending_approval',
                    'running',
                ])
                ->sum('amount');

            $availableLimit = max($loanLimit - $usedAmount, 0);

            if ($availableLimit > 0) {
                $amountOptions = array_filter($baseAmountOptions, function ($amount) use ($availableLimit) {
                    return $amount <= $availableLimit;
                });

                if (empty($amountOptions)) {
                    $amountOptions = [$availableLimit];
                }
            } else {
                $amountOptions = [];
            }
        }

        return view('frontend.loan.apply', compact(
            'amountOptions',
            'tenureOptions',
            'purposes',
            'loanLimit',
            'availableLimit'
        ));
    }

    public function store(Request $request)
    {
        $user = Auth::user();
        if (!$user) {
            abort(401);
        }

        $baseAmountOptions = $this->getAmountOptions();
        $tenureOptions     = $this->getTenureOptions();
        $purposes          = $this->getPurposes();
        $purposeKeys       = array_keys($purposes);

        $loanLimit = !empty($user->loan_limit) ? (int) $user->loan_limit : null;

        $usedAmount = Loan::where('user_id', $user->id)
            ->whereIn('status', [
                'draft',
                'summary_confirmed',
                'nid_uploaded',
                'pending_deposit',
                'pending_approval',
                'running',
            ])
            ->sum('amount');

        $availableLimit = !is_null($loanLimit) && $loanLimit > 0
            ? max($loanLimit - $usedAmount, 0)
            : null;

        $rules = [
            'nominee_name'     => ['required', 'string', 'max:255'],
            'nominee_phone'    => ['required', 'string', 'max:20'],
            'nominee_relation' => ['required', 'string', 'max:100'],
            'amount'           => ['required', 'integer', 'in:' . implode(',', $baseAmountOptions)],
            'tenure_months'    => ['required', 'integer', 'in:' . implode(',', $tenureOptions)],
            'purpose'          => ['required', 'string', Rule::in($purposeKeys)],
        ];

        if (!is_null($availableLimit)) {
            $rules['amount'][] = 'max:' . $availableLimit;
        }

        $messages = [
            'nominee_name.required'     => 'নমিনির নাম দিন।',
            'nominee_phone.required'    => 'নমিনির ফোন নম্বর দিন।',
            'nominee_relation.required' => 'নমিনির সাথে সম্পর্ক লিখুন।',
        ];

        if (!is_null($availableLimit)) {
            $messages['amount.max'] =
                'আপনি সর্বোচ্চ ' . number_format($availableLimit) .
                ' টাকা পর্যন্ত লোন নিতে পারবেন (আপনার limit: ' . number_format($loanLimit) . ' BDT).';
        }

        $validated = $request->validate($rules, $messages);

        if (!is_null($availableLimit) && $validated['amount'] > $availableLimit) {
            return back()->withErrors([
                'amount' =>
                    'আপনি সর্বোচ্চ ' . number_format($availableLimit) .
                    ' টাকা পর্যন্ত লোন নিতে পারবেন (limit: ' . number_format($loanLimit) . ' BDT).',
            ])->withInput();
        }

        // logged-in user এর users table এ nominee info save/update
        $user->update([
            'nominee_name'     => $validated['nominee_name'],
            'nominee_phone'    => $validated['nominee_phone'],
            'nominee_relation' => $validated['nominee_relation'],
        ]);

        $interestRate  = 5;
        $amount        = (int) $validated['amount'];
        $months        = (int) $validated['tenure_months'];
        $interest      = (int) floor($amount * $interestRate / 100);
        $totalPayable  = $amount + $interest;
        $monthlyAmount = (int) round($totalPayable / $months);

        $loan = Loan::create([
            'user_id'             => $user->id,
            'amount'              => $amount,
            'tenure_months'       => $months,
            'purpose'             => $validated['purpose'],
            'interest_rate'       => $interestRate,
            'total_payable'       => $totalPayable,
            'monthly_installment' => $monthlyAmount,
            'status'              => 'draft',
        ]);

        $firstDate = Carbon::now()->addMonth()->startOfDay();

        for ($i = 0; $i < $months; $i++) {
            $due = (clone $firstDate)->addMonths($i);

            LoanInstallment::create([
                'loan_id'        => $loan->id,
                'due_date'       => $due->toDateString(),
                'amount'         => $monthlyAmount,
                'principal_part' => (int) floor($amount / $months),
                'interest_part'  => (int) floor($interest / $months),
            ]);
        }

        return redirect()->route('loan.summary', $loan);
    }

    public function summary(Loan $loan)
    {
        $this->authorizeLoan($loan);

        $installments = $loan->installments()->orderBy('due_date')->get();

        return view('frontend.loan.summary', compact('loan', 'installments'));
    }

    public function confirmSummary(Loan $loan)
    {
        $this->authorizeLoan($loan);

        $loan->update(['status' => 'summary_confirmed']);

        return redirect()->route('loan.nid', $loan);
    }

    public function nidForm(Loan $loan)
    {
        $this->authorizeLoan($loan);

        $depositAmount = DepositCalculator::calculate($loan->amount);

        return view('frontend.loan.nid', compact('loan', 'depositAmount'));
    }

    public function nidUpload(Request $request, Loan $loan)
    {
        $this->authorizeLoan($loan);

        $request->validate([
            'nid_front' => ['required', 'image', 'max:2048'],
            'nid_back'  => ['required', 'image', 'max:2048'],
        ]);

        $frontPath = $request->file('nid_front')->store('nid', 'public');
        $backPath  = $request->file('nid_back')->store('nid', 'public');

        $loan->update([
            'nid_front_path' => $frontPath,
            'nid_back_path'  => $backPath,
            'status'         => 'nid_uploaded',
        ]);

        return redirect()->route('loan.deposit.method', $loan);
    }

    public function transactions()
    {
        $userId = Auth::id();

        $pendingDeposits = LoanDeposit::whereHas('loan', function ($q) use ($userId) {
                $q->where('user_id', $userId);
            })
            ->where('status', 'pending')
            ->latest()
            ->get();

        $approvedDeposits = LoanDeposit::whereHas('loan', function ($q) use ($userId) {
                $q->where('user_id', $userId);
            })
            ->where('status', 'approved')
            ->latest()
            ->get();

        $pendingWithdraws = WithdrawRequest::where('user_id', $userId)
            ->where('status', 'pending')
            ->latest()
            ->get();

        $approvedWithdraws = WithdrawRequest::where('user_id', $userId)
            ->where('status', 'approved')
            ->latest()
            ->get();

        $pendingLoans = Loan::where('user_id', $userId)
            ->whereIn('status', [
                'draft',
                'summary_confirmed',
                'nid_uploaded',
                'pending_deposit',
                'pending_approval',
            ])
            ->latest()
            ->get();

        $runningLoans = Loan::where('user_id', $userId)
            ->where('status', 'running')
            ->latest()
            ->get();

        return view('frontend.loan.transactions', compact(
            'pendingDeposits',
            'approvedDeposits',
            'pendingWithdraws',
            'approvedWithdraws',
            'pendingLoans',
            'runningLoans'
        ));
    }

    public function myLoans()
    {
        $loans = Loan::with(['installments', 'deposits'])
            ->where('user_id', Auth::id())
            ->orderByDesc('created_at')
            ->get();

        return view('frontend.loan.my-loans', compact('loans'));
    }

    protected function authorizeLoan(Loan $loan)
    {
         
    }
}