<?php

namespace App\Modules\Admin\Companies;

use App\Models\Company;
use App\Models\CompanySubscriptions;
use App\Models\EmailVerification;
use App\Models\IECMembers;
use App\Events\Admin\ChangeCompanyServiceChargeEvent;
use App\Http\Resources\Admin\CompanyAccountDetails as AdminCompanyAccountDetailsResource;
use App\Http\Resources\Admin\CompanyAccounts as AdminCompanyAccountsResource;
use App\Http\Resources\Admin\CompanyResource;
use App\Traits\MobileNumberValidatorTraits;
use App\Traits\SearchTraits;
use App\Traits\SortingTraits;
use App\Traits\ValidatorTraits;
use App\Traits\ZipcodeTraits;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Redirect;

class Companies
{
    use SortingTraits, SearchTraits, MobileNumberValidatorTraits, ValidatorTraits, ZipcodeTraits;

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

        // searching
        $nameSearch = $this->searchField($payload->name);
        $chapterSearch = $this->searchField($payload->chapter_name);
        $memberCodeSearch = $this->searchField($payload->iec_number);
        $expertiseSearch = $payload->expertises;
        $signupStatusSearch = $signupStatus? [$signupStatus]: $payload->signup_status;
        $accountStatusSearch = $payload->account_status;
        
        // subscription filters
        $isBanned = $payload->is_banned;
        $almostExpired = null;
        $expired = null;
        $blocked = null;
        $current = null;

        if ($isBanned == 'banned') {
            $isBanned = true;
        } else {
            $isBanned = false;
        }

        $subscriptionExpiration = $payload->subscription;
        if ($subscriptionExpiration == ['expired']) {
            $expired = true;
        } else if ($subscriptionExpiration == ['about to expired']) {
            $almostExpired = true;
        } else if ($subscriptionExpiration == ['blocked']) {
            $blocked = true;
        } else if ($subscriptionExpiration == ['current']) {
            $current = true;
        }

        return AdminCompanyAccountsResource::collection(
            Company::select(
                'companies.id',
                'companies.company_logo',
                'companies.name',
                'companies.service_charge',
                'companies.discount',
                'companies.is_banned as account_status',
                'company_subscriptions.duration as subscription_expiration',
                'company_subscriptions.is_expired',
                'companies.type as signup_status',
                'iec_members.chapter_name',
                'iec_members.iec_number',
                'companies.is_freezed',
                'companies.date_freezed',
                DB::raw(
                    '(
                        SELECT COUNT(*)
                        FROM company_users
                        INNER JOIN workers ON workers.id = company_users.worker_id
                        WHERE company_users.company_id = companies.id
                            AND role_id = 5
                            AND email_verified_at IS NOT NULL
                    ) as no_of_employees'
                ), // 5 = Worker
                DB::raw('(SELECT COUNT(DISTINCT worker_id) FROM loan_approved_histories WHERE loan_approved_histories.loaner_company_id = companies.id GROUP BY loaner_company_id) as no_of_loaned_employees'),
                DB::raw('(SELECT COUNT(DISTINCT worker_id) FROM loan_approved_histories WHERE loan_approved_histories.borrower_company_id = companies.id GROUP BY borrower_company_id) as no_of_borrowed_employees')
            )
                ->leftJoin('company_subscriptions', 'company_subscriptions.company_id', '=', 'companies.id')
                ->leftJoin('iec_members', 'iec_members.company_id', '=', 'companies.id')
                ->with('company_expertises')
                ->when(!empty($expertiseSearch), function ($query) use ($expertiseSearch) {
                        $query->whereHas('company_expertises', function ($query) use ($expertiseSearch) {  
                            return $query->whereIn('company_expertises.expertise_id', $expertiseSearch);
                    });
                })
                ->when(!empty($nameSearch), function ($query) use ($nameSearch) {
                    return $query->where(function ($query) use ($nameSearch) {
                        $query->where('companies.name', 'LIKE', $nameSearch . '%');
                    });
                })
                ->when(!empty($chapterSearch), function ($query) use ($chapterSearch) {
                    return $query->where(function ($query) use ($chapterSearch) {
                        $query->where('iec_members.chapter_name', 'LIKE', $chapterSearch . '%');
                    });
                })
                ->when(!empty($memberCodeSearch), function ($query) use ($memberCodeSearch) {
                    return $query->where(function ($query) use ($memberCodeSearch) {
                        $query->where('iec_members.iec_number', 'LIKE', $memberCodeSearch . '%');
                    });
                })
                ->when(!empty($chapterSearch), function ($query) use ($chapterSearch) {
                    return $query->where(function ($query) use ($chapterSearch) {
                        $query->where('iec_members.chapter_name', 'LIKE', $chapterSearch . '%');
                    });
                })
                ->when(!empty($signupStatusSearch), function ($query) use ($signupStatusSearch) {
                    return $query->whereIn('companies.type', $signupStatusSearch);
                })
                ->when(!empty($accountStatusSearch), function ($query) use ($accountStatusSearch) {
                    return $query->whereIn(DB::raw('(CASE
                        WHEN companies.is_banned = true THEN "Active"
                        ELSE "Banned"
                    END )'), $accountStatusSearch);
                })
                ->when(($isBanned == 'true' || $isBanned == 'false'), function ($query) use ($isBanned) {
                    return $query->where('companies.is_banned', $isBanned);
                })
                ->when(!empty($expired), function ($query) use ($expired) {
                    return $query->where('company_subscriptions.is_expired', $expired);
                })
                ->when(!empty($blocked), function ($query) use ($blocked) {
                    return $query->where('company_subscriptions.is_blocked', $blocked);
                })
                ->when(!empty($almostExpired), function ($query) {
                    return $query->where('company_subscriptions.duration', '<=', Carbon::now()->addDays(4))
                        ->where('company_subscriptions.is_expired', 'false');
                })
                ->when(!empty($current), function ($query) use ($current) {
                    return $query->where('company_subscriptions.is_expired', 'false');
                })
                ->groupBy('companies.id')
                ->orderBy($sortField, $sortOrder)
                ->paginate(20)
        )->response()->setStatusCode(201);
    }

    public function getDetails($id)
    {
        return AdminCompanyAccountDetailsResource::collection(
            Company::select(
                'companies.id',
                'companies.name',
                'companies.street_address',
                'companies.city',
                'companies.state',
                'companies.zipcode',
                'companies.type',
                'companies.email_address',
                'companies.company_tel',
                'companies.company_tel2',
                'companies.contact_person_name',
                'iec_members.chapter_name',
                'iec_members.iec_number',
                'companies.is_freezed',
                'companies.date_freezed',
            )
                ->with('company_expertises')
                ->leftJoin('iec_members', 'iec_members.company_id', '=', 'companies.id')
                ->where('companies.id', $id)
                ->limit(1)
                ->get()
        )->response()->setStatusCode(201);
        
        
    }

    /*  return $payload->all(); */
    /*========================================================================================================
    Validate Query Param
    ========================================================================================================*/
    public function update($payload)
    {
        $rules = array(
            'company_id' => 'required',
            'company_name' => 'required|unique:companies,name,' . $payload->company_id,
            'company_number' => 'required',
            'office_number' => 'required',
            'company_number' => 'required',
            'contact_person_full_name' => 'required|max:70',
            'street_address' => 'required|max:50',
            'city' => 'required|max:50',
            'state' => 'required|max:50',
            'zipcode' => 'required|string|min:5|max:5',
            'contact_person_first_name' => 'required|max:50',
            'contact_person_last_name' => 'required|max:50',
            'email' => $payload->company_id ? 'required|unique:companies,email_address,' . $payload->company_id . '|max:191' : 'required',
            'iec_number' => $payload->iec_number ? 'required|max:50' : '',
            'chapter_name' => 'nullable|string|max:100',
        );

        $validate = $this->validateRequest($payload, $rules);
        if ($validate) {
            return response()->json(['success' => false, 'errors' => $validate->original['errors']])->setStatusCode(201);
        }

        /*========================================================================================================
        preparing company data to be saved on database
        ========================================================================================================*/

        $company_data = array(
            'id' => $payload->company_id,
            'name' => $payload->company_name,
            'company_tel' => "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->office_number),
            'company_tel2' => "+1" . str_replace(array('-', '(', ')', ' '), '', $payload->company_number),
            'street_address' => $payload->street_address,
            'city' => $payload->city,
            'state' => $payload->state,
            'zipcode' => $payload->zipcode,
            'email_address' => strtolower($payload->email),
            'contact_person_name' => $payload->contact_person_full_name,
            'service_charge' => $payload->service_charge,
            'discount' => $payload->discount,
        );

        $validate = $this->validatePhoneNumber($payload->office_number);
        if ($validate) {
            return response()->json(['errors' => ["Sorry, have used non-existing US mobile number in your company number."]])->setStatusCode(201);
        }

        $validate = $this->validateZipcodeIfExisting($payload->zipcode);
        if ($validate) {
            return $validate;
        }


        /*========================================================================================================
        Create a flag to enable to fire an event that regulates the search table.
        ========================================================================================================*/

        $old_company_details = Company::select('service_charge')->where('id', $payload->company_id)->first();

        $is_service_charge_not_change = (floatval($company_data['service_charge']) == $old_company_details->service_charge);

        /*========================================================================================================
        update company data to companies table
        ========================================================================================================*/

        Company::where('id', $company_data['id'])
            ->update($company_data);
        if (!$is_service_charge_not_change) {
            event(new ChangeCompanyServiceChargeEvent($company_data['service_charge'], $company_data['id']));
        }

        /*========================================================================================================
        update company eic data
        ========================================================================================================*/

       // if ($payload->chapter_name) {
        $chapterName = ucfirst(trim($payload->chapter_name ?? ''));
        
            $memberData = [
                'chapter_name' => $chapterName,
                'iec_number' => $chapterName,
                'is_confirmed' => true,
            ];
            IECMembers::where('company_id', $company_data['id'])->update($memberData);
       // }

        /*========================================================================================================
        Check for email update, If does send email verification
        ========================================================================================================*/
        $email_return = false;

        return [
            'success' => true,
            'email_update' => $email_return,
            'code' => 201,
        ];
    }

    public function verify($payload)
    {

        $code = $payload->code;
        $verification = EmailVerification::where(
            ['code' => $code]
        )
            ->first();
        if ($verification) {
            $verification->date_verified = Carbon::now();
            $verification->save();

            $company = Company::where(['id' => $verification->company_id])->first();
            $company->date_email_verified = Carbon::now();
            $company->save();
            return Redirect::to(env('APP_FRONT_URL'));
            /*  return $company; */
        } else {
            return Redirect::to(env('APP_FRONT_URL'));
            /*  return 'Error : Code not found.'; */
        }
    }

    public function sendEmailVerification($email_info)
    {
        DB::beginTransaction();

        try {
            $title = $email_info['title'];
            $name = $email_info['name'];
            $email = $email_info['email'];
            $token = hash('sha256', $plainTextToken = Str::random(80));
            $verification = new EmailVerification;
            $verification->company_id = $email_info['company_id'];
            $verification->code = $token;
            $verification->save();

            $details = [
                'name' => $name,
                'title' => $title,
                'verification_url' => stripslashes(url('/api/verify-email?code=' . $token)),
            ];
            /*     return $details; */
            $email_success = Mail::to($email)->send(new \App\Mail\Admin\Emailer($details));

            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
            return ['success' => false, 'message' => "Error in proccessing you request :" . $e];
        }

        return ['success' => true];
    }

    public function approvedPending($id, $payload)
    {
        DB::beginTransaction();

        $companyID = $id;

        // Validation
        $dataTobeValidated = array(
            'chapter_name' => $payload->chapter_name,
            'iec_number' => $payload->iec_number,
        );
        $rules = array(
            'chapter_name' => 'required|max:100',
        );
        $error = Validator::make($dataTobeValidated, $rules);
        if ($error->fails()) {
            return response()->json(['errors' => $error->errors()->all()]);
        }

        $companyData = [
            'type' => 'affiliated',
        ];
        $compayTransaction = Company::where('id', $companyID)->update($companyData);

        $memberData = [
            'is_confirmed' => true,
            'chapter_name' => $payload->chapter_name,
        ];

        $memberTransaction = IECMembers::where('company_id', $companyID)->update($memberData);

        if (!$compayTransaction || !$memberTransaction) {
            DB::rollback();
            return response()->json(['errors' => 'Something went wrong. Please reload the page']);
        } else {
            DB::commit();
            return response()->json(['success' => 'Company was successfully verified as an affiliate.']);
        }
    }
    public function unApprovedPending($id, $payload)
    {
        DB::beginTransaction();
        $companyID = $id;
        $companyData = [
            'type' => 'guest',
        ];
        $compayTransaction = Company::where('id', $companyID)->update($companyData);

        $memberTransaction = IECMembers::where('company_id', $companyID)->delete();

        if (!$compayTransaction || !$memberTransaction) {
            DB::rollback();
            return response()->json(['errors' => 'Something went wrong. Please reload the page']);
        } else {
            DB::commit();
            return response()->json(['success' => 'Company successfully converted as a guest.']);
        }
    }

    public function getSubscriptionDetails($id)
    {
        return CompanySubscriptions::select(
            'company_subscriptions.*',
            'companies.discount as commpany_discount',
            'company_subscription_rates.name as subscription_name',
        )
            ->join('companies', 'companies.id', 'company_subscriptions.company_id')
            ->join('company_subscription_rates', 'company_subscription_rates.id', 'company_subscriptions.subscription_rate_id')
            ->where('company_id', $id)->first();
    }

    public function adminShowCompanyDetails($id)
    {
        $company_id = $id;
        $company_info = CompanyResource::collection(
            Company::select(
                'companies.*',
                'iec_members.chapter_name',
                'iec_members.iec_number',
            )
                ->leftJoin('iec_members', 'iec_members.company_id', '=', 'companies.id')
                ->where('companies.id', $company_id)
                ->get()
        );
        return array(
            'company_detail' => $company_info[0],
            'billing_info' => [],
        );
    }
}
