<?php

namespace App\Http\Controllers\api;

use App\Http\Controllers\Controller;
use App\Http\Requests\LoanSummaryRequest;
use App\Models\Application\Client;
use App\Models\Application\Loan;
use App\Models\Application\LoanEndorsement;
use App\Models\Application\RequestClient;
use App\Models\Application\RequestLoan;
use App\Models\Application\Status;
use App\Traits\LoanTrait;
use App\Traits\PaymentTrait;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use stdClass;

class RequestLoanSummaryController extends Controller
{
    use LoanTrait, PaymentTrait;

    private $MESSAGES = [
        'INDEX' => 'REQUESTSUMMARY_INDEX',
        'CONVERT' => 'REQUESTSUMMARY_CONVERT',
        'NOT-APPROVED' => 'REQUESTSUMMARY_NOT_APPROVED',
    ];

    public function __construct()
    {
        $this->CHANNEL = 'requestloansummary_errors';
    }

    public function index(LoanSummaryRequest $request)
    {
        try {
            $response = new stdClass();
            $isSystemAdministrator = $this->hasSystemAdministrator();
            $currentdate = Carbon::now()->startOfWeek()->addDays(3)->endOfDay();

            if (Carbon::now()->greaterThan($currentdate)) {
                $currentdate->addWeek();
            }

            $currentdate = $currentdate->previous(Carbon::SATURDAY);
            $init = $currentdate->subDays(2)->format('Y-m-d');
            $end = $currentdate->addDays(4)->format('Y-m-d');

            $response->requests = RequestLoan::select(
                'id',
                'fk_group',
                'fk_client',
                'fk_request_client',
                'loandate',
                'loanenddate',
                'loanamount',
                'weeklypayment',
                'realamount',
                'fk_promoter',
                'fk_executive',
                'fk_supervisor',
                'fk_loan_type',
                'fk_status',
                'created'
            )->with(['group', 'client', 'request_client', 'loan_type', 'status'])->where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', !$this->hasSpecial($request->fk_office)],
            ])->when(isset($request->fk_group), function ($group) use ($request) {
                $group->where('fk_group', $request->fk_group);
            })->whereHas('status', function ($status) use ($request) {
                $status->when(isset($request->statusname), function ($status) use ($request) {
                    $status->where('statusname', $request->statusname);
                }, function ($status) {
                    $defaultstatus = ['SOLICITUD EN APROBACIÓN', 'SOLICITUD APROBADA', 'SOLICITUD RECHAZADA', 'SOLICITUD REGISTRADA'];

                    $status->whereIn('statusname', $defaultstatus);
                });
            })->when(!$isSystemAdministrator, function ($query) {
                $query->where('visible', true);
            })->whereBetween('loandate', [$init, $end])->get();

            $response->requests->each(function ($item) {
                $item->promoter_commission = $item->loanamount * ((clone $item)->promoter->commissionpercent / 100);
                $item->executive_commission = $item->loanamount * ((clone $item)->executive->commissionpercent / 100);
                $item->supervisor_commission = $item->loanamount * ((clone $item)->supervisor->commissionpercent / 100);

                $client = [
                    'id' => $item->request_client->id ?? null,
                    'fk_client' => $item->client->id ?? null,
                    'fullname' => $item->client->fullname ?? $item->request_client->fullname,
                ];

                if ($item->request_client) {
                    $item->weeklypaymentchange = 0;
                } else {
                    $last_loan = Loan::whereHas('status', function ($status) {
                        $status->whereIn('statusname', ['SOLICITUD ACTIVA', 'SOLICITUD ATRASADA', 'SOLICITUD MOROSA']);
                    })->where([
                        ['fk_client', $item->client->id],
                        ['is_active', true]
                    ])->orderBy('loandate', 'DESC')->first();

                    $item->up = $last_loan ?  $item->weeklypayment - $last_loan->weeklypayment : 0;
                }

                unset($item->client);
                unset($item->request_client);

                $item->client = $client;
            });

            $response->availableamount = Loan::where([
                ['fk_site', $request->fk_site],
                ['fk_office', $request->fk_office],
                ['is_active', true],
            ])->whereHas('status', function ($status) {
                $defaultstatus = ['SOLICITUD ACTIVA', 'SOLICITUD ATRASADA', 'SOLICITUD MOROSA'];

                $status->whereIn('statusname', $defaultstatus);
            })->whereHas('payments', function ($payments) use ($init, $end) {
                $payments->whereHas('status', function ($status) {
                    $statusarray = ['PENDIENTE', 'FALLA', 'INCOMPLETO'];

                    $status->whereIn('statusname', $statusarray);
                })->whereBetween('duedate', [$init, $end])
                    ->where('is_active', true);
            })->when(isset($request->fk_group), function ($group) use ($request) {
                $group->where('fk_group', $request->fk_group);
            })->sum('weeklypayment');

            return $this->responseJson(null, $response, 201);
        } catch (Exception $ex) {
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['INDEX'], null, 501);
        }
    }

    public function convertToLoan(LoanSummaryRequest $request)
    {
        try {
            DB::beginTransaction();

            $client = null;
            $requestloan = RequestLoan::findOrFail($request->id);
            $allowMultiLoans = !$this->AllowMultiLoans($request);
            $registerstatus = Status::where('statusname', 'SOLICITUD REGISTRADA')->first();

            if ($requestloan->status->statusname !== 'SOLICITUD APROBADA') {
                return $this->responseJson($this->MESSAGES['NOT-APPROVED'], null, 501);
            }

            if (!isset($request->client['fk_client']) && !$request->client['fk_client']) {
                $requestclient = RequestClient::findOrFail($request->client['id']);

                $client = Client::create([
                    'fk_site' => $request->fk_site,
                    'fk_office' => $request->fk_office,
                    'firstname' => trim(mb_strtoupper($requestclient->firstname, $this->UTF_ENCODING)),
                    'lastname' => trim(mb_strtoupper($requestclient->lastname, $this->UTF_ENCODING)),
                    'secondlastname' => trim(mb_strtoupper($requestclient->secondlastname, $this->UTF_ENCODING)),
                    'curp' => trim(mb_strtoupper($requestclient->curp, $this->UTF_ENCODING)),
                    'fk_city' => $requestclient->fk_city,
                    'colony' => trim(mb_strtoupper($requestclient->colony, $this->UTF_ENCODING)),
                    'address' => trim(mb_strtoupper($requestclient->address, $this->UTF_ENCODING)),
                    'phonenumber' => $requestclient->phonenumber !== null ? trim($requestclient->phonenumber) : null,
                    'fk_usercreator' => $this->user()->id,
                ]);

                $requestclient->update([
                    'is_active' => false,
                    'fk_userupdater' => $this->user()->id,
                ]);
            } else {
                $client = Client::findOrFail($request->client['fk_client']);
            }

            if ($allowMultiLoans) {
                $activeloan = Loan::where([
                    ['fk_site', $request->fk_site],
                    ['fk_office', $request->fk_office],
                    ['is_active', true],
                    ['fk_client', $client->id],
                ])->whereHas('status', function ($status) {
                    $defaultstatus = ['SOLICITUD ACTIVA'];

                    $status->whereIn('statusname', $defaultstatus);
                })->first();

                if ($activeloan) {
                    $this->renewUniqueLoan($activeloan, true);
                }
            }

            $item = Loan::create([
                'fk_site' => $request->fk_site,
                'fk_office' => $request->fk_office,
                'fk_loan_type' => $requestloan->fk_loan_type,
                'fk_group' => $requestloan->fk_group,
                'fk_promoter' => $requestloan->fk_promoter,
                'fk_client' => $client->id,
                'loanamount' => $requestloan->loanamount,
                'weeklypayment' => $requestloan->weeklypayment,
                'duration' => $requestloan->duration,
                'loandate' => Carbon::createFromTimestamp($requestloan->loandate)->format('Y-m-d'),
                'loanenddate' => Carbon::createFromTimestamp($requestloan->loanenddate)->format('Y-m-d'),
                'realamount' => $requestloan->realamount,
                'fk_executive' => $requestloan->fk_executive,
                'fk_supervisor' => $requestloan->fk_supervisor,
                'fk_collaborator' => null,
                'fk_usercreator' => $this->user()->id,
            ]);

            $requestloan->update([
                'created' => true,
                'fk_status' => $registerstatus->id,
                'fk_userupdater' => $this->user()->id,
            ]);

            if (isset($activeloan)) {
                $activeloan->fk_loan_renewed = $item->id;
                $activeloan->fk_userupdater = $this->user()->id;

                $activeloan->update();
            }

            $this->addLoanDetails($item, $requestloan->details);
            $this->createPayments($item, $requestloan->firstpay);

            if ($requestloan->endorsements) {
                foreach ($requestloan->endorsements as $endorsement) {
                    $endorsement = Client::find($endorsement->id);

                    if (!$endorsement) {
                        continue;
                    }

                    LoanEndorsement::create([
                        'fk_loan' => $item->id,
                        'fk_endorsement' => $endorsement->id,
                        'fk_usercreator' => $this->user()->id
                    ]);
                }
            }

            $this->determineClientStatus($item);

            if ($requestloan->first_pay) {
                $incomingStatus = Status::where('statusname', 'ADELANTO')->first();
                $payment = $item->payments()->orderBy('duedate', 'ASC')->first();

                $payment->update([
                    'fk_status' => $incomingStatus->id,
                    'payment' => $item->weeklypayment,
                    'paymentdate' => $item->loandate,
                    'fk_userupdater' => $this->user()->id,
                ]);
            }

            DB::commit();
            return $this->responseJson(null, true, 201);
        } catch (Exception $ex) {
            DB::rollBack();
            $this->generateLog($this->CHANNEL, $ex);
            return $this->responseJson($this->MESSAGES['CONVERT'], null, 501);
        }
    }
}
