<?php

namespace App\Http\Controllers;

use App\Customer;
use App\DpsAccount;
use App\DpsInstallment;
use App\DpsWithdrawal;
use App\DpsPayment;
use App\BankAccount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class DpsAccountController extends Controller
{
     public function index(Request $request)
    {
        $query = DpsAccount::with('customer')->latest();

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

        if ($request->dps_id) {
            $query->where('id', $request->dps_id);
        }

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

        if ($request->from_date && $request->to_date) {
            $query->whereBetween('start_date', [$request->from_date, $request->to_date]);
        } elseif ($request->from_date) {
            $query->where('start_date', '>=', $request->from_date);
        } elseif ($request->to_date) {
            $query->where('start_date', '<=', $request->to_date);
        }

        $dpsAccounts = $query->paginate(20)->appends($request->all());
        $customers = Customer::all(); 

        return view('pages.dps.index', compact('dpsAccounts', 'customers'));
    }


    /**
     * Show create DPS form
     */
    public function create()
    {
        $customers = Customer::orderBy('name')->get();
        return view('pages.dps.create', compact('customers'));
    }

    /**
     * Store DPS Account
     */
   public function store(Request $request)
    {
        // Validate input
        $request->validate([
            'customer_id'      => 'required|exists:customers,id',
            'monthly_amount'   => 'required|numeric|min:1',
            'duration_months'  => 'required|integer|min:1',
            'interest_rate'    => 'required|numeric|min:0',
            'interest_type'    => 'required|in:daily,weekly,monthly',
            'start_date'       => 'required|date',
        ]);

        DB::transaction(function () use ($request) {

            $startDate = \Carbon\Carbon::parse($request->start_date);
            $totalDeposit = $request->monthly_amount * $request->duration_months;
            $interestAmount = ($totalDeposit * $request->interest_rate) / 100;

            $dps = DpsAccount::create([
                'customer_id'     => $request->customer_id,
                'monthly_amount'  => $request->monthly_amount,
                'duration_months' => $request->duration_months,
                'interest_rate'   => $request->interest_rate,
                'interest_type'   => $request->interest_type,
                'start_date'      => $startDate,
                'maturity_date'   => $startDate->copy()->addMonths($request->duration_months), // approximate maturity
                'total_deposit'   => $totalDeposit,
                'interest_amount' => $interestAmount,
                'maturity_amount' => $totalDeposit + $interestAmount,
            ]);

            // Generate installments
            $installmentDate = $startDate->copy();
            for ($i = 0; $i < $request->duration_months; $i++) {

                DpsInstallment::create([
                    'dps_account_id'  => $dps->id,
                    'installment_date'=> $installmentDate,
                    'amount'          => $request->monthly_amount,
                    'remaining_amount'=> $request->monthly_amount, // for partial payments
                ]);

                if ($request->interest_type == 'daily') {
                    $installmentDate->addDay();
                } elseif ($request->interest_type == 'weekly') {
                    $installmentDate->addWeek();
                } else { // monthly
                    $installmentDate->addMonth();
                }
            }
        });

        return redirect()->route('dps.index')
            ->with('success', 'DPS account created successfully.');
    }


    /**
     * Show DPS details
     */
   public function show($id)
    {
        $dps = DpsAccount::with('customer', 'installments')->findOrFail($id);
        $totalInstallments = $dps->installments->count();
        $totalRemaining = $dps->installments->sum('remaining_amount');
        $totalPaid = $dps->installments->sum('amount') - $totalRemaining;

        return view('pages.dps.show', compact('dps', 'totalInstallments', 'totalPaid', 'totalRemaining'));
    }

    public function installments($id)
    {
        $dps = DpsAccount::with(['customer', 'installments.payments.bankAccount'])->findOrFail($id);
        return view('pages.dps.installments', compact('dps'));
    }

    /**
     * Pay an installment
     */

    public function collect(Request $request, $installmentId)
    {
        $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'paid_date' => 'required|date',
            'bank_account_id' => 'required|exists:bank_accounts,id',
        ]);

        DB::transaction(function () use ($request, $installmentId) {

            $paymentAmount = $request->amount;

            $installment = DpsInstallment::findOrFail($installmentId);

            $bank = BankAccount::findOrFail($request->bank_account_id);

            // Get all unpaid installments in order
            $unpaidInstallments = DpsInstallment::where('dps_account_id', $installment->dps_account_id)
                ->where('remaining_amount', '>', 0)
                ->orderBy('installment_date')
                ->get();

            foreach ($unpaidInstallments as $inst) {

                if ($paymentAmount <= 0) break;

                $remaining = $inst->remaining_amount;

                if ($paymentAmount >= $remaining) {
                    // Pay full installment
                    $inst->remaining_amount = 0;
                    $inst->is_paid = 1;
                    $pay = $remaining;
                } else {
                    // Partial payment
                    $inst->remaining_amount -= $paymentAmount;
                    $pay = $paymentAmount;
                }

                $inst->paid_at = $request->paid_date;
                $inst->save();

                // Create DPS payment record
                DpsPayment::create([
                    'dps_installment_id' => $inst->id,
                    'amount' => $pay,
                    'paid_at' => $request->paid_date,
                    'bank_account_id' => $bank->id,
                    'user_id' => auth()->id(),
                ]);

                // Update bank balance
                $bank->current_balance += $pay;

                // Subtract from total payment amount
                $paymentAmount -= $pay;
            }

            $bank->save();
        });

        return redirect()->back()->with('success', 'Payment applied successfully!');
    }

    public function deleteDpsPayment($paymentId)
    {
        DB::transaction(function () use ($paymentId) {

            $payment = DpsPayment::findOrFail($paymentId);
            $installment = DpsInstallment::findOrFail($payment->dps_installment_id);
            $bankAccount = BankAccount::findOrFail($payment->bank_account_id);
            $bankAccount->current_balance -= $payment->amount;
            $bankAccount->save();
            $installment->remaining_amount += $payment->amount;
            $installment->is_paid = 0;
            $installment->paid_at = null;
            $installment->save();
            $payment->delete();
        });

        return back()->with('success', 'DPS payment deleted and bank balance updated.');
    }


    /**
     * Close / Mature DPS
     */
    public function close(DpsAccount $dps)
    {
        // if ($dps->status !== 'closed') {
        //     return back()->with('error', 'DPS already closed or withdrawn.');
        // }

        $dps->update([
            'status' => 'closed',
        ]);

        return back()->with('success', 'DPS closed successfully.');
    }


    public function report(Request $request)
    {
        $query = DpsAccount::with('customer');

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

        if ($request->from_date && $request->to_date) {
            $query->whereBetween('start_date', [
                $request->from_date,
                $request->to_date
            ]);
        }

        $dpsAccounts = $query->get();

        $totalDeposit = $dpsAccounts->sum('total_deposit');

        return view('pages.dps.report', compact('dpsAccounts', 'totalDeposit'));
    }


    public function withdrawForm($id)
    {
        $dps = DpsAccount::with('installments', 'customer')->findOrFail($id);

        if ($dps->status !== 'closed') {
            return redirect()->route('dps.show', $id)
                ->with('error', 'DPS already closed or withdrawn.');
        }

        $paidAmount = $dps->installments->sum('amount')
            - $dps->installments->sum('remaining_amount');

        $isMatured = now()->gte($dps->maturity_date);
        $interest = $isMatured ? $dps->interest_amount : 0;

        return view('pages.dps.withdraw', compact(
            'dps',
            'paidAmount',
            'interest',
            'isMatured'
        ));
    }


    public function withdraw(Request $request, $dpsId)
    {
        $request->validate([
            'withdraw_date' => 'required|date',
            'bank_account_id' => 'required|exists:bank_accounts,id',
        ]);

        $dps = DpsAccount::with('installments')->findOrFail($dpsId);

        if ($dps->status !== 'closed') {
            return back()->with('error', 'DPS already withdrawn or closed.');
        }

        $paidAmount = $dps->installments
            ->where('remaining_amount', 0)
            ->sum('amount');

        if ($paidAmount <= 0) {
            return back()->with('error', 'No paid installments found.');
        }

        $isMatured = now()->gte($dps->maturity_date);

        if ($isMatured) {
            $interest = $dps->interest_amount;
            $penalty = 0;
            $type = 'maturity';
        } else {
            $interest = 0;
            $penalty = $paidAmount * 0.05; // 5% penalty example
            $type = 'early';
        }

        $withdrawAmount = $paidAmount + $interest - $penalty;

        DB::transaction(function () use ($dps, $paidAmount, $interest, $penalty, $withdrawAmount, $request, $type) {

            DpsWithdrawal::create([
                'dps_account_id' => $dps->id,
                'paid_amount' => $paidAmount,
                'interest_amount' => $interest,
                'penalty_amount' => $penalty,
                'withdraw_amount' => $withdrawAmount,
                'withdraw_date' => $request->withdraw_date,
                'type' => $type,
                'bank_account_id' => $request->bank_account_id,
            ]);

            $bankAccount = BankAccount::findOrFail($request->bank_account_id);
            $bankAccount->current_balance -= $withdrawAmount;
            $bankAccount->save();

            $dps->update([
                'status' => 'withdrawn',
            ]);
        });

        return redirect()->route('dps.show', $dps->id)
            ->with('success', 'DPS withdrawn successfully.');
    }


    public function installmentsReport(Request $request)
    {
        $interestType = $request->query('interest_type');
        $customerId = $request->query('customer_id');

        $installments = DpsInstallment::with('dpsAccount.customer')
            ->where('is_paid', false)
            ->whereHas('dpsAccount', function ($query) use ($interestType, $customerId) {
                if ($interestType) {
                    $query->where('interest_type', $interestType);
                }
                if ($customerId) {
                    $query->where('customer_id', $customerId);
                }
                // Exclude closed DPS accounts from report
                $query->where('status', '!=', 'closed');
            })
            ->orderBy('installment_date', 'asc')
            ->get();

        $customers = \App\Customer::orderBy('name')->get();

        return view('pages.dps.installments_report', compact('installments', 'interestType', 'customers', 'customerId'));
    }


}
