<?php

namespace App\Http\Controllers\Front;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Property;
use App\Models\PropertyNearbySchool;
use App\Models\PropertyTransportNoise;
use App\Models\PropertySalesTrend;
use App\Models\PropertyDetailMortgage;
use App\Models\PropertyAllEventsDetail;
use App\Models\PropertyDetailOwner;
use App\Models\PropertyBuildingPermit;
use App\Models\PropertyRentalAvm;
use App\Models\User;
use App\Models\MortgageInformation;
use App\Models\OpportunityAlert;
use App\Models\ContactLoanOfficer;
use App\Models\State;
use App\Services\AtomApi;
use App\Services\AtomPropertyServices;
use App\Services\OpportunityAlertsServices;
use DB;
use App\Rules\ValidAmount;
use App\Mail\ContactLoanOfficerEmail;
use App\Models\Admin;
use Exception;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Carbon\Carbon;
use Google\Cloud\DocumentAI\V1\Client\DocumentProcessorServiceClient;
use Google\Cloud\DocumentAI\V1\ProcessRequest;
use Google\Cloud\DocumentAI\V1\RawDocument;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use App\Services\LenderPriceService;
use Illuminate\Support\Facades\Auth; 
use App\Jobs\RemoveTagAndUnsubscribeUser;
class MyAccountController extends Controller
{

    public $closing_cost;
    public $loanTermArray;

    /* Used for google document AI implementation */
    private $projectId;
    private $location;
    private $processorId;

    private LenderPriceService $lenderPriceService;
    

    public function __construct()
    {
        $this->closing_cost = 1000;
        $this->loanTermArray = [60, 84, 120, 180, 240, 300, 360];

        /* Set your Google Cloud Project ID, Location, and Processor ID */
        $this->projectId = env('GOOGLE_CLOUD_PROJECT_ID');
        $this->location = 'us'; // processor's location
        $this->processorId = env('GOOGLE_DOCUMENT_AI_PROCESSOR_ID');

        $this->lenderPriceService = new LenderPriceService();
        
    }

    //
    public function dashboard()
    {
        try {
            $myproperties = Property::with("mortgage_informations")
                ->where("user_id", auth()->id())
                ->get();

            if ($myproperties->isEmpty()) {
                Log::info('User has no properties, redirecting to add-property.', ['user_id' => auth()->id()]);
                //return redirect()->route('add-property');
            }

            $property = $myproperties->first();
            $mortgageInfo = $property->mortgage_informations ?? collect();
            /** 
             * is_property_details_completed = 0 that is property or mortgage info is completed
             * is_property_details_completed = 1 that is property or mortgage info is incomplete
             */
            session(['is_property_details_completed' => 0]);

            if ($myproperties->count() === 1) {

                // Check for missing required property fields
                if (!$this->isPropertyComplete($property)) {
                    session(['is_property_details_completed' => 1]);

                    /*
                    * Setting up redirect rout in session for dashboard modal pop up if property or mortgage information is incomplete
                    * If property details are not filled up, session will be set for adding property route which will be used in header whene there is pop up route handled
                    * If property details are filled up but mortgage information is not filled up, session will be set for adding property route which will be used in header whene there is pop up route handled
                    */
                    //session(['redirect_to' => "add-property"]);
                    session(['redirect_to' => route('edit-property', ['id' => $property->id])]);
                    Log::info('Incomplete property details, redirecting to edit-property.', [
                        'property_id' => $property->id,
                        'user_id' => auth()->id()
                    ]);
                    //return redirect()->route('edit-property', ['id' => $property->id]);
                }

                if ($mortgageInfo->isEmpty() || empty($mortgageInfo->first()->current_loan_balance)) {
                    session(['is_property_details_completed' => 1]);
                    session(['processing_alert_after_login_done' => 1]);
                    /*
                    * Setting up redirect rout in session for dashboard modal pop up if mortgage information is incompleted
                    * If property details are filled up but mortgage information is not filled up, session will be set for adding property route which will be used in header whene there is pop up route handled
                    */
                    session(['redirect_to' => route('mortage-information', ['property_id' => $property->id])]);

                    Log::info('Mortgage info missing or incomplete, redirecting to mortgage-information.', [
                        'property_id' => $property->id,
                        'user_id' => auth()->id()
                    ]);
                    //return redirect()->route('mortage-information', ['property_id' => $property->id]);
                }
            }

            $processing_alert_after_login_done = session('processing_alert_after_login_done');
            $is_property_details_completed = session('is_property_details_completed');
            // Process property data
            $myproperties->each(function ($value) {
                try {
                    $summary_array = [];

                    if (!empty($value->number_of_bedrooms)) {
                        $summary_array[] = "{$value->number_of_bedrooms} bd";
                    }
                    if (!empty($value->number_of_bathrooms)) {
                        $summary_array[] = "{$value->number_of_bathrooms} ba";
                    }
                    if (!empty($value->size_sqft)) {
                        $summary_array[] = "{$value->size_sqft} sqft";
                    }

                    $value->summary = implode(" | ", $summary_array);
                    $total_loan_balance = $value->mortgage_informations->sum("current_loan_balance");

                    if ($value->current_estimated_home_value > 0) {
                        $value->estimated_home_equity = $value->current_estimated_home_value - $total_loan_balance;
                    }

                    $value->current_rate = optional($value->mortgage_informations->first())->current_interest_rate
                        ? "{$value->mortgage_informations->first()->current_interest_rate}%"
                        : "";
                } catch (Exception $e) {
                    Log::error('Error processing property data.', [
                        'property_id' => $value->id ?? null,
                        'error' => $e->getMessage()
                    ]);
                }
            });

            $refinance_opportunity = ["current_rate" => "--"];
            $home_equity = ["home_equity_value" => "--"];
            $alert_types = [];

            if ($property) {
                try {
                    if ($mortgageInfo->isNotEmpty()) {
                        if (isset($mortgageInfo->first()->current_interest_rate)) {
                            $refinance_opportunity["current_rate"] = "{$mortgageInfo->first()->current_interest_rate}%";
                        }

                        if ($property->current_estimated_home_value > 0) {
                            $total_loan_balance = $mortgageInfo->sum("current_loan_balance");
                            $home_equity['home_equity_value'] = "$" . number_format($property->current_estimated_home_value - $total_loan_balance);
                        }
                    }

                    $alert_types = OpportunityAlert::select("alert_type", "property_id", DB::raw('count(*) as total'))
                        ->where("property_id", $property->id)
                        ->groupBy("alert_type")
                        ->get();
                } catch (ModelNotFoundException $e) {
                    Log::warning('No alerts found for property.', [
                        'property_id' => $property->id,
                        'error' => $e->getMessage()
                    ]);
                } catch (Exception $e) {
                    Log::error('Error fetching alert types.', [
                        'property_id' => $property->id,
                        'error' => $e->getMessage()
                    ]);
                }
            }

            /* Fetching URL from env for Get pre-approved to display on dashboard */
            $get_pre_approved_url = env("GET_PRE_APPROVED_URL");

            return view("front.myaccount.dashboard", compact(
                "myproperties",
                "refinance_opportunity",
                "home_equity",
                "alert_types",
                "get_pre_approved_url",
                "processing_alert_after_login_done",
                "is_property_details_completed"
            ));
        } catch (Exception $e) {
            Log::error('Unexpected error in dashboard.', [
                'user_id' => auth()->id(),
                'error' => $e->getMessage()
            ]);

            return redirect()->route('error-page')->with('error', 'Something went wrong. Please try again later.');
        }
    }

    public function getCurrentRateAndHomeEquity(Request $request)
    {
        $user_id = auth()->user()->id;
        $property_id = $request->property_id;

        $myproperty = Property::with("mortgage_informations")->where("id", $property_id)->where("user_id", auth()->user()->id)->first();

        $return_value = [];
        $return_value["current_rate"] = "--";
        $return_value['home_equity_value'] = "--";
        $return_value['alert_types'] = [];
        if ($myproperty) {
            if (!empty($myproperty->mortgage_informations)) {
                if (isset($myproperty->mortgage_informations[0]->current_interest_rate)) {
                    $return_value["current_rate"] = $myproperty->mortgage_informations[0]->current_interest_rate . "%";
                }

                if (floatval($myproperty->current_estimated_home_value ?? 0) > 0) {
                    $total_loan_balance = $myproperty->mortgage_informations->sum("current_loan_balance");
                    $return_value['home_equity_value'] = "$" . number_format($myproperty->current_estimated_home_value - $total_loan_balance);
                }
            }

            /// check if there is any alert for this property ========
            $return_value['alert_types'] = OpportunityAlert::select("alert_type", "property_id", DB::raw('count(*) as total'))->where("property_id", $myproperty->id)->groupBy("alert_type")->get();
        }

        return $return_value;
    }

    public function mortgage_information(Request $request)
    {
        try {
            $user_id = auth()->user()->id;  // Optimized user retrieval

            $property = Property::where("id", $request->property_id)
                ->where("user_id", $user_id)
                ->first();

            if (!$property) {
                Log::warning('Property not found or does not belong to user.', [
                    'property_id' => $request->property_id,
                    'user_id' => $user_id
                ]);
                abort(404);
            }

            // Check for missing required property fields
            if (!$this->isPropertyComplete($property)) {
                Log::info('Incomplete property details, redirecting to edit-property.', [
                    'property_id' => $property->id,
                    'user_id' => $user_id
                ]);
                return redirect()->route('edit-property', ['id' => $property->id]);
            }

            return view("front.myaccount.mortgage-information", compact('property'));
        } catch (ModelNotFoundException $e) {
            Log::error('Property not found.', [
                'property_id' => $request->property_id,
                'user_id' => auth()->id(),
                'error' => $e->getMessage()
            ]);
            abort(404);
        } catch (Exception $e) {
            Log::critical('Unexpected error in mortgage_information.', [
                'user_id' => auth()->id(),
                'property_id' => $request->property_id,
                'error' => $e->getMessage()
            ]);
            return redirect()->route('error-page')->with('error', 'Something went wrong. Please try again later.');
        }
    }

    /**
     * Check if the property has all required fields filled.
     * Returns bool value
     */
    private function isPropertyComplete($property)
    {
        return !empty($property->zipcode) &&
            !empty($property->state) &&
            !empty($property->property_type) &&
            !empty($property->occupancy) &&
            !empty($property->current_estimated_home_value);
    }


    public function save_mortgage_information(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("id", $request->property_id)->where("user_id", $user_id)->first();

        $rules = [
            "property_id" => "required",
            "current_interest_rate_1" => "required|numeric", // |min:0.01:max:30
            // "current_loan_balance_1" => "required|numeric", // |min:1
            "current_loan_balance_1" => ["required", new ValidAmount()], // |min:1
            "loan_term_1" => "required",
            "loan_program_1" => "required",
            "loan_type_1" => "required",
            "original_loan_balance_1" =>  ["required", new ValidAmount()], //"required|numeric", // |min:1
            "pmi_1" => "required",
            "mortgage_start_date_1" => "required",
            "monthly_pmi_payment_1" => "required_if:pmi_1,'==',Y",
            "estimated_credit_score_1" => "required|numeric", // |min:1
        ];

        if (!empty($request->secondmortgage)) {
            $rules["current_loan_balance_2"] =  ["required", new ValidAmount()]; // "required|numeric"; // |min:1

        }

        $request->validate($rules);

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Invalid Property"
            ];
        }

        $mortgage_count = MortgageInformation::where("user_id", $user_id)->where("property_id", $request->property_id)->count();

        if ($mortgage_count == 2) {
            return [
                "success" => 0,
                "message" => "You have already added mortgage information for this property"
            ];
        }

        $request->merge([
            'current_loan_balance_1' => removeCommaFromAmount($request->current_loan_balance_1),
            'original_loan_balance_1' => removeCommaFromAmount($request->original_loan_balance_1),
            'monthly_pmi_payment_1' => removeCommaFromAmount($request->monthly_pmi_payment_1)
        ]);

        if (!empty($request->secondmortgage)) {
            $request->merge([
                'current_loan_balance_2' => removeCommaFromAmount($request->current_loan_balance_2)
            ]);
        }

        //$mortgage_count == 1 means 1st mortgage info is already there and need to update
        if ($mortgage_count == 1) {
            $mortgage_info = MortgageInformation::where("user_id", $user_id)->where("property_id", $request->property_id)->first();
            $mortgage_info = MortgageInformation::find($mortgage_info->id);

            $mortgage_info->current_loan_balance = removeCommaFromAmount($request->current_loan_balance_1);

            $mortgage_info->current_interest_rate = $request->current_interest_rate_1;
            $mortgage_info->loan_term = $request->loan_term_1;
            $mortgage_info->loan_program = $request->loan_program_1;
            $mortgage_info->loan_type = $request->loan_type_1;
            $mortgage_info->original_loan_balance = removeCommaFromAmount($request->original_loan_balance_1);
            $mortgage_info->pmi = $request->pmi_1;
            $mortgage_info->mortgage_start_date = formatMortgageDateForMysql($request->mortgage_start_date_1);
            $mortgage_info->monthly_pmi_payment = removeCommaFromAmount($request->monthly_pmi_payment_1 ?? 0);
            $mortgage_info->estimated_credit_score = $request->estimated_credit_score_1 ?? null;
            $mortgage_info->save();
        } else {
            //$mortgage_count is not 1 or not 2 means need to add mortgage information
            MortgageInformation::create([
                "user_id" => $user_id,
                "property_id" => $request->property_id,
                "current_interest_rate" => $request->current_interest_rate_1,
                "current_loan_balance" => $request->current_loan_balance_1,
                "loan_term" => $request->loan_term_1,
                "loan_program" => $request->loan_program_1,
                "loan_type" => $request->loan_type_1,
                "original_loan_balance" => $request->original_loan_balance_1,
                "pmi" => $request->pmi_1,
                "mortgage_start_date" => formatMortgageDateForMysql($request->mortgage_start_date_1),
                "monthly_pmi_payment" => $request->monthly_pmi_payment_1 ?? 0,
                "estimated_credit_score" => $request->estimated_credit_score_1
            ]);
        }

        if (!empty($request->secondmortgage) && $request->secondmortgage == "yes") {
            //secondmortgage is yes means user added 2nd loan balance and so need to add into the DB
            MortgageInformation::create([
                "user_id" => $user_id,
                "property_id" => $request->property_id,
                "current_loan_balance" => $request->current_loan_balance_2
            ]);
        }

        return [
            "success" => 1,
            "message" => "Successfully saved",
            "redirectTo" => route("dashboard")
        ];
    }


    /**
     * Author : Gurupriya Solanki
     * Desciption : State should be show in select option list
     * Update Date: 4 Sep 2024
     */
    public function add_property(Request $request)
    {
        // $request->merge(['a' => str_ireplace(",", "", $request->a)]);
        // dd($request->all());
        session(['processing_alert_after_login' => 0]);
        //Fetch Satets
        $states = State::all();
        $states = $states->map(function ($sl) {
            return [
                "id" => $sl->id,
                "label" => ($sl->name . " - " . $sl->state_code),
                "value" => ($sl->state_code)
            ];
        });

        return view("front.myaccount.add-property", compact('states'));
    }

    /*
    * Author: Vidhi Shah
    * Updated: 12th jun 2024
    * Description: This action is used to store property related data as well mortgage information into databas
    * Fixed issue: Unable to upload mortgage statement because of mortgage start date field is undefined in this case.
    * Updated: 18th jun 2024, Removed upload mortgage code from this action becuase this feature has been removed from the user end.

    * Author : Gurupriya Solanki
    * Desciption : State should be show in select option list and Save
    * Update Date: 4 Sep 2024
    *
    * Author: Vidhi Shah
    * Update Date: 5th Sep 2024
    * Desciption: Updated function for capturing number_of_units while creating property
    */
    public function save_property(Request $request)
    {

        $rules = [
            "estimated_credit_score" => "required_if:info_option,ENTER_MANUALLY",
            "city" => "required_if:info_option,ENTER_MANUALLY",
            "state" => "required_if:info_option,ENTER_MANUALLY",
            "address" => "required_if:info_option,ENTER_MANUALLY",
            "property_type" => "required_if:info_option,ENTER_MANUALLY",
            "occupancy" => "required",
            "current_estimated_home_value" => ["required", new ValidAmount()],
            "mortgage_statement" => "required_if:info_option,UPLOAD",
            "property_tax" => ["nullable", new ValidAmount()],
            "home_insurance" => ["nullable", new ValidAmount()]

        ];

        $messages = [
            "city.required_if" => "Please enter city",
            "state.required_if" => "Please select state",
            "address.required_if" => "Please enter address",
            "mortgage_statement.required_if" => "Please upload mortgage statement",
            "property_type.required_if" => "Please select property type"
        ];


        if ($request->info_option == "ENTER_MANUALLY") {
            $rules["zipcode"] = "required|digits:5";
            $rules["current_interest_rate"] = "required|numeric";

            $rules["current_loan_balance"] = ["required", new ValidAmount()];
            $rules["original_loan_balance"] = ["required", new ValidAmount()];
        }

        if (!empty($request->secondmortgage) && $request->secondmortgage == "yes") {
            $rules["current_loan_balance_2"] =  ["required", new ValidAmount()]; // "required|numeric"; // |min:1
        }

        $request->validate($rules, $messages);

        $request->merge([
            'current_loan_balance' => removeCommaFromAmount($request->current_loan_balance),
            'original_loan_balance' => removeCommaFromAmount($request->original_loan_balance),
            'property_tax' => removeCommaFromAmount($request->property_tax),
            'home_insurance' => removeCommaFromAmount($request->home_insurance),
            'monthly_pmi_payment' => removeCommaFromAmount($request->monthly_pmi_payment),
            'current_estimated_home_value' => removeCommaFromAmount($request->current_estimated_home_value)
        ]);

        if (!empty($request->secondmortgage)) {
            $request->merge([
                'current_loan_balance_2' => removeCommaFromAmount($request->current_loan_balance_2),
            ]);
        }
        // return [
        //     "success" => 0,
        //     "message" => "All OK"
        // ];

        /* Author: Vidhi Shah
        * Update Date: 15 Nov 2024
        * Description: should allow image files as well*/
        /* if ($request->has('mortgage_statement')) {
            $orignal_filename = $request->file('mortgage_statement')->getClientOriginalName();
            $extension = pathinfo($orignal_filename, PATHINFO_EXTENSION);

            if (!in_array($extension, ["pdf", "xls", "xlsx", "jpeg", "png", "jpg"])) {
                return [
                    "success" => 0,
                    "message" => "Please upload pdf/xls/xlsx/jpeg/jpg/png file only"
                ];
            }

            $mortgage_statement = basename($request->file('mortgage_statement')->store('public/mortgage_statements'));
        } else {
            $mortgage_statement = "";
        } */
        $mortgage_statement = "";
        $mortgage_start_date = $request->mortgage_start_date ? formatMortgageDateForMysql($request->mortgage_start_date) : "";
        // save property and mortgage information
        try {
            $user = auth()->user();
            $user_id = auth()->user()->id;
            $assigned_to = null;
            if (!empty($user->partner_id) && $user->partner_id > 0) {
                $assigned_to = (!empty($user->assigned_to)) ? $user->assigned_to : null;
            }
            //check duplicate property ====
            $property_count = Property::where("address", $request->address)->where("city", $request->city)->where("zipcode", $request->zipcode)->where("occupancy", $request->occupancy)->count();
            if ($property_count > 0) {
                throw new \Exception("Oops! this property already exists in our database");
            }

            $property = Property::create([
                "user_id" => $user_id,
                "address" => $request->address,
                "city" => $request->city,
                "state" => $request->state,
                "zipcode" => $request->zipcode,
                "property_type" => $request->property_type,
                "property_type_other" => $request->property_type_other,
                "occupancy" => $request->occupancy,
                "info_option" => $request->info_option,
                "property_tax" => $request->property_tax,
                "home_insurance" => $request->home_insurance,
                "number_of_units" => ($request->property_type === "Multi-unit") ? $request->property_unit : 1,
                "assigned_to" => $assigned_to ?? null,
                "current_estimated_home_value" => $request->current_estimated_home_value
            ]);

            if ($property) {
                MortgageInformation::create([
                    "user_id" => $user_id,
                    "property_id" => $property->id,
                    "current_interest_rate" => $request->current_interest_rate,
                    "current_loan_balance" => $request->current_loan_balance,
                    "original_loan_balance" => $request->original_loan_balance,
                    "loan_term" => $request->loan_term,
                    "loan_program" => $request->loan_program,
                    "loan_type" => $request->loan_type,
                    // "original_loan_balance" => $request->original_loan_balance,
                    "pmi" => $request->pmi,
                    "mortgage_start_date" => $mortgage_start_date,
                    "monthly_pmi_payment" => $request->monthly_pmi_payment ?? 0,
                    "estimated_credit_score" => $request->estimated_credit_score ?? 0,
                    "mortgage_statement" => $mortgage_statement
                ]);
                

                if (!empty($request->secondmortgage) && $request->secondmortgage == "yes") {
                    MortgageInformation::create([
                        "user_id" => $user_id,
                        "property_id" => $property->id,
                        "current_interest_rate" => null,
                        "current_loan_balance" => $request->current_loan_balance_2,
                        "loan_term" => null,
                        "loan_program" => null,
                        "loan_type" => null,
                        "original_loan_balance" => null,
                        "pmi" => null,
                        "mortgage_start_date" => null,
                        "monthly_pmi_payment" => null,
                        "estimated_credit_score" => 0
                    ]);
                }
                /// pull all atom data here =================
                try {
                    dispatch(new RemoveTagAndUnsubscribeUser($user_id, env('MAILCHIMP_LIST_ID')));

                    $property_id = $property->id;
                    dispatch(function () use ($property_id) {
                        $service = new AtomPropertyServices;
                        $service->call_property_expandedprofile($property_id);
                        // $service->call_near_by_schools($property_id);
                        // $service->call_transportation_noise($property_id);
                        $service->call_sales_trend($property_id);
                        $service->call_property_detailmortgage($property_id);
                        $service->call_allevents_detail($property_id);
                        // $service->call_property_detailowner($property_id);
                        // $service->call_property_buildingpermits($property_id);
                        $service->call_property_rentalavm($property_id);
                    });
                } catch (\Exception $e) {
                }

                return [
                    "success" => 1,
                    "message" => "Property successfully added",
                    "redirectTo" => route("dashboard")
                ];
            } else {
                throw new \Exception("Something went wrong. Please try after sometime.");
            }
        } catch (\Exception $e) {
            return [
                "success" => 0,
                "message" => $e->getMessage()
            ];
        }
    }

    public function property_detail(Request $request)
    {

        return view("front.myaccount.property-detail");
    }

    public function all_property(Request $request)
    {
        $allproperties = Property::where("user_id", auth()->user()->id)->get();


        // $address1 = "4529 Winona Court";
        // $address2 = "Denver, CO";
        // // return (new AtomApi)->property_expandedprofile(0, 0, "", "", $address1, $address2);

        // return (new AtomApi)->valuation_homeequity(0, 0, "", "", $address1, $address2);

        $allproperties->each(function ($property) {
            if (floatval($property->current_estimated_home_value ?? 0) > 0) {
                $total_loan_balance = $property->mortgage_informations->sum("current_loan_balance");
                $property->estimated_home_equity = ($property->current_estimated_home_value - $total_loan_balance);
            }
        });


        return view('front.myaccount.all-property', compact('allproperties'));
    }

    public function fetch_data_atomapi(Request $request)
    {
        // return $request->all();
        $property_id = $request->property_id;
        $user_id = auth()->user()->id;

        $property = Property::where("user_id", $user_id)->where("id", $property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }


        $address1 = $property->address;
        $address2 = $property->city . "," . $property->state;

        $errors_array = [];
        $property_expandedprofile = (new AtomApi)->property_expandedprofile($user_id, $property_id, "all-property", "user", $address1, $address2);
        if ($property_expandedprofile['success'] == 1) {
            
            $attomId = $property_expandedprofile['response']->property[0]->identifier->attomId;
            $allevents_details = $this->allevents_details($property->user_id, $property->id, "atom-property-services", "jobs", $attomId);
            $current_estimated_home_value = "";
            if($allevents_details['success'] == 1) {
                if(!empty($allevents_details['response']->property)) {
                    $current_estimated_home_value = $allevents_details['response']->property[0]->avm->amount->value ?? null;
                }
            }
            $property->number_of_bedrooms = $property_expandedprofile['response']->property[0]->building->rooms->beds ?? null;
            $property->number_of_bathrooms = $property_expandedprofile['response']->property[0]->building->rooms->bathsTotal ?? null;
            $property->size_sqft = $property_expandedprofile['response']->property[0]->building->size->livingSize ?? null;
            $property->current_estimated_home_value = $current_estimated_home_value ?? $property_expandedprofile['response']->property[0]->assessment->market->mktTtlValue ?? null;

            $property->attomid = $property_expandedprofile['response']->property[0]->identifier->attomId ?? null;
            $property->geoidv4_n1 = $property_expandedprofile['response']->property[0]->location->geoIdV4->N1 ?? $property_expandedprofile['response']->property[0]->location->geoIdV4->N2 ?? null;

            $property->save();
        } else {
            $errors_array[] = "Property Detail: " . $property_expandedprofile['message'];
        }
        /*
        $valuation_homeequity = (new AtomApi)->valuation_homeequity($user_id, $property_id, "all-property", "user", $address1, $address2);

        if($valuation_homeequity['success'] == 1) {
            $property->estimated_home_equity = $valuation_homeequity['response']->property[0]->homeEquity->estimatedAvailableEquity;
            $property->save();
        } else {
            $errors_array[] = "Home Equity: " . $valuation_homeequity['message'];
        }

        if(count($errors_array) == 2) {
            return [
                "success" => 0,
                "message" => implode(",", $errors_array)
            ];
        }
        */

        if (floatval($property->current_estimated_home_value ?? 0) > 0) {
            $total_loan_balance = $property->mortgage_informations->sum("current_loan_balance");
            $property->estimated_home_equity = ($property->current_estimated_home_value - $total_loan_balance);
        }

        $property->current_estimated_home_value = number_format($property->current_estimated_home_value);
        $property->estimated_home_equity = number_format($property->estimated_home_equity);



        return [
            "success" => 1,
            "message" => implode(",", $errors_array),
            "property" => $property
        ];
    }

    public function fetch_data_atomapi_by_address(Request $request)
    {
        $address1 = $request->address;
        $address2 = $request->city . "," . $request->state;
        $user_id = auth()->user()->id;
        $bypass_property_check = $request->bypass_property_check ?? false;


        if (!$bypass_property_check) {
            $property_count = Property::where("address", $request->address)->where("city", $request->city)->where("zipcode", $request->zipcode)->where("occupancy", $request->occupancy)->count();
            if ($property_count > 0) {
                return [
                    "success" => 0,
                    "message" => "Oops! this property already exists in our database"
                ];
            }
        }

        $property_expandedprofile = (new AtomApi)->property_expandedprofile($user_id, 0, "add-property", "user", $address1, $address2);

        return $property_expandedprofile;
    }


    public function change_password(Request $request)
    {

        return view("front.myaccount.change-password");
    }

    public function save_password(Request $request)
    {
        $request->validate([
            "current_password" => "required",
            "new_password" => "required",
            "confirm_password" => "required|same:new_password"
        ]);

        if (!\Hash::check($request->current_password, auth()->user()->password)) {
            return [
                "success" => 0,
                "message" => 'The current password is incorrect.'
            ];
        }

        $user_id = auth()->user()->id;

        User::where("id", $user_id)->update([
            "password" => \Hash::make($request->new_password)
        ]);

        return [
            "success" => 1,
            "message" => "Successfully updated"
        ];
    }

    public function edit_property(Request $request)
    {
        $property_id = $request->id;
        $user_id = auth()->user()->id;

        $property = Property::where("user_id", $user_id)->where("id", $property_id)->first();

        if (!$property) {
            abort(404);
        }

        $mortgage_infos = MortgageInformation::where("user_id", $user_id)->where("property_id", $property_id)->get();
        // If no mortgage records exist, provide a default empty structure
        if ($mortgage_infos->isEmpty()) {
            $mortgage_infos = collect([(object)[
                'id' => null,
                'current_interest_rate' => null,
                'current_loan_balance' => null,
                'loan_term' => null,
                'loan_program' => null,
                'loan_type' => null,
                'pmi' => null,
                'mortgage_start_date' => null,
                'monthly_pmi_payment' => null,
                'original_loan_balance' => null,
                'estimated_credit_score' => null
            ]]);
        }
        //Fetch Satets
        $states = State::all();
        $states = $states->map(function ($sl) {
            return [
                "id" => $sl->id,
                "label" => ($sl->name . " - " . $sl->state_code),
                "value" => ($sl->state_code)
            ];
        });

        return view("front.myaccount.edit-property", compact('property', 'mortgage_infos', 'states'));
    }

    /**
     * Author : Gurupriya Solanki
     * Desciption : State should be show in select option list And Save
     * Update Date: 4 Sep 2024
     * 
     * Author: Vidhi Shah
     * Update Date: 5th Sep 2024
     * Desciption: Updated function for capturing number_of_units while updating property
     */
    public function update_property(Request $request) 
    {
        try {
            // Validate input
            $request->validate([
                "property_id" => "required",
                "city" => "required",
                "state" => "required",
                "address" => "required",
                "zipcode" => "required|digits:5",
                "property_type" => "required",
                "occupancy" => "required",
                "property_tax" => ["nullable", new ValidAmount()],
                "home_insurance" => ["nullable", new ValidAmount()],
                "current_estimated_home_value_0" => ["nullable", new ValidAmount()],    
            ]);

            $user = Auth::user();
            $property = Property::where("user_id", $user->id)
                                ->where("id", $request->property_id)
                                ->first();

            if (!$property) {
                Log::error("Property not found for user_id: {$user->id}, property_id: {$request->property_id}");
                return response()->json(["success" => 0, "message" => "Something went wrong. Please try again."]);
            }

            // Assign property fields
            $property->fill([
                "address" => $request->address,
                "city" => $request->city,
                "state" => $request->state,
                "zipcode" => $request->zipcode,
                "property_type" => $request->property_type,
                "property_type_other" => $request->property_type_other,
                "occupancy" => $request->occupancy,
                "property_tax" => removeCommaFromAmount($request->property_tax),
                "home_insurance" => removeCommaFromAmount($request->home_insurance),
                "number_of_units" => ($request->property_type === "Multi-unit") ? $request->property_unit : 1,
                "assigned_to" => $user->partner_id ? ($user->assigned_to ?? null) : ($property->assigned_to ?? null),
                "current_estimated_home_value" => removeCommaFromAmount($request->current_estimated_home_value_0),
            ]);

            $property->save();
            Log::info("Property updated successfully", ["user_id" => $user->id, "property_id" => $property->id]);

            // Handle mortgages
            $mortgage_count = MortgageInformation::where("user_id", $user->id)
                                                ->where("property_id", $property->id)
                                                ->count();

            collect($request->mortgage_id ?? [0])->each(function ($mortgage_id, $idx) use ($request, $user) {
                $this->updateOrCreateMortgage($mortgage_id, $idx, $request, $user);
            });

            
            // If only one mortgage exists, add a second one
            if (($mortgage_count == 1 && isset($request->current_loan_balance_2) && $request->current_loan_balance_2) || ($mortgage_count == 0 && isset($request->current_loan_balance_2) && $request->current_loan_balance_2)) {
             
                MortgageInformation::create([
                    "user_id" => $user->id,
                    "property_id" => $request->property_id,
                    "current_loan_balance" => removeCommaFromAmount($request->current_loan_balance_2),
                ]);
                Log::info("Second mortgage added for property", ["user_id" => $user->id, "property_id" => $request->property_id]);
            }

            //If already Two records are are exist then second will be update in case of value has removed as the time of edit. And now User want to enter the value 
            if ($mortgage_count == 2 && isset($request->current_loan_balance_2) && $request->current_loan_balance_2) {
    
                $mortgage_info = MortgageInformation::where("id", $request->mortgage_id[1])->first();
                
                if ($mortgage_info) {
                    $mortgage_info->update([
                        "current_loan_balance" => removeCommaFromAmount($request->current_loan_balance_2)
                    ]);
                    
                    Log::info("Second mortgage updated for property", [
                        "user_id" => $user->id, 
                        "property_id" => $request->property_id
                    ]);
                }
            }
            
            
            try {
                dispatch(new RemoveTagAndUnsubscribeUser($user->id, env('MAILCHIMP_LIST_ID')));
                Log::info("Dispatched RemoveTagAndUnsubscribeUser job", ['user_id' => $user->id]);
            } catch (\Throwable $e) {
                Log::error("Failed to dispatch RemoveTagAndUnsubscribeUser job", [
                    'user_id' => $user->id,
                    'error' => $e->getMessage()
                ]);
            }
            return response()->json(["success" => 1, "message" => "Successfully saved. Redirecting..."]);
        } catch (\Exception $e) {
            Log::error("Error updating property", ["error" => $e->getMessage(), "trace" => $e->getTraceAsString()]);
            return response()->json(["success" => 0, "message" => "An error occurred. Please try again later."]);
        }
    }

    /**
     * Update or create mortgage information
     */
    private function updateOrCreateMortgage($mortgage_id, $idx, $request, $user)
    {
        try {
            $current_loan_balance = request("current_loan_balance_$idx");
            $mortgage_data = [
                "user_id" => $user->id,
                "property_id" => $request->property_id,
                "current_loan_balance" => removeCommaFromAmount($current_loan_balance),
            ];

            if ($idx == 0) {
                
                $mortgage_data += [
                    "current_interest_rate" => request("current_interest_rate_$idx"),
                    "loan_term" => request("loan_term_$idx"),
                    "loan_program" => request("loan_program_$idx"),
                    "loan_type" => request("loan_type_$idx"),
                    "original_loan_balance" => removeCommaFromAmount(request("original_loan_balance_$idx")),
                    "pmi" => request("pmi_$idx"),
                    "mortgage_start_date" => formatMortgageDateForMysql(request("mortgage_start_date_$idx")),
                    "monthly_pmi_payment" => removeCommaFromAmount(request("monthly_pmi_payment_$idx") ?? 0),
                    "estimated_credit_score" => request("estimated_credit_score_$idx"),
                ];

            }
            
            if (empty($mortgage_id) || $mortgage_id == 0) {
                MortgageInformation::create($mortgage_data);
                Log::info("New mortgage record created", ["user_id" => $user->id, "property_id" => $request->property_id]);
            } else {
                $mortgage_info = MortgageInformation::find($mortgage_id);
                if ($mortgage_info) {
                    $mortgage_info->update($mortgage_data);
                    Log::info("Mortgage record updated", ["mortgage_id" => $mortgage_id]);
                } else {
                    Log::warning("Mortgage record not found", ["mortgage_id" => $mortgage_id]);
                }
            }
        } catch (\Exception $e) {
            Log::error("Error updating mortgage", ["error" => $e->getMessage(), "trace" => $e->getTraceAsString()]);
        }
    }



    public function loan_info(Request $request)
    {
        $property_id = $request->property_id;
        $user_id = auth()->user()->id;

        // $property = Property::find($property_id);


        $myproperties = Property::with("mortgage_informations")->whereHas("mortgage_informations")->where("user_id", $user_id)->where("id", $property_id)->get();
        if (!$myproperties) {
            abort(404);
        }
        // return view("front.myaccount.my-loans", compact('myproperties'));

        // $mortgage_list = MortgageInformation::where("user_id", $user_id)->where("property_id", $property_id)->get();

        return view("front.myaccount.loan-info", compact('myproperties'));
    }

    public function edit_loan_info(Request $request)
    {
        $property_id = $request->property_id;
        $id = $request->id;
        $user_id = auth()->user()->id;

        $property = Property::find($property_id);
        if (!$property) {
            abort(404);
        }

        $mortgage_info = MortgageInformation::with("property")->where("user_id", $user_id)->where("property_id", $property_id)->where("id", $id)->first();
        if (!$mortgage_info) {
            abort(404);
        }

        return view("front.myaccount.edit-loan-info", compact('mortgage_info'));
    }

    public function update_loan_info(Request $request)
    {
        $property_id = $request->property_id;
        $id = $request->id;
        $user_id = auth()->user()->id;
        $mortgage_info = MortgageInformation::with("property")->where("user_id", $user_id)->where("property_id", $property_id)->where("id", $id)->first();
        if (!$mortgage_info) {
            return [
                "success" => 0,
                "message" => "Invalid request"
            ];
        }

        $request->merge([
            "mortgage_start_date" => formatMortgageDateForMysql($request->mortgage_start_date)
        ]);

        $mortgage_info->current_interest_rate = $request->current_interest_rate;
        $mortgage_info->current_loan_balance = removeCommaFromAmount($request->current_loan_balance);
        $mortgage_info->loan_term = $request->loan_term;
        $mortgage_info->loan_program = $request->loan_program;
        $mortgage_info->loan_type = $request->loan_type;
        $mortgage_info->original_loan_balance = removeCommaFromAmount($request->original_loan_balance);
        $mortgage_info->pmi = $request->pmi;
        $mortgage_info->mortgage_start_date = $request->mortgage_start_date;
        $mortgage_info->monthly_pmi_payment = removeCommaFromAmount($request->monthly_pmi_payment ?? 0);
        $mortgage_info->estimated_credit_score = $request->estimated_credit_score ?? null;
        // $mortgage_info->current_credit_score = $request->current_credit_score;
        $mortgage_info->save();

        return [
            "success" => 1,
            "message" => "Successfully saved"
        ];
    }

    public function home_detail(Request $request)
    {
        $property = Property::where("user_id", auth()->user()->id)->where("id", $request->id)->first();

        if (!$property) {
            abort(404);
        }

        $summary_array = [];

        if (!empty($property->number_of_bedrooms)) {
            $summary_array[] = $property->number_of_bedrooms . " bd";
        }

        if (!empty($property->number_of_bathrooms)) {
            $summary_array[] = $property->number_of_bathrooms . " ba";
        }

        if (!empty($property->size_sqft)) {
            $summary_array[] = $property->size_sqft . " sqft";
        }

        $property->summary = implode(" | ", $summary_array);

        $schools = PropertyNearbySchool::where("property_id", $property->id)->get();
        $property_transportationnoises = PropertyTransportNoise::where("property_id", $property->id)->get();
        $sales_trends = PropertySalesTrend::where("property_id", $property->id)->orderBy("start_year", "DESC")->get();


        $mortgage_detail = PropertyDetailMortgage::where("property_id", $property->id)->first();

        if ($mortgage_detail) {
            if ($mortgage_detail->duedate) {
                $mortgage_detail->duedate = date("m-d-Y", strtotime($mortgage_detail->duedate));
            }

            if ($mortgage_detail->mort_date) {
                $mortgage_detail->mort_date = date("m-d-Y", strtotime($mortgage_detail->mort_date));
            }
        }

        $all_event_detail = PropertyAllEventsDetail::where("property_id", $property->id)->first();
        if ($all_event_detail) {
            $all_event_detail->avm = [];
            if (!empty($all_event_detail->api_response)) {
                $all_event_detail->api_response = json_decode($all_event_detail->api_response);
                $all_event_detail->avm = $all_event_detail->api_response->property[0]->avm;
            }
        }

        $property_detailowner = PropertyDetailOwner::where("property_id", $property->id)->first();
        if ($property_detailowner) {
            $property_detailowner->owner_detail = [];
            if (!empty($property_detailowner->api_response)) {
                $property_detailowner->api_response = json_decode($property_detailowner->api_response);
                $property_detailowner->owner_detail = $property_detailowner->api_response->property[0]->owner;
            }
        }

        $buildingpermits = PropertyBuildingPermit::where("property_id", $property->id)->get();
        $buildingpermits->each(function ($value) {
            $value->effectivedate1 = "";
            if ($value->effectivedate) {
                $value->effectivedate1 = $value->effectivedate->format('m-d-Y');
            }
        });

        if (floatval($property->current_estimated_home_value ?? 0) > 0) {
            $total_loan_balance = $property->mortgage_informations->sum("current_loan_balance");
            $property->estimated_home_equity = ($property->current_estimated_home_value - $total_loan_balance);
        }

        $rentalavms = PropertyRentalAvm::where("property_id", $property->id)->limit(1)->latest()->get();
        $rentalavms->each(function ($value) {
            $value->valuation_date1 = "";
            if ($value->valuation_date) {
                $value->valuation_date1 = $value->valuation_date->format('m-d-Y');
            }

            $value->estimated_rental_value = "$" . number_format($value->estimated_rental_value);
            $value->estimated_min_rental_value = "$" . number_format($value->estimated_min_rental_value);
            $value->estimated_max_rental_value = "$" . number_format($value->estimated_max_rental_value);
        });


        return view('front.myaccount.home-detail', compact('property', 'schools', 'property_transportationnoises', 'sales_trends', 'mortgage_detail', 'all_event_detail', 'property_detailowner', 'buildingpermits', 'rentalavms'));
    }

    //// call/save nearby schools =======================
    public function fetch_near_by_schools(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "No school found"
            ];
        }

        $property_detailwithschools = (new AtomApi)->property_detailwithschools($user_id, $property->id, "home-detail", "user", $property->attomid);

        if ($property_detailwithschools['success'] == 1) {
            if (!empty($property_detailwithschools['response']->property[0]->school)) {
                ///======== delete existing ==============
                PropertyNearbySchool::where("property_id", $property->id)->delete();

                foreach ($property_detailwithschools['response']->property[0]->school as $school) {
                    PropertyNearbySchool::create([
                        "property_id" => $property->id,
                        "geoidv4" => $school->geoIdV4,
                        "institutionname" => $school->InstitutionName,
                        "gstestrating" => $school->GSTestRating,
                        "schoolrating" => $school->schoolRating,
                        "gradelevel1lotext" => $school->gradelevel1lotext,
                        "gradelevel1hitext" => $school->gradelevel1hitext,
                        "lowassignedgrade" => $school->lowAssignedGrade,
                        "highassignedgrade" => $school->highAssignedGrade,
                        "filetypetext" => $school->Filetypetext,
                        "geocodinglatitude" => $school->geocodinglatitude,
                        "geocodinglongitude" => $school->geocodinglongitude,
                        "distance" => $school->distance
                    ]);
                }
            }
        }

        $schools = PropertyNearbySchool::where("property_id", $property->id)->get();


        return [
            "success" => 1,
            "message" => "",
            "schools" => $schools
        ];
    }

    //// call/save transportation noise =================
    public function fetch_transportation_noise(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Nothing found"
            ];
        }

        $address = $property->address . ", " . $property->city . " " . $property->zipcode;
        $transportationnoise = (new AtomApi)->transportationnoise($user_id, $property->id, "home-detail", "user", $address);

        if ($transportationnoise['success'] == 1) {
            if (!empty($transportationnoise['response']->transportationNoise->road_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "road_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "road_noise",
                    "level" => $transportationnoise['response']->transportationNoise->road_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->road_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->road_noise->noise_sources ?? []),
                ]);
            }

            if (!empty($transportationnoise['response']->transportationNoise->aviation_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "aviation_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "aviation_noise",
                    "level" => $transportationnoise['response']->transportationNoise->aviation_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->aviation_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->aviation_noise->noise_sources ?? []),
                ]);
            }

            if (!empty($transportationnoise['response']->transportationNoise->emg_vehicle_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "emg_vehicle_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "emg_vehicle_noise",
                    "level" => $transportationnoise['response']->transportationNoise->emg_vehicle_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->emg_vehicle_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->emg_vehicle_noise->noise_sources ?? []),
                ]);
            }

            if (!empty($transportationnoise['response']->transportationNoise->rail_whistle_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "rail_whistle_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "rail_whistle_noise",
                    "level" => $transportationnoise['response']->transportationNoise->rail_whistle_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->rail_whistle_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->rail_whistle_noise->noise_sources ?? []),
                ]);
            }

            if (!empty($transportationnoise['response']->transportationNoise->rail_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "rail_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "rail_noise",
                    "level" => $transportationnoise['response']->transportationNoise->rail_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->rail_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->rail_noise->noise_sources ?? []),
                ]);
            }

            if (!empty($transportationnoise['response']->transportationNoise->rail_noise)) {
                PropertyTransportNoise::updateOrCreate([
                    "property_id" => $property->id,
                    "noise_type" => "rail_noise"
                ], [
                    "property_id" => $property->id,
                    "noise_type" => "rail_noise",
                    "level" => $transportationnoise['response']->transportationNoise->rail_noise->level,
                    "level_description" => $transportationnoise['response']->transportationNoise->rail_noise->level_description,
                    "noise_sources" => json_encode($transportationnoise['response']->transportationNoise->rail_noise->noise_sources ?? []),
                ]);
            }

            $property->transportation_noise_summary = $transportationnoise['response']->transportationNoise->overall_summary ?? '';
            $property->save();
        }

        $property_transportationnoises = PropertyTransportNoise::where("property_id", $property->id)->get();

        return [
            "success" => 1,
            "message" => "",
            "property_transportationnoises" => $property_transportationnoises,
            "transportation_noise_summary" => $property->transportation_noise_summary
        ];
    }

    //// call/save nearby schools =======================
    public function fetch_sales_trend(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();


        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->geoidv4_n1)) {
            return [
                "success" => 0,
                "message" => "Property not found",
                "error" => "geoidv4 n1 id missing"
            ];
        }

        $transaction_salestrend = (new AtomApi)->transaction_salestrend($user_id, $property->id, "home-detail", "user", $property->geoidv4_n1);

        // $transaction_salestrend_d = \App\Models\AtomApiLog::find(160);
        // $transaction_salestrend = array();
        // $transaction_salestrend["success"] = 1;
        // $transaction_salestrend["response"] = json_decode($transaction_salestrend_d->api_response);

        if ($transaction_salestrend['success'] == 1) {
            if (!empty($transaction_salestrend['response']->salesTrends)) {

                ///======== delete existing ==============
                PropertySalesTrend::where("property_id", $property->id)->delete();

                foreach ($transaction_salestrend['response']->salesTrends as $trend) {

                    PropertySalesTrend::create([
                        "property_id" => $property->id,
                        "geoidv4" => $trend->location->geoIdV4,
                        "interval" => $trend->dateRange->interval,
                        "start_year" => $trend->dateRange->start,
                        "end_year" => $trend->dateRange->end,
                        "homesalecount" => ($trend->salesTrend->homeSaleCount ?? 0),
                        "avgsaleprice" => ($trend->salesTrend->avgSalePrice ?? 0),
                        "medsaleprice" => ($trend->salesTrend->medSalePrice ?? 0),
                        "pubdate" => $trend->vintage->pubDate
                    ]);
                }
            }
        }

        $sales_trends = PropertySalesTrend::where("property_id", $property->id)->orderBy("start_year", "DESC")->get();
        $sales_trends->each(function ($value) {
            $value->interval = ucwords($value->interval);
            $value->pubdate1 = $value->pubdate->format("m-d-Y");
        });

        return [
            "success" => 1,
            "message" => "",
            "sales_trends" => $sales_trends,

            // "xx" =>$transaction_salestrend
        ];
    }


    //// call/save all events detail =======================
    public function fetch_allevents_detail(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Property not found",
                "error" => "Attomid Missing"
            ];
        }

        $allevents_details = (new AtomApi)->allevents_details($user_id, $property->id, "home-detail", "user", $property->attomid);

        if ($allevents_details['success'] == 1) {
            if (!empty($allevents_details['response']->property)) {
                PropertyAllEventsDetail::updateOrCreate(["property_id" => $property->id], [
                    "property_id" => $property->id,
                    "api_response" => (json_encode($allevents_details['response'])),
                ]);


                $property->current_estimated_home_value = $allevents_details['response']->property[0]->avm->amount->value ?? null;
                $property->save();
            }
        }

        $all_event_detail = PropertyAllEventsDetail::where("property_id", $property->id)->first();
        if ($all_event_detail) {
            $all_event_detail->avm = [];
            if (!empty($all_event_detail->api_response)) {
                $all_event_detail->api_response = json_decode($all_event_detail->api_response);
                $all_event_detail->avm = $all_event_detail->api_response->property[0]->avm;
            }
        }


        // return $all_event_detail->api_response->property[0]->avm->amount->value;


        return [
            "success" => 1,
            "message" => "",
            "all_event_detail_view" => view("front.myaccount.inc-avm", compact('all_event_detail'))->render()
        ];
    }

    public function fetch_property_detailmortgage(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();


        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Property not found",
                "error" => "Attomid Missing"
            ];
        }

        $property_detailmortgage = (new AtomApi)->property_detailmortgage($user_id, $property->id, "home-detail", "user", $property->attomid);

        if ($property_detailmortgage['success'] == 1) {
            if (!empty($property_detailmortgage['response']->property[0]->mortgage)) {

                $mortgage = $property_detailmortgage['response']->property[0]->mortgage;

                if (!empty($mortgage->lender->lastname)) {
                    PropertyDetailMortgage::updateOrCreate(["property_id" => $property->id], [
                        "property_id" => $property->id,
                        "lender_lastname" => ($mortgage->lender->lastname ?? ""),
                        "lender_companycode" => ($mortgage->lender->companycode ?? ""),
                        "title_companyname" => ($mortgage->title->companyname ?? ""),
                        "amount" => ($mortgage->amount ?? 0),
                        "mort_date" => ($mortgage->date ?? null),
                        "deedtype" => ($mortgage->deedtype ?? ""),
                        "term" => ($mortgage->term ?? ""),
                        "duedate" => ($mortgage->duedate ?? null)
                    ]);
                }

                // "lender": {
                //     "lastname": "MOUNTAIN HOME LENDING",
                //     "companycode": "102082"
                //   },
                //   "title": {
                //     "companyname": "NONE AVAILABLE"
                //   },
                //   "amount": 154000,
                //   "date": "2007-03-21",
                //   "deedtype": "WD",
                //   "term": 359,
                //   "duedate": "2037-02-01"

            }
        }

        $mortgage_detail = PropertyDetailMortgage::where("property_id", $property->id)->first();

        if ($mortgage_detail) {
            if ($mortgage_detail->duedate) {
                $mortgage_detail->duedate = date("m-d-Y", strtotime($mortgage_detail->duedate));
            }

            if ($mortgage_detail->mort_date) {
                $mortgage_detail->mort_date = date("m-d-Y", strtotime($mortgage_detail->mort_date));
            }
        }

        return [
            "success" => 1,
            "message" => "",
            "mortgage_detail" => $mortgage_detail
        ];
    }

    public function my_loans(Request $request)
    {
        $myproperties = Property::with("mortgage_informations")->whereHas("mortgage_informations")->where("user_id", auth()->user()->id)->get();

        return view("front.myaccount.my-loans", compact('myproperties'));
    }

    public function fetch_property_detailowner(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Property not found",
                "error" => "Attomid Missing"
            ];
        }

        $property_detailowner = (new AtomApi)->property_detailowner($user_id, $property->id, "home-detail", "user", $property->attomid);

        if ($property_detailowner['success'] == 1) {
            if (!empty($property_detailowner['response']->property)) {
                PropertyDetailOwner::updateOrCreate(["property_id" => $property->id], [
                    "property_id" => $property->id,
                    "api_response" => (json_encode($property_detailowner['response'])),
                ]);
            }
        }

        $property_detailowner = PropertyDetailOwner::where("property_id", $property->id)->first();
        if ($property_detailowner) {
            $property_detailowner->owner_detail = [];
            if (!empty($property_detailowner->api_response)) {
                $property_detailowner->api_response = json_decode($property_detailowner->api_response);
                $property_detailowner->owner_detail = $property_detailowner->api_response->property[0]->owner;
            }
        }



        return [
            "success" => 1,
            "message" => "",
            "property_detailowner_view" => view("front.myaccount.inc-prop-owner", compact('property_detailowner'))->render()
        ];
    }

    public function fetch_property_buildingpermits(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Attomid missing"
            ];
        }

        $address1 = $property->address;
        $address2 = $property->city . "," . $property->state;

        $property_buildingpermits = (new AtomApi)->property_buildingpermits($user_id, $property->id, "home-detail", "user", $address1, $address2);

        if ($property_buildingpermits['success'] == 1) {
            if (!empty($property_buildingpermits['response']->property[0]->buildingPermits)) {
                ///======== delete existing ==============
                PropertyBuildingPermit::where("property_id", $property->id)->delete();

                foreach ($property_buildingpermits['response']->property[0]->buildingPermits as $buildingpermit) {
                    PropertyBuildingPermit::create([
                        "property_id" => $property->id,
                        "effectivedate" => ($buildingpermit->effectiveDate ?? null),
                        "permitnumber" => ($buildingpermit->permitNumber ?? null),
                        "status" => ($buildingpermit->status ?? null),
                        "description" => ($buildingpermit->description ?? null),
                        "type" => ($buildingpermit->type ?? null),
                        "projectname" => ($buildingpermit->projectName ?? null),
                        "fees" => ($buildingpermit->fees ?? null),
                        "businessname" => ($buildingpermit->businessName ?? null),
                        "homeownername" => ($buildingpermit->homeOwnerName ?? null),
                        "jobvalue" => ($buildingpermit->jobValue ?? null)
                    ]);
                }
            }
        }

        $buildingpermits = PropertyBuildingPermit::where("property_id", $property->id)->get();
        $buildingpermits->each(function ($value) {
            $value->effectivedate1 = "";
            if ($value->effectivedate) {
                $value->effectivedate1 = $value->effectivedate->format('m-d-Y');
            }
        });

        return [
            "success" => 1,
            "message" => "",
            "buildingpermits" => $buildingpermits
        ];
    }

    /*
    * Author: Vidhi Shah
    * Updated date: 12th Aug 2024
    * This function has been modified to implment the new design for alert page
    */
    public function opportunity_alerts(Request $request)
    {
        $f = request('f');
        $user_id = (!empty(request()->user()->id)) ? request()->user()->id : auth()->user()->id;
        $property_id = request("property_id");

        if (empty($f)) {
            $default_query = collect(DB::select("SELECT alert_type FROM `opportunity_alerts`
            WHERE property_id = ?
            ORDER BY FIELD(alert_type,'remove_mortgage_insurance','take_cash_out','lower_rate_same_term','lower_rate_not_same_term', 'change_loan_type')
            LIMIT 1", [$property_id]))->first();

            $default_tab = 'lrst';
            if (isset($default_query) && $default_query->alert_type == "remove_mortgage_insurance") {
                $default_tab = 'rmi';
            } else if (isset($default_query) && $default_query->alert_type == "take_cash_out") {
                $default_tab = 'tco';
            } else if (isset($default_query) && $default_query->alert_type == "lower_rate_same_term") {
                $default_tab = 'lrst';
            } else if (isset($default_query) && $default_query->alert_type == "lower_rate_not_same_term") {
                $default_tab = 'lrnst';
            } else if (isset($default_query) && $default_query->alert_type == "change_loan_type") {
                $default_tab = 'clt';
            }
        } else {
            $default_tab = $f;
        }

        $default_property_id = 0;
        if (!empty($property_id) && $property_id > 0) {
            $default_property_id = $property_id;
        }

        $opportunity_alerts = OpportunityAlert::where("user_id", $user_id)
            ->when(!empty($request->property_id), function ($query) {
                $query->where("property_id", request("property_id"));
            })
            ->whereHas("property")
            ->orderBy("created_at", "DESC")
            ->get();

        $opportunityAlerts = [];

        $opportunity_alerts->each(function ($value) use (&$opportunityAlerts) {
            $value->other_info = json_decode($value->other_info);
            $propertyId = $value->property_id;
            $propertyName = $value->other_info->address . ", " . $value->other_info->city . ", " . $value->other_info->zipcode;

            // Group by property_id
            if (!isset($opportunityAlerts[$propertyId])) {
                $mortgage_info = MortgageInformation::where("property_id", $propertyId)
                    ->where("user_id", $value->user_id)
                    ->first();
                $property = Property::where("id", $propertyId)->first();
                $opportunityAlerts[$propertyId] = [
                    'user_id' => $value->user_id,
                    'property_id' => $propertyId,
                    'property_name' => $propertyName,
                    'property_type' => $property->occupancy,
                    'current_estimated_home_value' => $property->current_estimated_home_value,
                    'mortgage_info' => $mortgage_info,
                    'alerts' => []
                ];
            }

            // Initialize alert_type array if not set
            if (!isset($opportunityAlerts[$propertyId]['alerts'][$value->alert_type])) {
                $opportunityAlerts[$propertyId]['alerts'][$value->alert_type] = [];
            }

            $opportunityAlerts[$propertyId]['alerts'][$value->alert_type][] = $value;
        });

        // Process each property and sort the alerts
        $opportunityAlerts = collect($opportunityAlerts)->map(function ($property) {
            $property['alerts'] = collect($property['alerts'])->map(function ($alerts, $alertType) {
                // Sort based on criteria specific to alert_type
                $alerts = collect($alerts)->sort(function ($a, $b) use ($alertType) {
                    if ($alertType === 'lower_rate_same_term') {
                        return ($b->other_info->emi_monthly_saving <=> $a->other_info->emi_monthly_saving);
                    } elseif ($alertType === 'lower_rate_not_same_term') {
                        return ($b->other_info->interest_saving <=> $a->other_info->interest_saving);
                    } elseif ($alertType === 'remove_mortgage_insurance') {
                        return ($b->other_info->emi_monthly_saving <=> $a->other_info->emi_monthly_saving);
                    }
                    // Add more sorting criteria for other alert types if necessary
                    return 0;
                })->take(5); // Get the top 5 alerts

                return $alerts;
            });

            return $property;
        });

        // Output the result
        $opportunityAlerts->each(function ($property)  use (&$propertiesWithAlerts) {
            $propertiesWithAlerts[] = $property;
        });


        //echo "<pre>";print_r($propertiesWithAlerts);die;
        return view("front.myaccount.opportunity-alerts", compact('opportunity_alerts', 'default_tab', 'propertiesWithAlerts', 'default_property_id'));
    }

    public function opportunity_alerts_detail(Request $request)
    {
        $id = $request->id;
        $user_id = $request->user()->id;
        $opportunity_alerts = OpportunityAlert::where("id", $id)->where("user_id", $user_id)->whereHas("property")->first();

        if (!$opportunity_alerts) {
            abort(404);
        }



        $other_info = json_decode($opportunity_alerts->other_info, true);
        $mdata = $other_info['mdata'];

        if ($opportunity_alerts->property_id == 82) {
            $mdata['proposed_interest_rate'] = 7.25;
            $mdata['proposed_mortgage_payment_monthly'] = 3128.95;
        }



        $subject = "";

        if ($opportunity_alerts->alert_type == "lower_rate_same_term") {
            $email_message = "Congratulations!! We have been managing your mortgage and are delighted to alert you of a refinance opportunity. Based on the information we have, you have the opportunity to refinance to get a lower rate same term and to save on interest paid over the life of the loan.";
            return (new \App\Mail\SameTermAlertMail($mdata, $email_message, $subject));
        } else if ($opportunity_alerts->alert_type == "lower_rate_not_same_term") {
            $email_message = "Congratulations!! We have been managing your mortgage and are delighted to alert you of a refinance opportunity. Based on the information we have, you have the opportunity to refinance to reduce lower rate not same term of the loan  and to save on interest paid over the life of the loan.";
            return (new \App\Mail\NotSameTermAlertMail($mdata, $email_message, $subject));
        } else if ($opportunity_alerts->alert_type == "remove_mortgage_insurance") {
            $email_message = "Congratulations!! We have been managing your mortgage and are delighted to alert you of a refinance opportunity. Based on the information we have, you have the opportunity to refinance to eliminate mortgage insurance and to save on interest paid over the life of the loan.";
            return (new \App\Mail\RemoveMortgageInsuranceAlertMail($mdata, $email_message, $subject));
        } else if ($opportunity_alerts->alert_type == "change_loan_type") {
            $email_message = "Congratulations!! We have been managing your mortgage and are delighted to alert you of a refinance opportunity. Based on the information we have, you have the opportunity to refinance to change loan type and to save on interest paid over the life of the loan.";
            return (new \App\Mail\ChangeLoanTypeAlertMail($mdata, $email_message, $subject));
        } else if ($opportunity_alerts->alert_type == "take_cash_out") {
            $email_message = "Congratulations!! We have been managing your mortgage and are delighted to alert you of a refinance opportunity. Based on the information we have, you have the opportunity to refinance to take a cashout and to save on interest paid over the life of the loan.";
            return (new \App\Mail\TakeCashOutAlertMail($mdata, $email_message, $subject));
        }
    }

    public function get_opportunity_alerts(Request $request)
    {

        $opportunity_alerts = OpportunityAlert::where("user_id", $request->user()->id)
            ->where("property_id", $request->property_id)
            ->where("alert_type", $request->alert_type)
            ->whereHas("property")
            ->orderBy("created_at", "DESC")->get();

        if ($opportunity_alerts->count() == 0) {
            return 'No Alerts Found';
        }

        $opportunity_alerts->each(function ($value) {
            $value->other_info = json_decode($value->other_info);
        });



        return view('front.myaccount.alerts-modal', compact('opportunity_alerts'));
    }

    /*
    * Author: Vidhi Shah
    * Updated date: 07 Jul 2024
    * Description: Updated code for sending contact request to Loan Officer
    *
    * Updated date: 10 Jul 2024
    * Description: Email should be sent to the default loan officer if there is not loan officer assigned to user
    */
    public function contact_loan_officer(Request $request)
    {
        $user = Auth()->user();
        try {
            $contact = ContactLoanOfficer::create([
                "officer_id" => $request->lo_id,
                "user_id" => $user->id,
                "message" => $request->message
            ]);


            $edata = [
                "name" => $user->name,
                "email"  => $user->email,
                "mobile" => $user->mobile,
                "message" => $request->message
            ];

            if (!empty($request->lo_id) && $request->lo_id > 0) {
                $getLODetails = Admin::find($request->lo_id);
                $loEmail = $getLODetails->email;
            } else {
                $loEmail = getenv("DEFAULT_LOANOFFICER_EMAIL");
            }

            Mail::to($loEmail)->send(new ContactLoanOfficerEmail($edata));
            return [
                "success" => 1,
                "message" => "Thank you for contacting us. We will get back to you shortly.",
                "redirectTo" => route("loan-officer")
            ];
        } catch (Exception $e) {
            Log::error("Error while sending contact resquet to the loan officer for user " . $user->id . ", Error - " . $e->getMessage());
            return [
                "success" => 0,
                "message" => $e->getMessage(),
                "redirectTo" => route("loan-officer")
            ];
        }
    }

    public function settings_page(Request $request)
    {
        $settings = User::select("lrst_frequency", "lrst_frequency_opt", "lrnst_frequency", "lrnst_frequency_opt", "clt_frequency", "clt_frequency_opt")->find($request->user()->id);

        return view("front.myaccount.settings", compact("settings"));
    }

    /*
    * Author: Vidhi Shah
    * Updated date: 18th Jun 2024
    * Description: This method is used to save alert frequency in the database, which will be later used for sending opportunity alerts to the user
    * Updated Date: 4th Sept 2024
    * Description: User should not allow if consent for email notification is not checked to true
    */
    public function save_settings(Request $request)
    {
        try {

            // Get the current date
            $currentDate = Carbon::now();

            // Get the day of the week as a number (1 = Monday, 7 = Sunday)
            $dayOfWeek = $currentDate->dayOfWeekIso; // Same as date('N')

            $settings = User::find($request->user()->id);

            $settings->lrst_frequency = $request->lrst_frequency;
            $settings->lrst_frequency_opt = (strtolower($request->lrst_frequency) == "weekly") ? $dayOfWeek : null;
            $settings->lrnst_frequency = $request->lrst_frequency;
            $settings->lrnst_frequency_opt = (strtolower($request->lrst_frequency) == "weekly") ? $dayOfWeek : null;
            $settings->clt_frequency = $request->lrst_frequency;
            $settings->clt_frequency_opt = (strtolower($request->lrst_frequency) == "weekly") ? $dayOfWeek : null;
            $settings->consent_to_receive_email = $request->consent_to_receive_email ?? 0;
            $settings->consent_to_receive_message = $request->consent_to_receive_message ?? 0;
            $settings->save();

            return [
                "success" => 1,
                "message" => "Successfully saved"
            ];
        } catch (\Exception $e) {
            return [
                "success" => 0,
                "message" => $e->getMessage()
            ];
        }
    }


    public function fetch_property_rentalavm(Request $request)
    {
        $user_id = auth()->user()->id;
        $property = Property::where("user_id", $user_id)->where("id", $request->property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }

        if (empty($property->attomid)) {
            return [
                "success" => 0,
                "message" => "Attomid missing"
            ];
        }

        $address1 = $property->address;
        $address2 = $property->city . "," . $property->state;

        $property_rentalavm = (new AtomApi)->property_rentalavm($user_id, $property->id, "home-detail", "user", $address1, $address2);

        if ($property_rentalavm['success'] == 1) {
            if (!empty($property_rentalavm['response']->property[0]->rentalAvm)) {
                ///======== delete existing ==============
                // PropertyRentalAvm::where("property_id", $property->id)->delete();

                // foreach($property_rentalavm['response']->property[0]->rentalAvm as $rentalAvm) {

                $rentalAvm = $property_rentalavm['response']->property[0]->rentalAvm;
                if (isset($rentalAvm->estimatedRentalValue)) {
                    PropertyRentalAvm::create([
                        "property_id" => $property->id,
                        "estimated_rental_value" => ($rentalAvm->estimatedRentalValue ?? null),
                        "estimated_min_rental_value" => ($rentalAvm->estimatedMinRentalValue ?? null),
                        "estimated_max_rental_value" => ($rentalAvm->estimatedMaxRentalValue ?? null),
                        "valuation_date" => ($rentalAvm->valuationDate ?? null)
                    ]);
                }
                // }

            }
        }

        $rentalavms = PropertyRentalAvm::where("property_id", $property->id)->limit(1)->latest()->get();
        $rentalavms->each(function ($value) {
            $value->valuation_date1 = "";
            if ($value->valuation_date) {
                $value->valuation_date1 = $value->valuation_date->format('m-d-Y');
            }

            $value->estimated_rental_value = "$" . number_format($value->estimated_rental_value);
            $value->estimated_min_rental_value = "$" . number_format($value->estimated_min_rental_value);
            $value->estimated_max_rental_value = "$" . number_format($value->estimated_max_rental_value);
        });

        return [
            "success" => 1,
            "message" => "",
            "rentalavms" => $rentalavms
        ];
    }

    public function delete_property(Request $request)
    {
        $user_id = $request->user()->id;
        $property = Property::where("id", $request->property_id)->where("user_id", $user_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property does not exists"
            ];
        }

        $property->delete();

        return [
            "success" => 1,
            "message" => "Property successfully removed. Please wait we are redirecting."
        ];
    }


    public function get_a_rate_quote(Request $request)
    {
        // return $request->all();
        $property_id = $request->property_id;
        $user_id = auth()->user()->id;

        $property = Property::where("user_id", $user_id)->where("id", $property_id)->first();

        if (!$property) {
            return [
                "success" => 0,
                "message" => "Property not found"
            ];
        }


        $address1 = $property->address;
        $address2 = $property->city . "," . $property->state;

        $errors_array = [];
        $property_expandedprofile = (new AtomApi)->property_expandedprofile($user_id, $property_id, "all-property", "user", $address1, $address2);
        $attomId = $property_expandedprofile['response']->property[0]->identifier->attomId;
        if ($property_expandedprofile['success'] == 1) {
            
            $allevents_details = $this->allevents_details($property->user_id, $property->id, "atom-property-services", "jobs", $attomId);
            $current_estimated_home_value = "";
            if($allevents_details['success'] == 1) {
                if(!empty($allevents_details['response']->property)) {
                    $current_estimated_home_value = $allevents_details['response']->property[0]->avm->amount->value ?? null;
                }
            }

            $property->number_of_bedrooms = $property_expandedprofile['response']->property[0]->building->rooms->beds ?? null;
            $property->number_of_bathrooms = $property_expandedprofile['response']->property[0]->building->rooms->bathsTotal ?? null;
            $property->size_sqft = $property_expandedprofile['response']->property[0]->building->size->livingSize ?? null;
            $property->current_estimated_home_value = $current_estimated_home_value ?? $property_expandedprofile['response']->property[0]->assessment->market->mktTtlValue ?? null;

            $property->attomid = $property_expandedprofile['response']->property[0]->identifier->attomId ?? null;
            $property->geoidv4_n1 = $property_expandedprofile['response']->property[0]->location->geoIdV4->N1 ?? $property_expandedprofile['response']->property[0]->location->geoIdV4->N2 ?? null;

            $property->save();
        } else {
            $errors_array[] = "Property Detail: " . $property_expandedprofile['message'];
        }

        //// current estimated home value===========================
        $allevents_details = (new AtomApi)->allevents_details($user_id, $property_id, "all-property", "user", $property->attomid);

        if ($allevents_details['success'] == 1) {
            if (!empty($allevents_details['response']->property)) {
                $property->current_estimated_home_value = $allevents_details['response']->property[0]->avm->amount->value ?? null;
                $property->save();
            }
        }


        /*
        $valuation_homeequity = (new AtomApi)->valuation_homeequity($user_id, $property_id, "all-property", "user", $address1, $address2);

        if($valuation_homeequity['success'] == 1) {
            $property->estimated_home_equity = $valuation_homeequity['response']->property[0]->homeEquity->estimatedAvailableEquity;
            $property->save();
        } else {
            $errors_array[] = "Home Equity: " . $valuation_homeequity['message'];
        }

        if(count($errors_array) == 2) {
            return [
                "success" => 0,
                "message" => implode(",", $errors_array)
            ];
        }
        */

        if (floatval($property->current_estimated_home_value ?? 0) > 0) {
            $total_loan_balance = $property->mortgage_informations->sum("current_loan_balance");
            $property->estimated_home_equity = ($property->current_estimated_home_value - $total_loan_balance);
        }

        $property->current_estimated_home_value = number_format($property->current_estimated_home_value);
        $property->estimated_home_equity = number_format($property->estimated_home_equity);

        //////call opportunity alerts ==============
        if (count($errors_array) == 0) {
            (new OpportunityAlertsServices())->removeMortgageInsuranceAlerts($property->id);
            (new OpportunityAlertsServices())->takeCashOutAlerts($property->id);
            (new OpportunityAlertsServices())->lowerRateSameTermAlerts($property->id, $property->user_id);
            (new OpportunityAlertsServices())->lowerRateNotSameTermAlerts($property->id, $property->user_id);
            //(new OpportunityAlertsServices())->changeLoanTypeAlerts($property->id, $property->user_id);

            $opp_alerts = collect(DB::select('SELECT alert_type, COUNT(*) AS total_new_alerts FROM `opportunity_alerts` WHERE property_id = ? AND read_status = 0 GROUP BY alert_type', [$property->id]));
            $opp_alerts = $opp_alerts->map(function ($alert) use ($property_id) {
                $alert_type_desc = "";
                $alert_link = "";
                if ($alert->alert_type == "lower_rate_same_term") {
                    $alert_type_desc = "Lower Rate Same Term";
                    $alert_link = route("opportunity-alerts", ["property_id" => $property_id, "f" => "lrst"]);
                } else if ($alert->alert_type == "lower_rate_not_same_term") {
                    $alert_type_desc = "Lower Rate But Not Same Term";
                    $alert_link = route("opportunity-alerts", ["property_id" => $property_id, "f" => "lrnst"]);
                } else if ($alert->alert_type == "change_loan_type") {
                    $alert_type_desc = "Change Loan Type";
                    $alert_link = route("opportunity-alerts", ["property_id" => $property_id, "f" => "clt"]);
                } else if ($alert->alert_type == "take_cash_out") {
                    $alert_type_desc = "Take Cashout";
                    $alert_link = route("opportunity-alerts", ["property_id" => $property_id, "f" => "tco"]);
                } else if ($alert->alert_type == "remove_mortgage_insurance") {
                    $alert_type_desc = "Remove Mortgage Insurance";
                    $alert_link = route("opportunity-alerts", ["property_id" => $property_id, "f" => "rmi"]);
                }

                return [
                    "alert_type_desc" => $alert_type_desc,
                    "alert_type" => $alert->alert_type,
                    "alert_link" => $alert_link,
                    "total_new_alerts" => $alert->total_new_alerts
                ];
            });
        } else {
            $opp_alerts = [];
        }

        return [
            "success" => 1,
            "message" => implode(",", $errors_array),
            "property" => $property,
            "opp_alerts" => $opp_alerts
        ];
    }


    public function runAttomForAllProperty()
    {
        $properties = Property::get();

        $properties->each(function ($property) {
            $property_id = $property->id;
            dispatch(function () use ($property_id) {
                $service = new AtomPropertyServices;
                $service->call_property_expandedprofile($property_id);
                // $service->call_near_by_schools($property_id);
                // $service->call_transportation_noise($property_id);
                $service->call_sales_trend($property_id);
                $service->call_property_detailmortgage($property_id);
                $service->call_allevents_detail($property_id);
                // $service->call_property_detailowner($property_id);
                // $service->call_property_buildingpermits($property_id);
                $service->call_property_rentalavm($property_id);
            });
        });
    }
    /*
    * Author: Vidhi Shah
    * Updated date: 3rd Jul 2024
    * Description: Get loan officer's details
    *
    * Updated date: 10 Jul 2024
    * Description: Assigning default loan officer's data
    */
    public function loanOfficer()
    {
        try {

            $user = auth()->user();
            $properties = Property::where("user_id", $user->id)->first();
            /* Default laon office is admin with ID 1 */
            $assigned_to = $properties->assigned_to > 0 ? $properties->assigned_to : (!empty($user->assigned_to && $user->partner_id > 0) ? $user->assigned_to : 1);
            
            $loanOfficerDetails = ($assigned_to > 0 && ($admin = Admin::find($assigned_to))) ? $admin : (object) [
                'id' => 0,
                'name' => getenv("DEFAULT_LOANOFFICER_NAME"),
                'email' => getenv("DEFAULT_LOANOFFICER_EMAIL"),
                'mobile' => getenv("DEFAULT_LOANOFFICER_MOBILE"),
                'nmls_number' => getenv("DEFAULT_LOANOFFICER_NMLS_ID"),
            ];

        } catch (Exception $e) {
            $loanOfficerDetails = [];
            Log::error($e->getMessage());
        }

        return view('front.myaccount.loan-officer', compact('loanOfficerDetails'));
    }

    public function newRate()
    {
        return view('front.myaccount.new-rate');
    }

    public function referFriend()
    {
        return view('front.myaccount.referFriend');
    }

    /**
     * Author: Vidhi Shah
     * Added date: 16th Sept 2024
     * Description: For call APIs for refinancing alerts
     */
    public function get_alerts(Request $request)
    {

        session(['processing_alert_after_login' => 1]);
        session(['processing_alert_after_login_done' => 0]);
        $myproperties = Property::where("user_id", auth()->user()->id)->get();

        try {
            foreach ($myproperties as $property) {
                if ($this->isPropertyComplete($property)) {
                    (new OpportunityAlertsServices())->updateCurrentLoanBalance($property->id);
                    (new OpportunityAlertsServices())->removeMortgageInsuranceAlerts($property->id);
                    (new OpportunityAlertsServices())->takeCashOutAlerts($property->id);
                    (new OpportunityAlertsServices())->lowerRateSameTermAlerts($property["id"], auth()->user()->id, false);
                    (new OpportunityAlertsServices())->lowerRateNotSameTermAlerts($property["id"], auth()->user()->id, false);
                }
            };
        } catch (Exception $e) {
            Log::error("After login, Lenderprice API call causing issue - " . $e->getMessage());
        }

        $opportunity_alerts = OpportunityAlert::where("user_id", auth()->user()->id)
            ->orderBy("created_at", "DESC")->count();


        if ($opportunity_alerts > 0) {
            $alerts_count = $opportunity_alerts;
        } else {
            $alerts_count = 0;
        }

        session(['processing_alert_after_login' => 0]);
        session(['processing_alert_after_login_done' => 1]);

        return $alerts_count;
    }

    
    /**
     * Author: Vidhi Shah
     * Added date: 16th Sept 2024
     * Description: For managing session flag to check whether APIs get called and ran once after success full login
     */
    public function manage_alert_sessions()
    {
        session(['processing_alert_after_login' => 0]);
        session(['processing_alert_after_login_done' => 1]);        
    }

    private function processDocument($fileName)
    {
        // Construct the full file path
        $filePath = storage_path('app/public/mortgage_statements/' . $fileName);

        // Instantiate the DocumentProcessorServiceClient
        $client = new DocumentProcessorServiceClient();

        // Build the processor name using project ID, location, and processor ID
        $name = $client->processorName($this->projectId, $this->location, $this->processorId);

        // Read the file content
        $fileContent = file_get_contents($filePath);

        // Determine the MIME type of the file
        $mimeType = mime_content_type($filePath);

        // Validate MIME type (ensure it's supported)
        $supportedMimeTypes = ['application/pdf', 'image/jpeg', 'image/png'];
        if (!in_array($mimeType, $supportedMimeTypes)) {
            return ['error' => 'Unsupported file type: ' . $mimeType];
        }

        // Create a RawDocument instance
        $rawDocument = new RawDocument([
            'content' => $fileContent,
            'mime_type' => $mimeType, // Use the dynamically detected MIME type
        ]);

        // Create a ProcessRequest instance and set the processor name and raw document
        $request = new ProcessRequest();
        $request->setName($name);
        $request->setRawDocument($rawDocument);

        // Initialize a response variable
        $response = null;

        // Call the API and handle any potential exceptions
        try {
            $response = $client->processDocument($request);
        } catch (\Exception $e) {
            // Handle API errors gracefully
            return ['error' => $e->getMessage()];
        }

        // Parse the response to get the processed document
        $document = $response->getDocument();

        // Extract desired fields from the document
        $fields = $this->extractFields($document);

        // Close the client to free up resources
        $client->close();

        // Return the extracted fields
        return $fields;
    }


    private function extractFields($document)
    {
        $fields = [];

        // Loop through the entities and extract specific fields
        foreach ($document->getEntities() as $entity) {
            $type = $entity->getType();
            $text = $entity->getMentionText();

            // Map extracted fields to specific keys
            switch ($type) {
                case 'PropertyAddress':
                    $fields['property_address'] = $text;
                    break;
                case 'OutstandingBalance':
                    $fields['outstanding_balance'] = $text;
                    break;
                case 'InterestRate':
                    $fields['interest_rate'] = $text;
                    break;
                case 'LoanNumber':
                    $fields['loan_number'] = $text;
                    break;
                case 'PaymentDueDate':
                    $fields['payment_due_date'] = $text;
                    break;
                case 'AmountDue':
                    $fields['amount_due'] = $text;
                    break;
                    // Add additional cases for other fields as needed
                default:
                    // For other fields not mapped explicitly
                    $fields[$type] = $text;
                    break;
            }
        }

        $address = $this->parseAddress($fields['property_address']);
        $fields['property_address'] = (!empty($address['address'])) ? $address['address'] : "";
        $fields['state'] = (!empty($address['state'])) ? $address['state'] : "";
        $fields['zip_code'] = (!empty($address['zip_code'])) ? $address['zip_code'] : "";

        // Check if maturity_date exists and is in valid format
        if (isset($fields['maturity_date']) && \DateTime::createFromFormat('m/d/Y', $fields['maturity_date'])) {
            // Create a Carbon instance from the maturity date
            $maturity_date = Carbon::createFromFormat('m/d/Y', $fields['maturity_date']);
            $loan_term_years = 30;  // Assuming it's a 30-year loan

            // Subtract loan term from maturity date to get the start date
            $start_date = $maturity_date->copy()->subYears($loan_term_years);

            // Add start_date to the fields array
            $fields['start_date'] = $start_date->format('m-Y'); // Format as needed - 10-25-2024
        } else {
            // If maturity_date does not exist or is invalid, leave start_date blank
            $fields['start_date'] = '';
        }

        return $fields;
    }

    /**
     * Author: Gurupriya Solanki
     * Descrption : Calling by Ajax call to get fields data to show property data by auto populate
     * Created Date : 9 OCT 2024
     */
    public function uploadAndProcessDocument(Request $request)
    {
        // Handle file upload and store it
        try {
            if ($request->has('mortgage_statement')) {
                $orignal_filename = $request->file('mortgage_statement')->getClientOriginalName();
                $extension = pathinfo($orignal_filename, PATHINFO_EXTENSION);

                /* Author: Vidhi Shah
                * Update Date: 15 Nov 2024
                * Description: should allow image files as well*/
                if (!in_array($extension, ["pdf", "xls", "xlsx", "jpeg", "png", "jpg"])) {
                    return response()->json([
                        "success" => 0,
                        "message" => "Please upload pdf/xls/xlsx/jpeg/jpg/png file only"
                    ]);
                }

                $mortgage_statement = basename($request->file('mortgage_statement')->store('public/mortgage_statements'));

                // Process the document with Document AI
                $extractedData = $this->processDocument($mortgage_statement);

                // Return the extracted fields as a JSON response
                return response()->json([
                    'success' => true,
                    'fields' => $extractedData,
                ]);
            } else {
                return response()->json([
                    'success' => false,
                    'message' => 'No file uploaded',
                ]);
            }
        } catch (\Exception $e) {
            // Handle any errors that may occur
            return response()->json([
                'success' => false,
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /* Parse address from mortgage statement and get city, state and zipcode */
    public function parseAddress($address)
    {

        // Regular expression to extract city, state, and ZIP code
        $pattern = '/([A-Za-z\s]+),?\s*([A-Z]{2})\s*(\d{5})/';

        // Initialize result array
        $result = [
            'city' => null,
            'state' => null,
            'zip_code' => null
        ];

        // Check if the address matches the pattern
        if (preg_match($pattern, $address, $matches)) {
            // Populate the result with matches
            $result['address'] = trim($address);
            $result['city'] = trim($matches[1]);
            $result['state'] = $matches[2];
            $result['zip_code'] = $matches[3];
        }

        return $result;
    }

    public function fetch_mortgage_atomapi_by_address(Request $request)
    {
        $address1 = $request->address;
        $address2 = "{$request->city}, {$request->state}";
        $user_id = auth()->id();
        $bypass_property_check = $request->bypass_property_check ?? false;
        $current_interest_rate = $request->current_interest_rate ?? 0;
        // Check if property already exists
        if (!$bypass_property_check && Property::where([
            "address" => $request->address,
            "city" => $request->city,
            "zipcode" => $request->zipcode,
            "occupancy" => $request->occupancy
        ])->exists()) {
            return ["success" => 0, "message" => "Oops! This property already exists in our database"];
        }

        // Fetch property profile from AtomApi
        $property_expandedprofile = (new AtomApi)->property_expandedprofile($user_id, 0, "add-property", "user", $address1, $address2);
        $attomId = $property_expandedprofile['response']->property[0]->identifier->attomId;
        $allevents_details = (new AtomApi)->allevents_details($user_id, 0, "add-property", "user", $attomId);
        $current_estimated_home_value = "";
        if($allevents_details['success'] == 1) {
            if(!empty($allevents_details['response']->property)) {
                $current_estimated_home_value = $allevents_details['response']->property[0]->avm->amount->value ?? null;
            }
        }
        $property = $property_expandedprofile['response']->property[0] ?? null;

        if (!$property) {
            return ["success" => 0, "message" => "Property details not found"];
        }

        // Extract mortgage details
        $mortgage = $property->assessment->mortgage->FirstConcurrent ?? null;
        $original_loan_balance = $mortgage->amount ?? 0;

        // Convert mortgage_start_date to MM-YYYY format
        $mortgage_start_date_raw = !empty($mortgage->date) ? Carbon::parse($mortgage->date)->format('m-Y') : "";
        
        // Extract property sale details
        $appraised_proprty_value = $current_estimated_home_value ?? $property->assessment->market->mktTtlValue 
        ?? $property->assessment->assessed->assdTtlValue 
        ?? 0;

        // Calculate current loan balance
        $current_loan_balance = "";
        if(!empty($current_interest_rate) && is_numeric($current_interest_rate) && $current_interest_rate > 0){
            $loan_term = 360; 
            // Validate & convert mortgage start date
            if (preg_match('/^\d{2}-\d{4}$/', $mortgage_start_date_raw)) {
                // Convert "MM-YYYY" to "YYYY-MM-01"
                $parts = explode('-', $mortgage_start_date_raw);
                $mortgage_start_date = "{$parts[1]}-{$parts[0]}-01"; // Convert to "YYYY-MM-01"
            } else {
                $mortgage_start_date = $mortgage_start_date_raw;
            }
            $current_loan_balance = getCurrentLoanBalance($original_loan_balance, $current_interest_rate, $loan_term, $mortgage_start_date) ?? 0;    
            $current_loan_balance =  number_format($current_loan_balance, 2);
        }
        
        return [
            "success" => 1,
            "message" => "Mortgage and summary data retrieved successfully",
            "current_estimated_home_value" => number_format($appraised_proprty_value, 2),
            "all_events_current_estimated_home_value" => number_format($current_estimated_home_value,2),
            "mortgage_start_date" => $mortgage_start_date_raw,
            "original_loan_balance" => number_format($original_loan_balance, 2),
            "current_loan_balance" => $current_loan_balance,
            "loan_type" => "Fixed",
            "loan_program" => "Conventional",
            "loan_term" => 360
        ];
    }

    function calculateCurrentLoanBalance(Request $request) {
        try {
            // Sanitize and retrieve input values
            $original_loan_balance = removeCommaFromAmount($request->get("original_loan_balance"));
            $current_interest_rate = $request->get("current_interest_rate");
            $loan_term = $request->get("loan_term");
            $mortgage_start_date_raw = $request->get("mortgage_start_date");
    
            // Log received request data
            Log::info("Processing loan balance calculation", [
                'original_loan_balance' => $original_loan_balance,
                'current_interest_rate' => $current_interest_rate,
                'loan_term' => $loan_term,
                'mortgage_start_date_raw' => $mortgage_start_date_raw,
            ]);
    
            // Validate numeric inputs
            if (!is_numeric($original_loan_balance) || !is_numeric($current_interest_rate) || !is_numeric($loan_term)) {
                Log::error("Invalid numeric values", [
                    'original_loan_balance' => $original_loan_balance,
                    'current_interest_rate' => $current_interest_rate,
                    'loan_term' => $loan_term,
                ]);
                return response()->json(['success' => 0, 'error' => 'Invalid numeric values provided.'], 400);
            }
    
            // Validate & convert mortgage start date
            if (preg_match('/^\d{2}-\d{4}$/', $mortgage_start_date_raw)) {
                // Convert "MM-YYYY" to "YYYY-MM-01"
                $parts = explode('-', $mortgage_start_date_raw);
                $mortgage_start_date = "{$parts[1]}-{$parts[0]}-01"; // Convert to "YYYY-MM-01"
            } else {
                $mortgage_start_date = $mortgage_start_date_raw;
            }
    
            // Parse the date using Carbon
            try {
                $mortgage_start_date = Carbon::parse($mortgage_start_date)->format('Y-m-d');
            } catch (Exception $e) {
                Log::error("Invalid mortgage start date format", ['input' => $mortgage_start_date_raw, 'error' => $e->getMessage()]);
                return response()->json(['success' => 0, 'error' => 'Invalid mortgage start date format. Expected format: MM-YYYY or YYYY-MM-DD.'], 400);
            }
    
            // Calculate loan balance
            $current_loan_balance = getCurrentLoanBalance($original_loan_balance, $current_interest_rate, $loan_term, $mortgage_start_date) ?? 0;
    
            Log::info("Successfully calculated loan balance", ['current_loan_balance' => $current_loan_balance]);
    
            return response()->json(['success' => 1, 'current_loan_balance' => number_format($current_loan_balance, 2)], 200);
        } catch (Exception $e) {
            Log::error("Unexpected error in loan balance calculation", ['error' => $e->getMessage()]);
            return response()->json(['success' => 0, 'error' => 'An unexpected error occurred. Please try again later.'], 500);
        }
    }

}
