<?php

namespace App\Http\Controllers;

use App\Models\Department;
use App\Models\EmployeeDebt;
use App\Models\EmployeePayablePayment;
use App\Models\EmployeePayablePaymentDetail;
use App\Models\EmployeePayablePaymentDetailPay;
use App\Models\PaymentMethod;
use App\Models\Employee;
use App\Models\Company;
use App\Models\Coa;
use App\Models\DeleteLog;
use App\Models\EmployeeDebtHistory;
use App\Models\Journal;
use App\Models\CurrencyConversion;
use App\Models\Currency;
use App\Models\Periode;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\QueryException;
use DB;
use Carbon\Carbon;

class EmployeeDebtPaymentController extends Controller
{
    public function index($dateStart,$dateEnd)
    {
        try {
            $debt = EmployeePayablePayment::with(['details.employee'])->whereBetween('employee_payable_payment_date',[$dateStart,$dateEnd])
            ->whereIn('department_id',$this->getDepartment())->get();
            $periods = Periode::all();
            foreach($debt as $d){
                $listEmp = [];
                foreach($d->details as $dDet){
                    if(!in_array($dDet->employee->employee_name,$listEmp)){
                        $listEmp[] = $dDet->employee->employee_name;
                    }
                }
                $d->closed = Module::checkPeriodeBack($periods,$d->employee_payable_payment_date);
                $d->employee_name = "";
                foreach($listEmp as $e){
                    if($d->employee_name == ""){
                        $d->employee_name = $e;
                    }else{
                        $d->employee_name .= " , ".$e;
                    }
                }
            }

            return response()->json(["debt" => $debt,"role" => $this->getRole()]);
        } catch (\Exception $e) {
            Log::error('Failed to fetch employee payable payment', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to fetch employee payable payment'], 500);
        }
    }

    public function store(Request $request)
    {
        DB::beginTransaction();
        try{
            $validated = $request->validate([
                'document_date' => 'required|date',
                'acc_disc' => 'nullable|integer|exists:coa,id',
                'notes' => 'nullable|string',
                'department_id' => 'nullable|integer|exists:department,id',
                'details' => 'required|array|min:1',
                'details.*.document_number' => 'required|string|exists:employee_debt,document_number',
                'details.*.employee_id' => 'required|integer|exists:employees,id',
                'details.*.nominal_payment' => 'nullable|numeric',
                'details.*.disc_nominal' => 'nullable|numeric|min:0',
                'payments' => 'nullable|array|min:0',
                'payments.*.payment_method_id' => 'required|integer|exists:payment_method,id',
                'payments.*.payment_nominal' => 'required|numeric',
                'payments.*.bg_check_number' => 'nullable|string',
            ]);

            $company = Company::first();
            $department = Department::find($request->department_id);
            $date = Carbon::parse($request->document_date);
            $nobukti = Module::generateDocumentNumber($company->companyCode,$department->department_code,$date->month,$date->year,"EDP",1);
            $employee = Employee::all();

            $payable = EmployeePayablePayment::create([
                "employee_payable_payment_number" => $nobukti,
                "employee_payable_payment_date" => $request->document_date,
                "acc_disc" => $request->acc_disc,
                'total_debt' => 0,
                "notes" => $request->notes,
                'company_code' => $company->companyCode,
                "department_id" => $request->department_id,
                'created_by' => Auth::user()->id,
                'updated_by' => Auth::user()->id,
            ]);

            $details = $request->details;
            $total_nominal = 0;
            $total_discount = 0;
            $payment_details = $request->payments;
            $allDocumentNumber = "";
            foreach ($details as $key => $detail) {
                $detail['nominal_payment'] = $detail['nominal_payment'] ?? 0;
                $detail['discount'] = $detail['discount'] ?? 0;
                if ($detail['nominal_payment'] == 0){
                    continue;
                }
                $oldDebt = EmployeeDebt::where('document_number', $detail['document_number'])->first();
                $balance = $oldDebt->debt_balance-$detail['discount'];
                $total_nominal+= $detail['nominal_payment'];
                $total_discount+= $detail['discount'];
                if($detail['nominal_payment']<>0){
                    $allDocumentNumber .= $detail['document_number'].",";
                    EmployeePayablePaymentDetail::create([
                        'employee_payable_payment_id' => $payable->id,
                        'employee_payable_payment_date' => $payable->employee_payable_payment_date,
                        'employee_id' => $detail['employee_id'],
                        'document_number' => $detail['document_number'] ?? '',
                        'document_date' => $detail['document_date'],
                        'document_nominal' => $oldDebt->total_debt ?? 0,
                        'document_payment' => $oldDebt->debt_balance ?? 0,
                        'nominal_payment' => $detail['nominal_payment'] ?? 0,
                        'nominal_payment_base' => ($detail['nominal_payment'] ?? 0),
                        'discount' => $detail['discount'] ?? 0,
                        'balance' => $balance,
                        'acc_debt' => $detail['acc_debt'] ?? null,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => Auth::user()->id,
                        'updated_by' => Auth::user()->id,
                    ]);

                    // Update DebtHistory
                    $oldDebt = EmployeeDebt::where('document_number', $detail['document_number'])->first();
                    EmployeeDebtHistory::create([
                        'document_number' => $detail['document_number'],
                        'document_date' => $detail['document_date'],
                        'employee_id' => $detail['employee_id'],
                        'payment_number' => $payable->employee_payable_payment_number,
                        'payment_date' => $payable->employee_payable_payment_date,
                        'payment' => $detail['nominal_payment'],
                        'discount' => $detail['discount'],
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => Auth::user()->id,
                        'updated_by' => Auth::user()->id,
                    ]);

                    // Update old debt balance
                    $oldDebt->debt_balance = $oldDebt->debt_balance - ($detail['nominal_payment'] + $detail['discount']);
                    $oldDebt->save();

                    $emp = $employee->where('id',$detail['employee_id'])->first();
                    if($emp){
                        Journal::create([
                            'document_number' => $payable->employee_payable_payment_number,
                            'document_date' => $payable->employee_payable_payment_date,
                            'account_number' => $emp->account_employee_debt,
                            'notes' => 'Employee Debt Payment ' . $emp->employee_name . ' - ' . $detail['document_number'] . ' @ ' . $detail['nominal_payment'],
                            'debet_nominal' => 0,
                            'credit_nominal' => $detail['nominal_payment'] ?? 0,
                            'debet_nominal_base' => 0,
                            'credit_nominal_base' => $detail['nominal_payment'] ?? 0,
                            'company_code' => $company->companyCode,
                            'department_id' => $payable->department_id,
                            'created_by' => Auth::user()->id,
                            'updated_by' => Auth::user()->id,
                        ]);
                    }
                }
            }

            foreach ($payment_details as $pay_detail_data) {
                // Store payment details for each invoice
                $payment_method = PaymentMethod::find($pay_detail_data['payment_method_id']);

                if($pay_detail_data['payment_nominal']>0){
                    // Create Payable Payment Detail
                    EmployeePayablePaymentDetailPay::create([
                        'employee_payable_payment_id' => $payable->id,
                        'employee_payable_payment_date' => $payable->employee_payable_payment_date,
                        'payment_method_id' => $pay_detail_data['payment_method_id'],
                        'payment_nominal' => $pay_detail_data['payment_nominal'],
                        'payment_nominal_base' => $pay_detail_data['payment_nominal'],
                        'bg_check_number' => $pay_detail_data['bg_check_number'] ?? null,
                        'acc_debt_bg' => $payment_method->account_number ?? null,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => Auth::user()->id,
                        'updated_by' => Auth::user()->id,
                    ]);

                    Journal::create([
                        'document_number' => $payable->employee_payable_payment_number,
                        'document_date' => $payable->employee_payable_payment_date,
                        'account_number' => $payment_method->account_number,
                        'notes' => 'Payment for ' . $allDocumentNumber . ' by ' . $payment_method->payment_name,
                        'debet_nominal' => $pay_detail_data['payment_nominal'] ?? 0,
                        'credit_nominal' => 0,
                        'debet_nominal_base' => $pay_detail_data['payment_nominal'] ?? 0,
                        'credit_nominal_base' => 0,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => Auth::user()->id,
                        'updated_by' => Auth::user()->id,
                    ]);
                }
            }

            $payable->total_debt = $total_nominal + $total_discount;
            $payable->save();

            DB::commit();
            return response()->json(null);
        }catch(\Exception $e){
            DB::rollback();
            dd($e->getMessage());
            Log::error('Error store employee debt payment', ['error' => $e->getMessage(), 'user' => Auth::user()->name ?? 'system']);
            return response()->json(['error' => 'Failed to fetch employee debt payment'], 500);
        }
    }

    public function show($id){
        try {
            $payable = EmployeePayablePayment::with([
                'details.employee',
                'detailPays',
                'department'
            ])->findOrFail($id);

            return response()->json($payable);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Debt Payment not found'], 404);
        }
    }

    public function update(Request $request, $id){
        DB::beginTransaction();
        try{
            $validated = $request->validate([
                'document_date' => 'required|date',
                'acc_disc' => 'nullable|integer|exists:coa,id',
                'notes' => 'nullable|string',
                'department_id' => 'nullable|integer|exists:department,id',
                'details' => 'required|array|min:1',
                'details.*.document_number' => 'required|string|exists:employee_debt,document_number',
                'details.*.employee_id' => 'required|integer|exists:employees,id',
                'details.*.nominal_payment' => 'nullable|numeric',
                'details.*.disc_nominal' => 'nullable|numeric|min:0',
                'payments' => 'nullable|array|min:0',
                'payments.*.payment_method_id' => 'required|integer|exists:payment_method,id',
                'payments.*.payment_nominal' => 'required|numeric',
                'payments.*.bg_check_number' => 'nullable|string',
            ]);

            $company = Company::first();
            $department = Department::find($request->department_id);
            $date = Carbon::parse($request->document_date);

            EmployeePayablePayment::find($id)->update([
                "acc_disc" => $request->acc_disc,
                'total_debt' => 0,
                "notes" => $request->notes,
                'updated_by' => Auth::user()->id,
                'updated_at' => now(),
            ]);

            $payable = EmployeePayablePayment::find($id);
            $employee = Employee::all();

            $details = $request->details;
            $total_nominal = 0;
            $total_discount = 0;
            $payment_details = $request->payments;
            $oldDetail = EmployeePayablePaymentDetail::where("employee_payable_payment_id",$payable->id)->get();

            //kembalikan debt dulu
            foreach($oldDetail as $od){
                $oldDebtUbah = EmployeeDebt::where('document_number', $od->document_number)->first();
                $oldDebtUbah->debt_balance = $oldDebtUbah->debt_balance + $od->nominal_payment + $od->discount;
                $oldDebtUbah->update();
            }
            EmployeePayablePaymentDetail::where("employee_payable_payment_id",$payable->id)->delete();
            EmployeePayablePaymentDetailPay::where('employee_payable_payment_id', $payable->id)->delete();
            EmployeeDebtHistory::where("payment_number",$payable->employee_payable_payment_number)->delete();
            Journal::where("document_number",$payable->employee_payable_payment_number)->delete();
            $allDocumentNumber = "";
            foreach ($details as $key => $detail) {
                $detail['nominal_payment'] = $detail['nominal_payment'] ?? 0;
                $detail['discount'] = $detail['discount'] ?? 0;
                if ($detail['nominal_payment'] == 0){
                    continue;
                }
                $oldDebt = EmployeeDebt::where('document_number', $detail['document_number'])->first();
                $balance = $oldDebt->debt_balance-$detail['discount'];
                $total_nominal+= $detail['nominal_payment'];
                $total_discount+= $detail['discount'];
                if($detail['nominal_payment']<>0){
                    $allDocumentNumber .= $detail['document_number'].",";
                    EmployeePayablePaymentDetail::create([
                        'employee_payable_payment_id' => $payable->id,
                        'employee_payable_payment_date' => $payable->employee_payable_payment_date,
                        'employee_id' => $detail['employee_id'],
                        'document_number' => $detail['document_number'] ?? '',
                        'document_date' => $detail['document_date'],
                        'document_nominal' => $oldDebt->total_debt ?? 0,
                        'document_payment' => $oldDebt->debt_balance ?? 0,
                        'nominal_payment' => $detail['nominal_payment'] ?? 0,
                        'nominal_payment_base' => ($detail['nominal_payment'] ?? 0),
                        'discount' => $detail['discount'] ?? 0,
                        'balance' => $balance,
                        'acc_debt' => $detail['acc_debt'] ?? null,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => $payable->created_by,
                        'updated_by' => Auth::user()->id,
                        'created_at' => $payable->created_at,
                        'updated_at' => now(),
                    ]);

                    // Update DebtHistory
                    $oldDebt = EmployeeDebt::where('document_number', $detail['document_number'])->first();
                    EmployeeDebtHistory::create([
                        'document_number' => $detail['document_number'],
                        'document_date' => $detail['document_date'],
                        'employee_id' => $detail['employee_id'],
                        'payment_number' => $payable->employee_payable_payment_number,
                        'payment_date' => $payable->employee_payable_payment_date,
                        'payment' => $detail['nominal_payment'],
                        'discount' => $detail['discount'],
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => $payable->created_by,
                        'updated_by' => Auth::user()->id,
                        'created_at' => $payable->created_at,
                        'updated_at' => now(),
                    ]);

                    // Update old debt balance
                    $oldDebt->debt_balance = $oldDebt->debt_balance - ($detail['nominal_payment'] + $detail['discount']);
                    $oldDebt->save();

                    $emp = $employee->where('id',$detail['employee_id'])->first();
                    if($emp){
                        Journal::create([
                            'document_number' => $payable->employee_payable_payment_number,
                            'document_date' => $payable->employee_payable_payment_date,
                            'account_number' => $emp->account_employee_debt,
                            'notes' => 'Employee Debt Payment ' . $emp->employee_name . ' - ' . $detail['document_number'] . ' @ ' . $detail['nominal_payment'],
                            'debet_nominal' => 0,
                            'credit_nominal' => $detail['nominal_payment'] ?? 0,
                            'debet_nominal_base' => 0,
                            'credit_nominal_base' => $detail['nominal_payment'] ?? 0,
                            'company_code' => $company->companyCode,
                            'department_id' => $payable->department_id,
                            'created_by' => Auth::user()->id,
                            'updated_by' => Auth::user()->id,
                        ]);
                    }
                }
            }

            foreach ($payment_details as $pay_detail_data) {
                // Store payment details for each invoice
                $payment_method = PaymentMethod::find($pay_detail_data['payment_method_id']);

                if($pay_detail_data['payment_nominal']>0){
                    // Create Payable Payment Detail
                    EmployeePayablePaymentDetailPay::create([
                        'employee_payable_payment_id' => $payable->id,
                        'employee_payable_payment_date' => $payable->employee_payable_payment_date,
                        'payment_method_id' => $pay_detail_data['payment_method_id'],
                        'payment_nominal' => $pay_detail_data['payment_nominal'],
                        'payment_nominal_base' => $pay_detail_data['payment_nominal'],
                        'bg_check_number' => $pay_detail_data['bg_check_number'] ?? null,
                        'acc_debt_bg' => $payment_method->account_number ?? null,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => $payable->created_by,
                        'updated_by' => Auth::user()->id,
                        'created_at' => $payable->created_at,
                        'updated_at' => now(),
                    ]);

                    Journal::create([
                        'document_number' => $payable->employee_payable_payment_number,
                        'document_date' => $payable->employee_payable_payment_date,
                        'account_number' => $payment_method->account_number,
                        'notes' => 'Payment for ' . $allDocumentNumber . ' by ' . $payment_method->payment_name,
                        'debet_nominal' => $pay_detail_data['payment_nominal'] ?? 0,
                        'credit_nominal' => 0,
                        'debet_nominal_base' => $pay_detail_data['payment_nominal'] ?? 0,
                        'credit_nominal_base' => 0,
                        'company_code' => $company->companyCode,
                        'department_id' => $payable->department_id,
                        'created_by' => Auth::user()->id,
                        'updated_by' => Auth::user()->id,
                    ]);
                }
            }

            $payable->total_debt = $total_nominal + $total_discount;
            $payable->save();

            //If there's a discount, create a journal entry for it
            if ($total_discount > 0) {
                // Journal::create([
                //     'document_number' => $payable->payable_payment_number,
                //     'document_date' => $payable->payable_payment_date,
                //     'account_number' => $request->acc_disc,
                //     'notes' => 'Discount on payment for ' . $payable->payable_payment_number,
                //     'debet_nominal' => 0,
                //     'credit_nominal' => $total_discount,
                //     'company_code' => $company->companyCode,
                //     'department_id' => $payable->department_id,
                //     'created_by' => Auth::user()->id,
                //     'updated_by' => Auth::user()->id,
                // ]);
            }

            //Create Journal Total entry for the supplier payment
            //$acc_payable = Coa::where("account_number",$supplier->account_payable)->first();
            // Journal::create([
            //     'document_number' => $payable->payable_payment_number,
            //     'document_date' => $payable->payable_payment_date,
            //     'account_number' => $acc_payable->id,
            //     'notes' => 'Total payment for ' . $payable->payable_payment_number,
            //     'debet_nominal' => $total_nominal + $total_discount,
            //     'credit_nominal' => 0,
            //     'company_code' => $company->companyCode,
            //     'department_id' => $payable->department_id,
            //     'created_by' => Auth::user()->id,
            //     'updated_by' => Auth::user()->id,
            // ]);

            DB::commit();
            return response()->json(null);
        }catch(\Exception $e){
            DB::rollback();
            Log::error('Error update Employee debt payment', ['error' => $e->getMessage(), 'user' => Auth::user()->name ?? 'system']);
            return response()->json(['error' => 'Failed to fetch Employee debt payment'], 500);
        }
    }

    public function destroy(Request $request,$id){
        DB::beginTransaction();
        try{
            $payable = EmployeePayablePayment::find($id);

            $oldDetail = EmployeePayablePaymentDetail::where("employee_payable_payment_id",$payable->id)->get();
            EmployeeDebtHistory::where("payment_number",$payable->employee_payable_payment_number)->delete();
            //kembalikan debt dulu
            foreach($oldDetail as $od){
                $oldDebtUbah = EmployeeDebt::where('document_number', $od->document_number)->first();
                $oldDebtUbah->debt_balance = $oldDebtUbah->debt_balance + $od->nominal_payment + $od->discount;
                $oldDebtUbah->update();
            }

            EmployeePayablePaymentDetail::where("employee_payable_payment_id",$payable->id)->delete();
            EmployeePayablePaymentDetailPay::where('employee_payable_payment_id', $payable->id)->delete();
            EmployeePayablePayment::find($id)->delete();
            Journal::where("document_number",$payable->employee_payable_payment_number)->delete();

            DeleteLog::create([
                'document_number' => $payable->employee_payable_payment_number,
                'document_date' => $payable->employee_payable_payment_date,
                'delete_notes' => $request->delete_notes ?? 'No notes provided',
                'company_code' => $payable->company_code,
                'department_code' => $payable->department_id,
                'deleted_by' => Auth::check() ? Auth::user()->name : 'system',
                'type' => 'Employee Debt Payment',
            ]);
            DB::commit();
            return response()->json(null);
        }catch(\Exception $e){
            DB::rollback();
            return response()->json(['error' => 'Failed to delete Employee debt payment'], 500);
        }
    }

    public function getMasterData(){
        $Listdepartment = $this->getDepartment();
        $departments = Department::whereIn("id",$Listdepartment)->get();
        $paymentMethod = PaymentMethod::all();
        $coas = Coa::with('coaType')
                // ->whereHas('coaType', function ($query) {
                //     $query->where('account_sub_type', '!=', 'PM');
                // })
                ->orderBy('account_number','asc')
                ->get();
        $debt = EmployeeDebt::with(['employee'])->where("debt_balance","<>",0)->get();

        $company = Company::first();
        $date = Carbon::now();
        $nobukti = Module::generateDocumentNumber($company->companyCode,$departments->first()->department_code,$date->month,$date->year,"EDP",0);

        $response = [
            'departments' => $departments,
            'debt' => $debt,
            'coas' => $coas,
            'paymentMethod' => $paymentMethod,
            'nobukti' => $nobukti,
            "role" => $this->getRole()
        ];
        return response()->json($response);
    }

    public function getNomorBukti(Request $request)
    {
        $company = Company::first();
        $department = Department::find($request->department_id);
        $date = Carbon::parse($request->document_date);
        $nobukti = Module::generateDocumentNumber($company->companyCode,$department->department_code,$date->month,$date->year,"EDP",0);
        return response()->json($nobukti);
    }

    public function print($id)
    {
        $debtPayment = EmployeePayablePayment::with(['details.employee','detailPays.paymentMethod'])->where("id", $id)->firstOrFail();
        $imagePath = storage_path('app/images/logo-only.png');
        $imageData = file_get_contents($imagePath);

        $totalHuruf = ucwords($this->numberToWords($debtPayment->total_debt)) . ' Rupiah';
        $username = Auth::user()->name;
        $pdf = \PDF::loadView('print.employee_debt_payment_pdf', compact('debtPayment', 'imageData', 'totalHuruf','username'))->setPaper('A5', 'landscape');
        return ["data" => "data:application/pdf;base64," . base64_encode($pdf->stream()),"role" => $this->getRole()];
    }

    public function increasePrintNumber($id){
        $gr = GoodReceiptMakloon::find($id);
        $gr->print_number = ($gr->print_number ?? 0) + 1;
        $gr->save();
        return response()->json(null);
    }
}
