<?php

namespace App\Services;

use App\Http\Resources\DetailMembershipPaymentResource;
use App\Http\Resources\DetailMembershipPaymentResourcePayment;
use App\Mail\MembershipOldExpiredMail;
use App\Models\Company;
use App\Models\DetailMembershipPayment;
use App\Models\Membership;
use App\Models\MembershipCosts;
use App\Models\MembershipPlans;
use App\Models\Pay;
use App\Models\Url;
use App\Models\User;
use App\Traits\HasResponse;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;

class DetailMembershipPaymentService
{
    use HasResponse;

    public function getMembershipPayment($withPagination)
    {
        $membershipPayment = DetailMembershipPayment::where('idcompany', request('idcompany'))->active();

        $membershipPayment = !empty($withPagination)
            ? $membershipPayment->orderBy('id', 'desc')->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $membershipPayment->orderBy('id', 'desc')->get();

        $membershipPayment = DetailMembershipPaymentResource::collection($membershipPayment->load('company', 'membershipCosts', 'pay'));

        return $this->successResponse('Lectura exitosa.', $membershipPayment);
    }

    public function getPaymentsByIdMembership($params, $withPagination)
    {
        #Validaciones
        if (Auth::user()->iduser_type != 1) return $this->errorResponse('Usuario no autorizado', 401);

        $validation = Validator::make($params, [
            'idmembership' => 'required|numeric',
            'term'         => 'nullable|string'
        ]);
        if ($validation->fails()) return $this->errorResponse($validation->errors(), 400);

        $membership = Membership::where('id', $params['idmembership'])->where('status', 1)->first();
        if (!$membership) return $this->errorResponse('Membresía inválida.', 400);

        $payments = DetailMembershipPayment::whereHas('membershipCosts', function ($q) use ($params) {
            $q->where('idmembership', $params['idmembership'])->active();
        })->where('status', 1);

        if (isset($params['idcompany'])) $payments = $payments->where('idcompany', $params['idcompany']);

        $payments = !empty($withPagination)
            ? $payments->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $payments->get();

        return $this->successResponse('Lectura exitosa.', DetailMembershipPaymentResourcePayment::collection($payments->load('membershipCosts', 'company')));
    }

    public function getPaymentsByIdMembershipPay($idcompany)
    {
        $company = Company::find($idcompany);
        $membershipPayment = DetailMembershipPayment::where('idcompany', $company->id)->active();
        $membershipPayment = DetailMembershipPaymentResource::collection($membershipPayment);
        return $this->successResponse('OK', $membershipPayment);
    }

    public function getCompanysWithMembershipExpired($params, $withPagination)
    {
        if (Auth::user()->iduser_type != 1) return $this->errorResponse('Usuario no autorizado', 401);

        $expireds   = DetailMembershipPayment::where('payment_date_end', '<', now())->active();
        $expireds   = !empty($withPagination)
            ? $expireds->paginate($withPagination['perPage'], page: $withPagination['page'])
            : $expireds->groupBy('idcompany')->get();

        return $this->successResponse('OK', DetailMembershipPaymentResource::collection($expireds->load('company', 'membershipCosts', 'pay')));
    }

    public function createMembershipPayment($params)
    {
        DB::beginTransaction();
        try {
            //FALTA PONER METODO DE PAGO
            $date = Carbon::now();
            $validate = $this->validateMembershipCosts($params);
            if (!$validate->original['status']) return $validate;

            $afterMembershipPay = DetailMembershipPayment::where('idcompany', $params['idcompany'])->active()->whereIn('status_page', [1, 2])->first();
            if (isset($afterMembershipPay)) {
                $datePayEnd = Carbon::parse($afterMembershipPay->payment_date_end);
                if ($afterMembershipPay->status_page == '2') {
                    if ($date->gte($datePayEnd)) { # Mayor igual
                        $days = $date->diffInDays($datePayEnd);
                        if ($days > 3) {
                            $date->subDay(3);
                        } else {
                            $date->subDay($days - 1);
                        }
                    }
                } else {
                    $date = $datePayEnd->addDay(1);
                }
                $membershipPayUpdate = DetailMembershipPayment::updateOrCreate(['id' => $afterMembershipPay->id], ['status_page' => '0']);
                $membershipPayUpdate->fresh();
            }

            $payment_date_end = $this->validateDateEnd($validate->original['data']['detail'], $date);

            $membershipPayment = DetailMembershipPayment::create([
                'idcompany'         => $params['idcompany'],
                'idmembershipcosts' => $params['idmembershipcosts'],
                'idpay'             => $params['idpay'],
                'payment_date'      => $date->format("Y-m-d H:i:s"),
                'status_page'       => 1,
                'payment_date_end'  => $payment_date_end
            ]);
            $membershipPayment->fresh();

            # Actualiza la membresía
            $membershipCosts = MembershipCosts::find($params['idmembershipcosts']);

            $company = Company::find($params['idcompany']);
            $company->update(['idmembership' =>  $membershipCosts->idmembership]);
            $company->fresh();

            DB::commit();
            return $this->successResponse("Pago de membresia registrado con éxito.", $membershipPayment);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante el registro de una pago de membresía.', $th->getMessage());
        }
    }

    public function sendMailMembershipExpired($idcompany)
    {
        try {
            // if (Auth::user()->iduser_type != 1) return $this->errorResponse('Usuario no autorizado', 401);

            $company = Company::activeForID($idcompany)->first();
            if (!$company) return $this->errorResponse('Compañía no válida.', 400);

            $admin = User::where('idcompany', $idcompany)->active()
                ->whereHas('detailUser', function ($q) use ($idcompany) {
                    $q->where('iduser_type', 2)->where('idcompany', $idcompany)->active();
                })->first();

            $username       = base64_encode($admin->username);
            $rut            = base64_encode($admin->rut);
            $password64     = base64_encode(Crypt::decryptString($admin->encrypted_password));
            $iduser_type    = base64_encode(2);
            $url_autologin  = Url::find(2)->url . "/?rut_company=$company->rut&username=$username&rut=$rut&password=$password64&iduser_type=$iduser_type";

            Mail::to($admin->email)->send(new MembershipOldExpiredMail($admin->username, $url_autologin));

            return $this->successResponse('Correo envíado exitosamente.');
        } catch (\Throwable $th) {
            return $this->externalError('durante el envío de correo.', $th->getMessage());
        }
    }

    public function validateMembershipCosts($params)
    {
        $membershipCosts = MembershipCosts::find($params['idmembershipcosts']);
        if (!$membershipCosts) return $this->errorResponse("El costo de plan de la membresia no existe", 400);


        $company = Company::find($params['idcompany']);
        if (!$company) return $this->errorResponse("Compañía no válido", 400);

        $pay = Pay::find($params['idpay']);
        if (!$pay) return $this->errorResponse("Id de pago no válido", 400);

        return $this->successResponse("Es válido", $membershipCosts->idplans);
    }

    private function validateDateEnd($idplan, $date)
    {
        $plan = MembershipPlans::find($idplan);
        $dateNow = clone $date;
        $endData = $dateNow->addMonth($plan->month)->format("Y-m-d H:i:s");

        return $endData;
    }
}
