<?php

namespace App\Modules\Company\Borrow\Billings;

use App\Events\Company\InvoiceUpdateEvent;
use App\Events\Company\BorrowBillingNotificationEvent;
use App\Http\Controllers\Controller;
use App\Http\Resources\Company\BorrowBillingBorrowedEmployees as BorrowBillingBorrowedEmployeesResource;
use App\Http\Resources\Company\BorrowBillingClientInvoiceDetails as BorrowBillingClientInvoiceDetailsResource;
use App\Http\Resources\Company\BorrowBillingLoanInvoice as BorrowBillingLoanInvoiceResource;
use App\Models\InboundBillingRequests;
use App\Models\LoanBorrowList;
use App\Models\OutboundBillingRequests;
use App\Models\ProjectWorkersTimesheet;
use App\Traits\CreateUserActionTraits;
use App\Traits\SearchTraits;
use App\Traits\SortingTraits;
use App\Traits\TimeSheetTrait;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Illuminate\Support\Facades\DB;
use App\Events\Company\Admin\NotificationForApprovedPaymentEvent;

class Invoice extends Controller
{

    use SortingTraits, SearchTraits, TimeSheetTrait, CreateUserActionTraits;

    public function fetchBorrowedEmployees($payload)
    {
        // sorting
        $sortField = $this->sortField($payload, 'first_name'); // first_name = default column to search
        $sortOrder = $this->sortOrder($payload, 'asc');

        $company_id = $this->getCurrentUser()->company_id;
        return BorrowBillingBorrowedEmployeesResource::collection(
            LoanBorrowList::select(
                'workers.id',
                'workers.worker_id',
                'workers.first_name',
                'workers.last_name',
            )
                ->join('workers', 'workers.id', '=', 'loan_borrow_lists.worker_id')
                ->where('loan_borrow_lists.borrower_company_id', $company_id)
                ->groupBy('loan_borrow_lists.loaner_company_id')
                ->groupBy('loan_borrow_lists.worker_id')
                ->orderBy($sortField, $sortOrder)
                ->get()
        )
            ->response()
            ->setStatusCode(201);
    }

    public function fetchLoanInvoice($payload)
    {
        // sorting
        $sortField = $this->sortField($payload, 'initial_date'); // initial_date = default column to search
        $sortOrder = $this->sortOrder($payload);

        // searching
        $worker_id = $this->searchField($payload->worker_id);

        $borrowed_worker_id = $payload->borrowed_worker_id;
        $company_id = $this->getCurrentUser()->company_id;
        DB::enableQueryLog();
        return BorrowBillingLoanInvoiceResource::collection(
            LoanBorrowList::select(
                'loan_borrow_lists.id',
                'loan_borrow_lists.rate',
                'loan_borrow_lists.tax',
                'loan_borrow_lists.status',
                'workers.worker_id',
                'workers.last_name',
                'IBR.initial_date',
                'IBR.cutoff_date',
                'IBR.days',
                'IBR.other_expense',
            )
                ->join('inbound_billing_requests AS IBR', 'IBR.loan_borrow_lists_id', '=', 'loan_borrow_lists.id')
                ->join('workers', 'workers.id', '=', 'loan_borrow_lists.worker_id')
                ->whereNotIn('loan_borrow_lists.status', ['Approved', 'Pending'])
                ->where('loan_borrow_lists.borrower_company_id', (int) $company_id)
                ->where('loan_borrow_lists.worker_id', $borrowed_worker_id)
                ->when(!empty($worker_id), function ($query) use ($worker_id) {
                    return $query->where(function ($query) use ($worker_id) {
                        $query->where('workers.worker_id', 'LIKE', $worker_id . '%');
                    });
                })
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )
            ->response()
            ->setStatusCode(201);
    }

    public function sendModificationInvoice($payload)
    {

        $loanBorrowID = $payload->id; //loan_borrow_list id 
        $payload_note = $payload->note;

        $billingData = $this->fetchLoanBorrowData($loanBorrowID);

        $updateLoanBorrow = LoanBorrowList::where('id', $loanBorrowID)->update(['status' => 'Request Modification']);

        $updateInvoiceBillingRequest = InboundBillingRequests::where('loan_borrow_lists_id', $loanBorrowID)->update(['client_request' => $payload_note]);

        $notificationData = (object) [
            'purpose' => 'request-modification',
            'company_id' => $billingData->loaner_company_id,
            'full_name' => $billingData->full_name,
            'company_worker_id' => $billingData->company_worker_id,
        ];
        
        $this->createUserAction('Requested a billing modification for invoice ' . $billingData->invoice_no);
        event(new BorrowBillingNotificationEvent($notificationData));

        if($updateInvoiceBillingRequest && $updateLoanBorrow){
            return [
                'success' => true,
                'message' => 'Request Modification successfully sent.',
                'code' => 200   
            ];
        }

        return [
            'success' => false,
            'message' => 'Something went wrong while requesting modification. Please try again later.',
            'code' => 201
        ];
        
    }

    public function fetchLoanBorrowData($loanBorrowID){
        return LoanBorrowList::select(
                'loan_borrow_lists.*',
                DB::raw('CONCAT(workers.first_name, " ", workers.last_name) as full_name'),
                'workers.worker_id as company_worker_id'
            )
            ->join('workers', 'workers.id', 'loan_borrow_lists.worker_id')
            ->where('loan_borrow_lists.id', $loanBorrowID)
            ->first();
    }

    public function approve($payload)
    {

        $billing_id = $payload->id;
        $total = $payload->total;
        $subtotal_without_service_charge = $payload->subtotal_without_service_charge;
        $other_expenses = $payload->other_expenses;

        $outbound_outstanding = $other_expenses + $subtotal_without_service_charge;

        $billing = LoanBorrowList::find($billing_id);
        $billing->status = 'Approved';
        $billing->save();

        $outbound = OutboundBillingRequests::where(['loan_borrow_lists_id' => $billing_id])
            ->update([
                'outstanding_balance' => $outbound_outstanding,
                'total_billing' => $outbound_outstanding,
                'conx_status' => 'Unpaid']);

        $inbound = InboundBillingRequests::where(['loan_borrow_lists_id' => $billing_id])
            ->update([
                'outstanding_balance' => $total,
                'total_billing' => $total,
            ]);

        $period = CarbonPeriod::create(Carbon::parse($billing->date_from), Carbon::parse($billing->date_to));
        $dates = array();

        foreach ($period as $date) {
            array_push($dates, $date->toDateString());
        }

        $timesheets = ProjectWorkersTimesheet::select(
            'assigned_workers.project_id',
            'project_workers_timesheet.total_hours',
            'project_workers_timesheet.date'
        )
            ->join('assigned_workers', 'assigned_workers.id', 'project_workers_timesheet.project_worker_id')
            ->whereIn('project_workers_timesheet.date', $dates)
            ->where('project_workers_timesheet.worker_id', $billing->worker_id)
            ->get();

        ProjectWorkersTimesheet::whereIn('project_workers_timesheet.date', $dates)
            ->where('project_workers_timesheet.worker_id', $billing->worker_id)
            ->where('status', 'submitted')
            ->update([
                'status' => 'approved',
                'approved_by' => $this->getCurrentUserName(),
            ]);

        foreach ($timesheets as $timesheet) {
            $this->processWorker($billing->worker_id, $timesheet->total_hours, $timesheet->project_id, $timesheet->date);
        }

        $this->createUserAction('Approved the billing of invoice ' . $billing->invoice_no);

        event(new InvoiceUpdateEvent($billing->id, "invoice", "approve"));

        // Ad an admin notification here for notifying them in regards sa approved billing
        $companyName = $this->getCurrentUser()->company_name;
        event(new NotificationForApprovedPaymentEvent($companyName)); //Event for notifying super admin 

        return [
            'success' => true,
            'message' => 'Invoice approved successfully!',
            'code' => 200
        ];
    }

    public function fetchDetails($payload)
    {
        $company_id = $this->getCurrentUser()->company_id;
        return BorrowBillingClientInvoiceDetailsResource::collection(
            LoanBorrowList::select(
                'loan_borrow_lists.id',
                'loan_borrow_lists.invoice_no',
                'loan_borrow_lists.rate',
                'loan_borrow_lists.original_rate',
                'loan_borrow_lists.date_from',
                'loan_borrow_lists.date_to',
                'workers.worker_id',
                'IBR.client_request',
                'IBR.days',
                'IBR.other_expense',
                'IBR.notes',
                'loan_borrow_lists.tax'
            )
                ->join('inbound_billing_requests AS IBR', 'IBR.loan_borrow_lists_id', '=', 'loan_borrow_lists.id')
                ->join('workers', 'workers.id', '=', 'loan_borrow_lists.worker_id')
                ->where('loan_borrow_lists.status', '!=', 'Approved')
                ->where('loan_borrow_lists.borrower_company_id', $company_id)
                ->where('loan_borrow_lists.id', $payload)
                ->limit(1)->get()
        )
            ->response()
            ->setStatusCode(201);
    }
}
