<?php

namespace App\Http\Controllers;

use App\Models\Admission;
use App\Models\Classe;
use App\Models\Student;
use App\Models\Student_collect_fee;
use App\Models\Student_collect_fee_detail;
use App\Models\Student_fee_detail;
use App\Models\Transaction;
use App\Models\Transaction_detail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Barryvdh\DomPDF\Facade\Pdf;

class FeeReciptController extends Controller
{
    public function show()
    {
        $stdList = Student::select('head_code', 'student_name', 'reg_no','status')->get();
        return view('stdFeeRecipt.feeReciptForm',compact('stdList'));
    }

    public function index(Request $request)
    {
        $stdList = Student::select('head_code', 'student_name', 'reg_no')->where('status', 'active')->get();
        $classList = Classe::select('id', 'name')->get();
        $query = Student_collect_fee::with(['student', 'collectFeeDetail', 'class', 'section'])
            ->orderBy('id', 'desc');


        if ($request->filled('search')) {
            $query->where(function ($q) use ($request) {
                $q->where('reg_no', 'like', '%' . $request->search . '%')
                    ->orWhere('head_code', 'like', '%' . $request->search . '%')
                    ->orWhere('class_id', 'like', '%' . $request->search . '%');
            });
        }

        if ($request->filled('class_search')) {
            $query->where(function ($q) use ($request) {
                $q->where('class_id', $request->class_search);
            });
        }


        $fees = $query->paginate($request->get('entries', 40)); // default to 10

        if ($request->ajax()) {
            return view('stdFeeRecipt.partialFeeRecipt', compact('fees'))->render();
        }

        return view('stdFeeRecipt.feeReciptReport', compact('fees', 'stdList', 'classList'));
    }


    public function pdfFeeReciptReport(Request $request)
    {
        $query = Student_collect_fee::with(['student', 'collectFeeDetail', 'class', 'section'])->orderBy('id', 'desc');

        if ($request->filled('search')) {
            $query->where(function ($q) use ($request) {
                $q->where('reg_no', 'like', '%' . $request->search . '%')
                    ->orWhere('head_code', 'like', '%' . $request->search . '%')
                    ->orWhere('class_id', 'like', '%' . $request->search . '%');
            });
        }

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

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

        $fees = $query->get();

        $pdf = Pdf::loadView('stdFeeRecipt.pdfFeeReciptReport', compact('fees'))->setPaper('a4', 'landscape');
        return $pdf->download('Fee_Recipt_Report.pdf');
    }



    public function search(Request $request)
    {
        $s_HeadCode = $request->input('s_HeadCode');
        $student = Student::where('head_code', $s_HeadCode)->first();

        if ($student) {
            // Fetch the latest admission record for the student
            $latestAdmission = Admission::where('head_code', $s_HeadCode)
                ->orderBy('admission_date', 'desc')
                ->with('class', 'section')
                ->first();

            if ($latestAdmission) {
                $className = $latestAdmission->class->name;
                $sectionName = $latestAdmission->section->name;
                $classId = $latestAdmission->class_id;
                $sectionId = $latestAdmission->section_id;
                $academicYear = $latestAdmission->session_year;
            } else {
                // Handle the case where no admission is found
                $className = "null";
                $sectionName = "null";
                $classId = null;
                $sectionId = null;
                $academicYear = null;
            }

            // Fetch student fee details and handle the case when no details are found
            $feeDetails = Student_fee_detail::where('head_code', $s_HeadCode)
                ->selectRaw('
                SUM(admission_fee) as total_admission_fee,
                SUM(promotion_fee) as total_promotion_fee,
                SUM(scholarship_fee) as total_scholarship_fee,
                SUM(sport_fee) as total_sport_fee,
                SUM(tuition_fee) as total_tuition_fee,
                SUM(lab_fee) as total_lab_fee,
                SUM(exam_fee) as total_exam_fee,
                SUM(board_fee) as total_board_fee,
                SUM(entertainment_fee) as total_entertainment_fee,
                SUM(other_fee) as total_other_fee,
                SUM(books_charges) as total_books_charges,
                SUM(annual_charges) as total_annual_charges,
                SUM(second_time_fee) as total_second_time_fee
            ')
                ->first();

            // Ensure feeDetails exists before accessing properties
            $feeDetails = $feeDetails ?: (object)[
                'total_admission_fee' => 0,
                'total_promotion_fee' => 0,
                'total_scholarship_fee' => 0,
                'total_sport_fee' => 0,
                'total_tuition_fee' => 0,
                'total_lab_fee' => 0,
                'total_exam_fee' => 0,
                'total_board_fee' => 0,
                'total_entertainment_fee' => 0,
                'total_other_fee' => 0,
                'total_books_charges' => 0,
                'total_annual_charges' => 0,
                'total_second_time_fee' => 0
            ];

            // Fetch collected fees and handle the case when no details are found
            $collectedFees = Student_collect_fee_detail::where('head_code', $s_HeadCode)
                ->selectRaw('
                SUM(admission_fee) as collected_admission_fee,
                SUM(promotion_fee) as collected_promotion_fee,
                SUM(scholarship_fee) as collected_scholarship_fee,
                SUM(sport_fee) as collected_sport_fee,
                SUM(tuition_fee) as collected_tuition_fee,
                SUM(lab_fee) as collected_lab_fee,
                SUM(exam_fee) as collected_exam_fee,
                SUM(board_fee) as collected_board_fee,
                SUM(entertainment_fee) as collected_entertainment_fee,
                SUM(other_fee) as collected_other_fee,
                SUM(books_charges) as collected_books_charges,
                SUM(annual_charges) as collected_annual_charges,
                SUM(second_time_fee) as collected_second_time_fee
            ')
                ->first();

            // Ensure collectedFees exists before accessing properties
            $collectedFees = $collectedFees ?: (object)[
                'collected_admission_fee' => 0,
                'collected_promotion_fee' => 0,
                'collected_scholarship_fee' => 0,
                'collected_sport_fee' => 0,
                'collected_tuition_fee' => 0,
                'collected_lab_fee' => 0,
                'collected_exam_fee' => 0,
                'collected_board_fee' => 0,
                'collected_entertainment_fee' => 0,
                'collected_other_fee' => 0,
                'collected_books_charges' => 0,
                'collected_annual_charges' => 0,
                'collected_second_time_fee' => 0
            ];

            // Calculate remaining amounts after subtracting collected fees from the total fee details
            $remainingFees = [
                'admission_fee' => $feeDetails->total_admission_fee - $collectedFees->collected_admission_fee,
                'promotion_fee' => $feeDetails->total_promotion_fee - $collectedFees->collected_promotion_fee,
                'scholarship_fee' => $feeDetails->total_scholarship_fee - $collectedFees->collected_scholarship_fee,
                'sport_fee' => $feeDetails->total_sport_fee - $collectedFees->collected_sport_fee,
                'tuition_fee' => $feeDetails->total_tuition_fee - $collectedFees->collected_tuition_fee,
                'lab_fee' => $feeDetails->total_lab_fee - $collectedFees->collected_lab_fee,
                'exam_fee' => $feeDetails->total_exam_fee - $collectedFees->collected_exam_fee,
                'board_fee' => $feeDetails->total_board_fee - $collectedFees->collected_board_fee,
                'entertainment_fee' => $feeDetails->total_entertainment_fee - $collectedFees->collected_entertainment_fee,
                'other_fee' => $feeDetails->total_other_fee - $collectedFees->collected_other_fee,
                'books_charges' => $feeDetails->total_books_charges - $collectedFees->collected_books_charges,
                'annual_charges' => $feeDetails->total_annual_charges - $collectedFees->collected_annual_charges,
                'second_time_fee' => $feeDetails->total_second_time_fee - $collectedFees->collected_second_time_fee,
            ];

            $totalDue = Transaction_detail::where('coa_id', $s_HeadCode)
                ->selectRaw('SUM(COALESCE(debit, 0)) - SUM(COALESCE(credit, 0)) as balance')
                ->first();

            $balance = $totalDue->balance ?? 0;


            // Return student details along with the class and section names as JSON
            return response()->json([
                'success' => true,
                'student' => $student,
                'class' => $className,
                'section' => $sectionName,
                'remainingFees' => $remainingFees,
                'totalDue' => $balance,
                'sectionId' => $sectionId,
                'classId' => $classId,
                'academicYear' => $academicYear
            ]);
        }

        // Return error if student not found
        return response()->json([
            'success' => false,
            'message' => 'Student not found.'
        ]);
    }

    public function store(Request $request)
    {
        // Filter out only *_fee_input fields
        $feeInputs = collect($request->all())
            ->filter(function ($value, $key) {
                return str_ends_with($key, '_input');
            });

        // Check if at least one *_fee_input has a numeric value
        $hasAtLeastOne = $feeInputs->filter(function ($value) {
            return is_numeric($value) && $value > 0;
        })->isNotEmpty();

        if (!$hasAtLeastOne) {
            return back()
                ->withErrors(['at_least_one_fee' => 'At least one fee input must have a numeric value.'])
                ->withInput();
        }
        DB::beginTransaction();

        try {
            // 1. Create main student fee record

            $status_paid = "Partially Paid";
            if ($request->receiving_amount == ($request->total_due - $request->discount)) {
                $status_paid = "Paid";
            }
            if ($request->receiving_amount == 0) {
                $status_paid = "UnPaid";
            }

            $student = Student::where('reg_no',  $request->registration_no)->first();

            $studentFee = Student_collect_fee::create([
                'head_code' =>  $student->head_code,
                'reg_no' => $request->registration_no,
                'student_id'        => $request->student_id,
                'class_id'         => $request->class_id,
                'section_id'               => $request->section_id,
                'description' => 'Recipt fee',
                'total_amount'             => $request->receiving_amount,
                'discount'       => $request->discount,
                'date' => now(),
                'status'              => $status_paid,
            ]);

            // Define fee types
            $feeTypes = [
                'admission_fee',
                'promotion_fee',
                'tuition_fee',
                'lab_fee',
                'exam_fee',
                'board_fee',
                'entertainment_fee',
                'books_charges',
                'annual_charges',
                'second_time_fee',
                'other_fee',
                'scholarship_fee'
            ];

            // Prepare data array
            $data = [
                'student_id' => $request->student_id,
                'reg_no' => $request->registration_no,
                'head_code' => $student->head_code,
                'class_id' => $request->class_id,
                'std_collect_fee_id' => $studentFee->id,
                'academic_year' => $request->academicYear,
            ];

            // Assign dynamic fee values
            foreach ($feeTypes as $type) {
                $inputKey = $type . '_input';
                $data[$type] = $request->input($inputKey, 0);
            }

            // Insert data into database
            Student_collect_fee_detail::create($data);

            // 3. Create transaction
            $transaction = Transaction::create([
                'transaction_type' => 'Receive fee',
                'trans_type_id' =>  $studentFee->id,
                'transaction_date' => now(),
                'total_amount'     => $request->receiving_amount,
            ]);

            // Credit from student
            Transaction_detail::create([
                'transaction_id' => $transaction->id,
                'coa_id'       => $student->head_code,
                'transaction_type'         => "Recipt Fee",
                'debit'         => 0,
                'credit'         => $request->receiving_amount,
            ]);

            // do work for Cash in hand
            // Cash in hand head code is 20500
            Transaction_detail::create([
                'transaction_id' => $transaction->id,
                'coa_id'       => "20500",
                'transaction_type'         => "Recipt Fee",
                'debit'         => $request->receiving_amount,
                'credit'         => 0,
            ]);

            // do work for receiveable account its head code is 20600
            Transaction_detail::create([
                'transaction_id' => $transaction->id,
                'coa_id'       => "20600",
                'transaction_type'         => "Recipt Fee",
                'debit'         => 0,
                'credit'         => $request->receiving_amount,
            ]);

            DB::commit();

            return back()->with('success', 'Fee successfully recorded.');
        } catch (\Exception $e) {
            DB::rollBack();
            return back()
                ->withErrors(['at_least_one_fee' => 'Failed to store fee. ' . $e->getMessage()])
                ->withInput();
        }
    }
}
