<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Livewire\WithPagination;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Mail;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Support\Facades\Log;
use App\Http\Middleware\TenantMiddleware;

class RecordIN extends Component
{
    use WithPagination;
    protected $paginationTheme = 'bootstrap';

    protected $listeners = ['setCausal' => 'setCausal', 'refreshMembers' => 'refreshMembers', 'scontoChanged' => 'updateSconto'];

    public $sortField = 'date';
    public $sortAsc = false;

    public $typeIN = "IN";

    public $fromPage = '';

    public $isDuplicate = false;
    public $multiP = false;
    public $from, $to;

    public $multiMonthTo = 0;
    public $multiYearTo = 0;
    public $multiMonthFrom = 0;
    public $multiYearFrom = 0;
    public $createSubscription = 0;

    public $corrispettivo_causal_id = 0;

    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortAsc = ! $this->sortAsc;
        } else {
            $this->sortAsc = true;
        }

        $this->sortField = $field;
    }

    public $courseId = 0;
    public $rateId = 0;
    public $months = array();
    

    public $records, $dataId, $member_id, $supplier_id,
        $causal_id,
        $payment_method_id,
        $destination_id,
        $date,
        $month,
        $year,
        $type,
        $deleted,
        $financial_movement,
        $amount,
        $vat,
        $virtual,
        $note,
        $parent,
        $corrispettivo_fiscale,
        $commercial, $update = false, $add = false;

    public $corrispettivo = [];

    public $currentReceip;

    public $filterMember = 0, $filterPaymentMethod = 0, $filterCausals = 0, $filterFrom = '', $filterTo = '', $filterCommercial = 0;

    public $hasFilter = false;

    public $total = 0;

    public $selectedFilter = '';

    public $multipleIds = [];
    public $multipleAction = '';

    public $first = true;

    public $selectId = 0;
    public $refreshAfter = 0;
    public $sconto = 0;
    public $canSave = true;
    public $newMemberFirstName = '';
    public $newMemberLastName = '';
    public $newMemberEmail = '';
    public $newMemberToComplete = false;
    public $newMemberFiscalCode = '';
    public $newMemberFiscalCodeExist = false;

    public $causals = array();
    public $payments = array();
    public $banks = array();
    public $members = array();
    public $vats = array();

    public $rows = array();

    public $fromCourse = false;

    protected $rules = [
        'member_id' => 'required',
        'payment_method_id' => 'required',
        'rows.*.causal_id' => 'required',
        'rows.*.amount' => 'required'
    ];

    protected $messages = [
        'member_id.required' => 'La persona è obbligatorio',
        'payment_method_id.required' => 'Il metodo di pagamento è obbligatorio',
        'rows.*.causal_id.required' => 'La causale è obbligatoria',
        'rows.*.amount.required' => 'L\'importo è obbligatorio',
    ];

    public function boot()
    {
        app(TenantMiddleware::class)->setupTenantConnection();
    }

    public function updatedMemberId()
    {
        $this->emit('refresh');
        if ($this->member_id > 0) {
            $member = \App\Models\Member::findOrFail($this->member_id);
            if (!$member->isAdult()) {
                if ($member->father_name != '')
                    $this->parent = $member->father_name . " (C.F. " . $member->father_fiscal_code . ")";
                else if ($member->mother_name != '')
                    $this->parent = $member->mother_name . " (C.F. " . $member->mother_fiscal_code . ")";
                else
                    $this->parent = '';
            }
            $this->virtual = $member->getMoney();
            $this->newMemberFirstName = '';
            $this->newMemberLastName = '';
            $this->newMemberEmail = '';
            $this->newMemberToComplete = false;
            $this->newMemberFiscalCode = '';
            $this->newMemberFiscalCodeExist = false;
        }
    }

    public function updatedCausalId()
    {
        //$this->emit('refresh');
    }

    public function updatedDate()
    {
        //$this->emit('refresh');
    }

    public function hydrate()
    {
        $this->emit('load-select');
    }

    /*public function updated() {
        $this->emit('refresh');
    }*/

    public function updatedPaymentMethodId()
    {
        //$this->emit('refresh');
        $this->canSave = $this->checkCanSave();
    }

    public function updatedAmount()
    {
        // $this->emit('refresh');
        $this->canSave = $this->checkCanSave();
    }

    public function updatedCommercial($value)
    {
        $this->emitSelf('refreshMembers');
    }

    public function updateSconto()
    {
        $totalSconto = 0;
        foreach ($this->rows as $row) {
            if (isset($row['sconto']) && $row['sconto'] != null && $row['sconto'] != "") {
                $totalSconto += $this->currencyToDouble($row['sconto']);
            }
        }
        $this->sconto = formatPrice($totalSconto);
        Log::info("Total sconto updated to: " . $this->sconto);
    }


    public function checkCanSave()
    {
        $ret = true;
        if ($this->payment_method_id != null) {
            $payment_method = \App\Models\PaymentMethod::findOrFail($this->payment_method_id);
            if ($payment_method->money) {
                $from = str_replace(".", "", str_replace(",", "", number_format($this->virtual, 2)));
                $this->from = $this->virtual;
                $from = $this->from;
                $to = str_replace(".", "", str_replace(",", "", $this->currencyToDouble($this->amount)));
                $this->to = $this->amount;
                $to = $this->to;
                $ret = $from >= $to;
            }
        }
        return $ret;
    }

    public function refreshMembers()
    {
        if ($this->add || $this->update) {
            if ($this->commercial) {
                $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])->orderBy('last_name')->orderBy('first_name')->get();
            } else {
                $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])->where('current_status', 2)->orWhere('current_status', 1)->orderBy('last_name')->orderBy('first_name')->get();
            }
        } else
            $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])->orderBy('last_name')->orderBy('first_name')->get();
    }

    public function setAmount()
    {
        $tot = 0;
        foreach ($this->rows as $r) {
            $tot += $this->currencyToDouble($r["amount"]);
        }
        $this->amount = $tot;
        $this->canSave = $this->checkCanSave();
    }

    public function resetFields()
    {
        $this->member_id = null;
        $this->supplier_id = null;
        $this->payment_method_id = null;
        $this->destination_id = null;
        $this->commercial = 0;
        $this->corrispettivo_fiscale = false;
        $this->date = date("Y-m-d");
        $this->type = 'IN';
        $this->deleted = false;
        $this->financial_movement = false;
        $this->newMemberFirstName = '';
        $this->newMemberLastName = '';
        $this->newMemberEmail = '';
        $this->newMemberToComplete = false;
        $this->newMemberFiscalCode = '';
        $this->newMemberFiscalCodeExist = false;
        $this->currentReceip = null;
        $this->parent = '';
        $this->courseId = 0;
        $this->rateId = 0;
        $this->months = array();
        $this->rows = array();
        $this->rows[] = array('causal_id' => isset($_GET["causalId"]) ? $_GET["causalId"] : null, 'when' => array(array('month' => date("n"), 'year' => date("Y"), 'period' => '')),  'amount' => null, 'vat_id' => null, 'note' => '', 'commercial' => 0, 'sconto' => 0);
        $this->corrispettivo = [];
        $this->emit('load-data-table');
    }

    public function getMemberProperty()
    {
        $ret = null;
        if ($this->member_id > 0) {
            $ret = \App\Models\Member::findOrFail($this->member_id);
        }
        return $ret;
    }

    public function getCausalProperty()
    {
        $ret = null;
        if ($this->causal_id > 0) {
            $ret = \App\Models\Causal::findOrFail($this->causal_id);
        }
        return $ret;
    }

    public function getCausal($causal)
    {
        $ret = '';
        if ($causal > 0) {
            $ret = \App\Models\Causal::findOrFail($causal)->getTree();
        }
        return $ret;
    }

    public function getPaymentMethod($payment)
    {
        $ret = '';
        if ($payment > 0) {
            $ret = \App\Models\PaymentMethod::findOrFail($payment)->name;
        }
        return $ret;
    }

    function buildTree($records, $parentId = 0)
    {
        $this->causals = array();

        foreach ($records as $record) {
            if ($record->parent_id == $parentId) {
                $children = $this->buildTree($record, $record->id);
                if ($children) {
                    $record->children = $children;
                }
                $this->causals[] = $record;
            }
        }

        return $this->causals;
    }

    public function getCausale($records, $indentation)
    {
        foreach ($records as $record) {
            $this->causals[] = array('id' => $record->id, 'name' => $record->getTree(), 'text' => $record->getTree(), 'level' => $indentation);
            if (count($record->childs))
                $this->getCausale($record->childs, $indentation + 1);
        }
    }

    public function mount()
    {

        if (isset($_GET["from"])) {
            $this->fromPage = $_GET["from"];
        }

        $this->causals = array();

        $this->multiMonthFrom = date("n");
        $this->multiYearFrom = date("Y");
        $this->multiMonthTo = date("n");
        $this->multiYearTo = date("Y");

        $fisc = \App\Models\Causal::where('corrispettivo_fiscale', true)->first();
        if ($fisc)
            $this->corrispettivo_causal_id = $fisc->id;

        $this->getCausale(\App\Models\Causal::select('id', 'name')->where('parent_id', null)->where('type', 'IN')->get(), 0);

        //$this->buildTree(\App\Models\Causal::all(), null);

        $this->refreshMembers();
        $this->payments = \App\Models\PaymentMethod::select('id', 'name')->where('enabled', true)->whereIn('type', array('ALL', 'IN'))->orderBy('name')->get();
        $this->banks = \App\Models\Bank::select('id', 'name')->where('enabled', true)->whereIn('visibility', array('ALL', 'IN'))->orderBy('name')->get();
        $this->vats = \App\Models\Vat::select('id', 'name', 'value')->orderBy('value')->get();

        if ($this->first) {
            if (isset($_GET["new"])) {
                $this->refreshAfter = 1;
                $this->add();
            }
            if (isset($_GET["memberId"])) {
                $this->refreshAfter = 1;
                $this->member_id = $_GET["memberId"];
                $member = \App\Models\Member::findOrFail($this->member_id);
                if (!$member->isAdult()) {
                    if ($member->father_name != '')
                        $this->parent = $member->father_name . " (C.F. " . $member->father_fiscal_code . ")";
                    else if ($member->mother_name != '')
                        $this->parent = $member->mother_name . " (C.F. " . $member->mother_fiscal_code . ")";
                    else
                        $this->parent = '';
                }
            }
            if (isset($_GET["causalId"])) {
                $this->refreshAfter = 1;
                $this->causal_id = $_GET["causalId"];
            }
            if (isset($_GET["id"])) {
                $this->refreshAfter = 1;
                $this->edit($_GET["id"]);
            }
            $count = 0;
            if (isset($_GET["courseId"])) {
                $this->courseId = $_GET["courseId"];
                $mc = \App\Models\MemberCourse::findOrFail($this->courseId);
                $course = \App\Models\Course::findOrFail($mc->course_id);
            }
            if (isset($_GET["rateId"])) {
                $this->rateId = $_GET["rateId"];
            }
            if (isset($_GET["months"]) && $_GET["months"] != '') {

                $this->fromCourse = true;

                $price = $_GET["price"] / 100 * 100;
                $this->refreshAfter = 1;
                $desc = "Pagamento";
                $months = explode("|", $_GET["months"]);
                $this->months = $months;
                //$this->rows[0]["amount"] = formatPrice($price * sizeof($months));
                $this->rows[0]["amount"] = formatPrice($price);
                foreach ($months as $idx => $m) {
                    $this->rows[0]["when"][$idx]["month"] = $m;

                    if ($m >= date("m"))
                        $this->rows[0]["when"][$idx]["year"] = date("Y");
                    else
                        $this->rows[0]["when"][$idx]["year"] = date("Y") + 1;
                    /*if (env('FISCAL_YEAR_MONTH_FROM', 1) > 1)
                    {
                        if ($m > date("M"))
                            $this->rows[0]["when"][$idx]["year"] = $m < env('FISCAL_YEAR_MONTH_FROM', 1) ? (date("Y")) : date("Y" + 1);
                        else
                            $this->rows[0]["when"][$idx]["year"] = $m > env('FISCAL_YEAR_MONTH_TO', 1) ? (date("Y")) : date("Y" + 1);
                    }
                    else
                    {

                    }

                    if ($m > date("M"))
                        $this->rows[0]["when"][$idx]["year"] = $m < env('FISCAL_YEAR_MONTH_FROM', 1) ? (date("Y")) : date("Y" + 1);
                    else
                        $this->rows[0]["when"][$idx]["year"] = $m > env('FISCAL_YEAR_MONTH_TO', 1) ? (date("Y")) : date("Y" + 1);
                    */
                    if ($idx > 0) {
                        if ($this->rows[0]["when"][$idx - 1]["year"] != $this->rows[0]["when"][$idx]["year"])
                            $desc .= " " . $this->rows[0]["when"][$idx - 1]["year"] . " ";
                    }
                    $desc .= " " . $this->getMonth($m); // . " " . $this->rows[0]["when"][$idx]["year"];
                }
                $desc .= " " . $this->rows[0]["when"][$idx]["year"];
                $this->rows[0]["note"] = $desc;
                $count += 1;
            }


            if (isset($_GET["createSubscription"]) && $_GET["createSubscription"] == 1) {

                $this->createSubscription = 1;
                $this->courseId = $_GET["courseId"];
                $this->rateId = $_GET["rateId"];
                $price = $_GET["subscription_price"] / 100 * 100;
                $this->refreshAfter = 1;
                if ($count == 1)
                    $this->rows[] = array('causal_id' => null, 'when' => array(array('month' => date("n"), 'year' => date("Y"), 'period' => '')),  'amount' => null, 'vat_id' => null, 'note' => '', 'commercial' => 0);
                $this->rows[$count]["causal_id"] = null;
                $this->rows[$count]["amount"] = formatPrice($price);
                $this->rows[$count]["note"] = "Pagamento iscrizione " . $course->name;
                if (isset($_GET["subCausalId"])) {
                    $this->refreshAfter = 1;
                    $this->rows[$count]["causal_id"] = $_GET["subCausalId"];
                }
            }
        }
        $this->first = false;
    }

    public function search()
    {
        $this->hasFilter = true;
    }

    public function disableSearch()
    {
        $this->filterMember = 0;
        $this->filterPaymentMethod = 0;
        $this->filterCausals = 0;
        $this->filterTo = '';
        $this->filterFrom = '';
        $this->filterCommercial = 0;
        $this->hasFilter = false;
        $this->total = 0;
    }

    public function render()
    {

        $datas = [];
        return view('livewire.records_in', ['datas' => $datas]);
    }

    public function executeMultipleAction()
    {

        if ($this->multipleAction == 'delete')
            $this->multipleDelete();
    }

    public function add()
    {

        $this->emit('load-select');
        //if ($this->hasFilter)
        $this->emit('hide-search');
        $this->resetFields();
        $this->dataId = 0;
        $this->add = true;
        $this->update = false;
        $this->emit('setEdit', true);
    }

    public function storeCorrispettivo()
    {

        $this->emit('refresh');

        $rules = [
            'member_id' => 'required'
        ];

        $this->validate($rules);



        foreach ($this->payments as $p) {
            if ($p->corrispettivo_fiscale) {
                $price = isset($this->corrispettivo[$p->id]) ? $this->currencyToDouble($this->corrispettivo[$p->id]) : 0;

                if ($price > 0) {

                    $record = \App\Models\Record::create([
                        'member_id' => $this->member_id,
                        'supplier_id' => null,
                        'payment_method_id' => $p->id,
                        'destination_id' => $this->destination_id,
                        'commercial' => $this->commercial,
                        'corrispettivo_fiscale' => $this->corrispettivo_fiscale,
                        'date' => $this->date,
                        'type' => $this->type,
                        'amount' => $price,
                        'financial_movement' => $this->financial_movement,
                        'deleted' => $this->deleted
                    ]);

                    \App\Models\RecordRow::create([
                        'record_id' => $record->id,
                        'causal_id' => $this->corrispettivo_causal_id,
                        'note' => '',
                        'amount' => $price,
                        'vat_id' => null,
                        'commercial' => $this->commercial,
                        'when' => json_encode([])
                    ]);
                }
            }
        }

        $this->resetFields();
        $this->add = false;
        $this->isDuplicate = false;
        $this->emit('setEdit', false);
    }

    public function store($generate)
    {
        Log::info("Starting store method");
        $this->emit('refresh');

        $rules = [
            'payment_method_id' => 'required',
            'rows.*.causal_id' => 'required',
            'rows.*.amount' => 'required'
        ];

        if (!$this->commercial)
            $rules["member_id"] = 'required';

        $this->validate($rules);

        /* Validazione campi azienda per generazione ricevuta */
        try {
            if (!$this->financial_movement && !$this->commercial) {
                $no_receipt_causal_azienda = false;
                foreach ($this->rows as $row) {
                    $no_receipt_causal_azienda = false;

                    $cau = \App\Models\Causal::findOrFail($row["causal_id"]);
                    if ($cau->no_receipt)
                        $no_receipt_causal_azienda = true;
                }

                $azienda = \App\Models\Azienda::first();

                $payment_method = \App\Models\PaymentMethod::findOrFail($this->payment_method_id);
                if (!$payment_method->money) {
                    if (!$no_receipt_causal_azienda) {
                        if (!$azienda->isValid()) {
                            session()->flash('error_ricevuta', implode("", array_map(function ($item) {
                                return "<li>$item</li>";
                            }, $azienda->validate())));
                            return false;
                        }
                    }
                }
            }
        } catch (\Exception $ex) {
            Log::error("Error in store method: " . $ex->getMessage());
            Log::error("Stack trace: " . $ex->getTraceAsString());
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
        /* END - Validazione campi azienda per generazione ricevuta */

        try {


            $totalGross = 0;
            $totalSconto = 0;
            $totalNet = 0;

            foreach ($this->rows as $row) {
                $rowAmount = $this->currencyToDouble($row["amount"]);
                $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                $rowNet = max(0, $rowAmount - $rowSconto);

                $totalGross += $rowAmount;
                $totalSconto += $rowSconto;
                $totalNet += $rowNet;
            }

            Log::info("Total gross: " . $totalGross . ", Total sconto: " . $totalSconto . ", Total net: " . $totalNet);

            $record = \App\Models\Record::create([
                'member_id' => $this->member_id,
                'supplier_id' => $this->supplier_id,
                'payment_method_id' => $this->payment_method_id,
                'destination_id' => $this->destination_id,
                'commercial' => $this->commercial,
                'corrispettivo_fiscale' => $this->corrispettivo_fiscale,
                'date' => $this->date,
                'type' => $this->type,
                'amount' => $totalNet,
                'prediscount_amount' => $totalGross,
                'financial_movement' => $this->financial_movement,
                'deleted' => $this->deleted,
                'numero_fattura' => '',
            ]);

            $this->dataId = $record->id;

            $no_receipt_causal = false;
            $vat = 0;

            foreach ($this->rows as $row) {
                foreach ($row["when"] as $x => $y) {
                    $row["when"][$x]['period'] = $row["when"][$x]['month'] . "-" . $row["when"][$x]['year'];
                }

                $rowAmount = $this->currencyToDouble($row["amount"]);
                $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                $rowNet = max(0, $rowAmount - $rowSconto);

                Log::info("Row - Gross: " . $rowAmount . ", Sconto: " . $rowSconto . ", Net: " . $rowNet);

                \App\Models\RecordRow::create([
                    'record_id' => $this->dataId,
                    'causal_id' => $row["causal_id"],
                    'note' => $row["note"],
                    'amount' => $rowNet,
                    'prediscount_amount' => $rowAmount,
                    'sconto' => $rowSconto,
                    'vat_id' => $row["vat_id"],
                    'commercial' => $this->commercial,
                    'when' => json_encode($row["when"])
                ]);

                $vat += getVatValue($rowNet, $row["vat_id"]);

                $cau = \App\Models\Causal::findOrFail($row["causal_id"]);
                if ($cau->no_receipt)
                    $no_receipt_causal = true;

                if ($cau->money) {
                    if ($rowNet >= env('MIN_MONEY', 100)) {
                        $money = new \App\Models\Money();
                        $money->member_id = $this->member_id;
                        $money->record_id = $this->dataId;
                        $money->amount = env('EXTRA_MONEY', 10);
                        $money->date = date("Y-m-d");
                        $money->note = env('EXTRA_MONEY', 10) . ' in più per aver caricato ' . $rowNet;
                        $money->save();
                    }
                }
            }

            Log::info("Final amount saved to record: " . $totalNet);

            if (!$this->financial_movement) {
                $payment_method = \App\Models\PaymentMethod::findOrFail($this->payment_method_id);
                if (!$payment_method->money) {
                    if ($generate && !$no_receipt_causal)
                        $this->createReceipt();
                }
            }

            if ($this->rateId > 0) {

                $rates = explode(",", $this->rateId);
                foreach($rates as $rid)
                {
                    $rate = \App\Models\Rate::findOrFail($rid);
                    $rate->status = 1;
                    $rate->record_id = $record->id;
                    $rate->save();
                }

            }

            session()->flash('success', 'Movimento creato');
            $this->resetFields();
            $this->add = false;
            $this->isDuplicate = false;
            $this->emit('setEdit', false);
        } catch (\Exception $ex) {
            Log::error("Error in store method: " . $ex->getMessage());
            Log::error("Stack trace: " . $ex->getTraceAsString());
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function duplicate($id)
    {
        $record = \App\Models\Record::findOrFail($id);
        $newRecord = $record->replicate();
        $newRecord->save();
        $rows = \App\Models\RecordRow::where('record_id', $id)->get();
        foreach ($rows as $r) {
            $newRow = $r->replicate();
            $newRow->record_id = $newRecord->id;
            $newRow->save();
        }
        $this->edit($newRecord->id);
        $this->isDuplicate = true;
    }


    public function edit($id)
    {
        if (!isset($_GET["from"]) && $this->fromPage == '')
            $this->fromPage = 'in';
        $this->emit('setEdit', true);
        //if ($this->hasFilter)
        $this->emit('hide-search');
        $this->emit('load-select');

        try {
            $record = \App\Models\Record::findOrFail($id);
            if (!$record) {
                session()->flash('error', 'Movimento non trovato');
            } else {
                if ($record->member_id) {
                    $member = \App\Models\Member::find($record->member_id);
                    if (!$member || $member->status == 'archived') {
                        $this->member_id = null;
                    } else {
                        $this->member_id = $record->member_id;
                    }
                } else {
                    $this->member_id = $record->member_id;
                }

                if ($record->payment_method_id) {
                    $paymentMethod = \App\Models\PaymentMethod::find($record->payment_method_id);
                    if (!$paymentMethod || (isset($paymentMethod->hidden) && $paymentMethod->hidden)) {
                        $this->payment_method_id = null;
                    } else {
                        $this->payment_method_id = $record->payment_method_id;
                    }
                } else {
                    $this->payment_method_id = $record->payment_method_id;
                }

                $this->destination_id = $record->destination_id;
                $this->supplier_id = $record->supplier_id;
                $this->amount = $record->amount;
                $this->commercial = $record->commercial;
                $this->corrispettivo_fiscale = $record->corrispettivo_fiscale;
                $this->date = date("Y-m-d", strtotime($record->date));
                $this->type = $record->type;
                $this->deleted = $record->deleted;
                $this->financial_movement = $record->financial_movement;
                $this->dataId = $record->id;
                $this->update = true;
                $this->add = false;

                $rows = \App\Models\RecordRow::where('record_id', $this->dataId)
                    ->select('causal_id', 'note', 'commercial', 'when', 'amount', 'prediscount_amount', 'sconto', 'vat_id')
                    ->get();

                $this->rows = [];
                foreach ($rows as $i => $r) {
                    $grossAmount = $r->prediscount_amount ?? ($r->amount + $r->sconto);

                    $causalId = $r->causal_id;
                    if ($causalId) {
                        $causal = \App\Models\Causal::find($causalId);
                        if (!$causal || (isset($causal->hidden) && $causal->hidden)) {
                            $causalId = null;
                        }
                    }

                    $this->rows[] = [
                        'causal_id' => $causalId,
                        'note' => $r->note,
                        'commercial' => $r->commercial,
                        'when' => json_decode($r->when),
                        'amount' => formatPrice($grossAmount),
                        'sconto' => formatPrice($r->sconto),
                        'vat_id' => $r->vat_id
                    ];
                }

                $exist = \App\Models\Receipt::where('record_id', $id)->orderBy('id', 'DESC')->first();
                if ($exist != null) {
                    $this->currentReceip = $exist;
                    $this->parent = $this->currentReceip->parent;
                }

                $this->refreshEditOptions();
            }
        } catch (\Exception $ex) {
            Log::error("Error in edit method: " . $ex->getMessage());
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    private function refreshEditOptions()
    {
        $this->causals = array();
        $visibleCausals = \App\Models\Causal::select('id', 'name')
            ->where('parent_id', null)
            ->where('type', 'IN')
            ->where(function ($query) {
                $query->where('hidden', false)->orWhereNull('hidden');
            })
            ->get();
        $this->getCausale($visibleCausals, 0);

        $this->payments = \App\Models\PaymentMethod::select('id', 'name')
            ->where('enabled', true)
            ->whereIn('type', array('ALL', 'IN'))
            ->where(function ($query) {
                $query->where('hidden', false)->orWhereNull('hidden');
            })
            ->orderBy('name')
            ->get();

        if ($this->commercial) {
            $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])
                ->where(function ($query) {
                    $query->where('status', '!=', 'archived');
                })
                ->orderBy('last_name')
                ->orderBy('first_name')
                ->get();
        } else {
            $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])
                ->where(function ($query) {
                    $query->where('current_status', 2)->orWhere('current_status', 1);
                })
                ->where(function ($query) {
                    $query->where('status', '!=', 'archived');
                })
                ->orderBy('last_name')
                ->orderBy('first_name')
                ->get();
        }
    }

    public function update($generate = false)
    {
        Log::info("Starting update method");
        $this->emit('refresh');
        $rules = [
            'payment_method_id' => 'required',
            'rows.*.causal_id' => 'required',
            'rows.*.amount' => 'required'
        ];

        if (!$this->commercial)
            $rules["member_id"] = 'required';

        $this->validate($rules);

        /* Validazione campi azienda per generazione ricevuta */
        try {
            if (!$this->financial_movement && !$this->commercial) {
                $no_receipt_causal_azienda = false;
                foreach ($this->rows as $row) {
                    $no_receipt_causal_azienda = false;

                    $cau = \App\Models\Causal::findOrFail($row["causal_id"]);
                    if ($cau->no_receipt)
                        $no_receipt_causal_azienda = true;
                }

                $azienda = \App\Models\Azienda::first();

                $payment_method = \App\Models\PaymentMethod::findOrFail($this->payment_method_id);
                if (!$payment_method->money) {
                    if (!$no_receipt_causal_azienda) {
                        if (!$azienda->isValid()) {
                            session()->flash('error_ricevuta', implode("", array_map(function ($item) {
                                return "<li>$item</li>";
                            }, $azienda->validate())));
                            return false;
                        }
                    }
                }
            }
        } catch (\Exception $ex) {
            Log::error("Error in store method: " . $ex->getMessage());
            Log::error("Stack trace: " . $ex->getTraceAsString());
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
        /* END - Validazione campi azienda per generazione ricevuta */

        try {
            $totalGross = 0;
            $totalSconto = 0;
            $totalNet = 0;

            foreach ($this->rows as $row) {
                $rowAmount = $this->currencyToDouble($row["amount"]);
                $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                $rowNet = max(0, $rowAmount - $rowSconto);

                $totalGross += $rowAmount;
                $totalSconto += $rowSconto;
                $totalNet += $rowNet;
            }

            Log::info("Total gross: " . $totalGross . ", Total sconto: " . $totalSconto . ", Total net: " . $totalNet);

            \App\Models\Record::whereId($this->dataId)->update([
                'member_id' => $this->member_id,
                'supplier_id' => $this->supplier_id,
                'payment_method_id' => $this->payment_method_id,
                'destination_id' => $this->destination_id,
                'commercial' => $this->commercial,
                'corrispettivo_fiscale' => $this->corrispettivo_fiscale,
                'date' => date("Y-m-d", strtotime($this->date)),
                'type' => $this->type,
                'financial_movement' => $this->financial_movement,
                'deleted' => $this->deleted,
                'amount' => $totalNet,
                'prediscount_amount' => $totalGross,
            ]);

            $no_receipt_causal = false;
            $vat = 0;

            \App\Models\RecordRow::where('record_id', $this->dataId)->delete();

            foreach ($this->rows as $row) {
                foreach ($row["when"] as $x => $y) {
                    $row["when"][$x]['period'] = $row["when"][$x]['month'] . "-" . $row["when"][$x]['year'];
                }

                $rowAmount = $this->currencyToDouble($row["amount"]);
                $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                $rowNet = max(0, $rowAmount - $rowSconto);

                Log::info("Row - Gross: " . $rowAmount . ", Sconto: " . $rowSconto . ", Net: " . $rowNet);

                \App\Models\RecordRow::create([
                    'record_id' => $this->dataId,
                    'causal_id' => $row["causal_id"],
                    'note' => $row["note"],
                    'vat_id' => $row["vat_id"],
                    'amount' => $rowNet,
                    'prediscount_amount' => $rowAmount,
                    'sconto' => $rowSconto,
                    'commercial' => $this->commercial,
                    'when' => json_encode($row["when"])
                ]);

                $vat += getVatValue($rowNet, $row["vat_id"]);

                $cau = \App\Models\Causal::findOrFail($row["causal_id"]);
                if ($cau->no_receipt)
                    $no_receipt_causal = true;
            }

            Log::info("Final amount saved to record: " . $totalNet);

            if (!$this->financial_movement) {
                $payment_method = \App\Models\PaymentMethod::findOrFail($this->payment_method_id);
                if (!$payment_method->money) {
                    if ($generate && !$no_receipt_causal)
                        $this->createReceipt();
                }
            }
            session()->flash('success', 'Movimento aggiornato');
            $this->resetFields();
            $this->update = false;
            $this->isDuplicate = false;
            $this->emit('setEdit', false);
        } catch (\Exception $ex) {
            Log::error("Error in update method: " . $ex->getMessage());
            Log::error("Stack trace: " . $ex->getTraceAsString());
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function rigenerate()
    {
        $this->emit('refresh');

        try {

            $record = \App\Models\Record::findOrFail($this->dataId);
            $newRecord = $record->replicate();
            $newRecord->date = date("Y-m-d");
            $newRecord->save();

            $recordRows = \App\Models\RecordRow::where('record_id', $this->dataId)->get();
            // Inserisco le righe
            foreach ($recordRows as $row) {
                $newRow = $row->replicate();
                $newRow->record_id = $newRecord->id;
                $newRow->save();
            }

            $this->dataId = $newRecord->id;

            $this->createReceipt();

            session()->flash('success', 'Movimento aggiornato');
            $this->resetFields();
            $this->update = false;
            $this->isDuplicate = false;
            $this->emit('setEdit', false);
        } catch (\Exception $ex) {
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function cancel()
    {
        // Se arrivo da duplica elimino
        if ($this->isDuplicate) {
            try {
                \App\Models\Record::find($this->dataId)->delete();
                session()->flash('success', "Movimento eliminato");
            } catch (\Exception $e) {
                session()->flash('error', 'Errore (' . $e->getMessage() . ')');
            }
        }
        $this->isDuplicate = false;

        $this->add = false;
        $this->update = false;
        $this->resetFields();
        $this->emit('setEdit', false);
        return redirect()->to('/in');
    }

    public function delete($id)
    {
        try {

            $r = \App\Models\Record::find($id);

            // Annullo la ricevuta
            $receipt = \App\Models\Receipt::where('record_id', $r->id)->first();
            if ($receipt) {
                $receipt->status = 99;
                sendReceiptDeleteEmail($receipt);
                $receipt->save();
            }

            if ($r->member_course_id > 0) {
                $months = json_decode($r->months);
                $c = \App\Models\MemberCourse::findOrFail($r->member_course_id);
                $xxx = json_decode($c->months);
                foreach ($xxx as $idx => $mm) {
                    if (in_array($mm->m, $months)) {
                        $xxx[$idx]->status = "";
                    }
                }
                $c->months = json_encode($xxx);
                $c->save();
            }

            $r->deleted = true;
            $r->save();

            session()->flash('success', 'Movimento aggiornato');
            $this->resetFields();
            $this->update = false;
            $this->isDuplicate = false;
            $this->emit('setEdit', false);

            $this->emit('reload');

            //$this->emit('load-data-table');

        } catch (\Exception $ex) {
            session()->flash('error', 'Errore (' . $ex->getMessage() . ')');
        }
    }

    public function multipleDelete()
    {
        try {
            foreach ($this->multipleIds as $id) {
                \App\Models\Record::find($id)->delete();
            }
        } catch (\Exception $e) {
            session()->flash('error', 'Errore (' . $e->getMessage() . ')');
        }
        $this->multipleAction = '';
    }

    public function createMember()
    {

        $this->newMemberFiscalCodeExist = false;
        $this->validate([
            // 'newMemberFiscalCode'=>'required|max:16',
            'newMemberFirstName' => 'required',
            'newMemberLastName' => 'required',
            //'newMemberEmail'=>'required',
        ]);

        // Check fiscal code exist
        $exist = false;
        if ($this->newMemberFiscalCode != '') {
            $check = \App\Models\Member::where('fiscal_code', $this->newMemberFiscalCode)->get();
            $exist = $check->count() > 0;
        }
        if (!$exist) {
            $member = \App\Models\Member::create([
                'first_name' => strtoupper($this->newMemberFirstName),
                'last_name' => strtoupper($this->newMemberLastName),
                'email' => strtoupper($this->newMemberEmail),
                'to_complete' => $this->newMemberToComplete,
                'fiscal_code' => $this->newMemberFiscalCode,
                'status' => true
            ]);
            $this->member_id = $member->id;
            $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])->get();
            // $this->emit('reloadMembers');
            $this->emit('refresh');
            $this->newMemberFirstName = '';
            $this->newMemberLastName = '';
            $this->newMemberEmail = '';
            $this->newMemberToComplete = false;
            $this->newMemberFiscalCode = '';
            $this->emit('saved');
            //$this->validate();
            $this->selectId++;
        } else {
            $this->newMemberFiscalCodeExist = true;
        }
    }

    public function createReceipt()
    {
        // Ulteriore controllo commerciale/non commerciale
        if (!$this->commercial) {
            $create = false;
            $receipt = \App\Models\Receipt::where('record_id', $this->dataId)->orderBy('id', 'DESC')->first();
            if ($receipt != null) {

                // Controllo lo stato, se 99 ne genero una nuova
                if ($receipt->status == 99) {
                    $create = true;
                }
            } else {
                $create = true;
            }

            if ($create) {
                $number = 1;
                $exist = \App\Models\Receipt::where('year', date("Y"))->orderBy('number', 'DESC')->first();
                if ($exist != null)
                    $number = $exist->number + 1;

                // Calculate totals for the receipt
                $totalGross = 0;
                $totalNet = 0;
                foreach ($this->rows as $row) {
                    $rowAmount = $this->currencyToDouble($row["amount"]);
                    $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                    $rowNet = max(0, $rowAmount - $rowSconto);

                    $totalGross += $rowAmount;
                    $totalNet += $rowNet;
                }

                $receipt = \App\Models\Receipt::create([
                    'record_id' => $this->dataId,
                    'member_id' => $this->member_id,
                    'supplier_id' => $this->supplier_id,
                    'payment_method_id' => $this->payment_method_id,
                    'number' => $number,
                    'date' => $this->date,
                    'year' => date("Y"),
                    'type' => $this->type,
                    'parent' => $this->parent,
                    'status' => 1,
                ]);

                foreach ($this->rows as $row) {
                    $rowAmount = $this->currencyToDouble($row["amount"]);
                    $rowSconto = isset($row['sconto']) ? $this->currencyToDouble($row['sconto']) : 0;
                    $rowNet = max(0, $rowAmount - $rowSconto);

                    Log::info("Receipt Row - Gross: " . $rowAmount . ", Sconto: " . $rowSconto . ", Net: " . $rowNet);

                    \App\Models\ReceiptRow::create([
                        'receip_id' => $receipt->id,
                        'causal_id' => $row["causal_id"],
                        'note' => $row["note"],
                        'vat_id' => $row["vat_id"],
                        'amount' => $rowNet,
                        'prediscount_amount' => $rowAmount,
                        'sconto' => $rowSconto,
                        'commercial' => $row["commercial"],
                        'when' => json_encode($row["when"])
                    ]);
                }

                $this->currentReceip = $receipt;

                sendReceiptEmail($receipt);

                session()->flash('receipt', "Ricevuta " . $number . "/" . date("Y") . " creata correttamente");

                $this->emit('showReceipt', $this->currentReceip->id);
            }
        }
    }

    public function removeReceipt()
    {
        $receipt = \App\Models\Receipt::findOrFail($this->currentReceip->id);
        $receipt->status = 99;
        $receipt->save();
        sendReceiptDeleteEmail($receipt);
        $this->currentReceip = $receipt;
    }

    function currencyToDouble($val)
    {
        $x = str_replace("€", "", $val);
        $x = str_replace(".", "", $x);
        $x = str_replace(",", ".", $x);
        return floatval(trim($x));
    }


    public function addRow()
    {
        $this->rows[] = array('causal_id' => null, 'when' => array(array('month' => date("n"), 'year' => date("Y"), 'period' => '')),  'amount' => null, 'vat_id' => null, 'note' => '', 'commercial' => 0);
        $this->emit('load-select');
    }

    public function delRow($idx)
    {
        unset($this->rows[$idx]);
        // $this->emit('load-select');
    }

    public function addPeriod($idx)
    {
        $x = sizeof($this->rows[$idx]['when']) - 1;
        $newDate = \Carbon\Carbon::create($this->rows[$idx]['when'][$x]["year"] . "-" . $this->rows[$idx]['when'][$x]["month"] . '-01')->addMonth();
        $this->rows[$idx]['when'][] = array('month' => $newDate->format("n"), 'year' => $newDate->format("Y"), 'period' => '');
    }

    public function delPeriod($idx, $xxx)
    {
        array_splice($this->rows[$idx]['when'], $xxx, $xxx);
        //unset($this->rows[$idx]['when'][$xxx]);
        // $this->emit('load-select');
    }
    public function getTotal()
    {
        $total = 0.00;

        foreach ($this->rows as $r) {
            if ($r["amount"] != null && $r["amount"] != "") {
                $rowAmount = $this->currencyToDouble($r["amount"]);
                $rowSconto = isset($r['sconto']) ? $this->currencyToDouble($r['sconto']) : 0;
                $netAmount = max(0, $rowAmount - $rowSconto);

                $total += $netAmount;

                if ($r["vat_id"] > 0)
                    $total += getVatValue($netAmount, $r["vat_id"]);
            }
        }

        return formatPrice($total);
    }
    public function getTotalCorrispettivo()
    {
        $total = 0.00;
        foreach ($this->corrispettivo as $r) {
            $total += $this->currencyToDouble($r);
        }
        return formatPrice($total);
        // $this->emit('load-select');
    }

    public function getPrice()
    {
        $total = 0.00;
        foreach ($this->rows as $r) {
            if ($r["amount"] != null && $r["amount"] != "")
                $total += $this->currencyToDouble($r["amount"]);
        }
        return formatPrice($total);
        // $this->emit('load-select');
    }

    public function getVat()
    {
        $total = 0.00;
        foreach ($this->rows as $r) {
            if ($r["amount"] != null && $r["amount"] != "" && $r["vat_id"] > 0)
                $total += getVatValue($this->currencyToDouble($r["amount"]), $r["vat_id"]);
        }
        return formatPrice($total);
        // $this->emit('load-select');
    }

    public function getVats()
    {
        $vats = array();
        foreach ($this->rows as $r) {
            if ($r["amount"] != null && $r["amount"] != "" && $r["vat_id"] > 0) {
                $vat = getVatValue($this->currencyToDouble($r["amount"]), $r["vat_id"]);
                $vatName = "";
                foreach ($this->vats as $v) {
                    if ($v->id == $r["vat_id"])
                        $vatName = $v->name;
                }
                if (isset($vats[$vatName]))
                    $vats[$vatName] += $vat;
                else
                    $vats[$vatName] = $vat;
            }
        }
        return $vats;
        // $this->emit('load-select');
    }

    public function setCausal($id, $idx)
    {
        $this->rows[$idx]["causal_id"] = $id;
    }

    public function printReceipt()
    {
        //$pdf = PDF::loadView('pdf/receipt', array('datas' => $datas, 'from' => $x, 'to' => $y, 'who' => '', 'matricola' => $matricola));
        $pdf = PDF::loadView('receipt', array('receipt' => $this->currentReceip)); //->output();
        $pdfName = "Ricevuta_" . $this->currentReceip->member->last_name . "_" . $this->currentReceip->number . "_" . $this->currentReceip->year . ".pdf";
        return $pdf->stream();
        /*return response()->streamDownload(
            fn () => print($pdf),
            "ricevuta_" . $this->currentReceip->number . "_" . $this->currentReceip->year . ".pdf"
        );*/
        /*return response()->streamDownload(function () {
            echo $pdf->stream();
        }, 'test.pdf');*/
    }

    public function multiPeriod()
    {
        $this->multiP = true;
    }

    public function multiPeriodCreate($idx)
    {

        $period = \Carbon\CarbonPeriod::create($this->multiYearFrom . '-' . $this->multiMonthFrom . '-01', '1 month', $this->multiYearTo . '-' . $this->multiMonthTo . '-01');
        $this->rows[$idx]['when'] = [];
        foreach ($period as $dt) {
            if (!in_array(array('month' => $dt->format("n"), 'year' => $dt->format("Y"), 'period' => ''), $this->rows[$idx]['when']))
                $this->rows[$idx]['when'][] = array('month' => $dt->format("n"), 'year' => $dt->format("Y"), 'period' => '');
        }

        $this->multiP = false;
    }

    public function multiPeriodCancel()
    {
        $this->multiP = false;
    }

    public function getMonth($m)
    {
        $ret = '';
        switch ($m) {
            case 1:
                $ret = 'Gennaio';
                break;
            case 2:
                $ret = 'Febbraio';
                break;
            case 3:
                $ret = 'Marzo';
                break;
            case 4:
                $ret = 'Aprile';
                break;
            case 5:
                $ret = 'Maggio';
                break;
            case 6:
                $ret = 'Giugno';
                break;
            case 7:
                $ret = 'Luglio';
                break;
            case 8:
                $ret = 'Agosto';
                break;
            case 9:
                $ret = 'Settembre';
                break;
            case 10:
                $ret = 'Ottobre';
                break;
            case 11:
                $ret = 'Novembre';
                break;
            case 12:
                $ret = 'Dicembre';
                break;
            default:
                $ret = '';
                break;
        }
        return $ret;
    }

    public function setYear($idx, $xxx)
    {
        $m = $this->rows[$idx]["when"][$xxx]["month"];
        $this->rows[$idx]["when"][$xxx]["year"] = $m < env('FISCAL_YEAR_MONTH_FROM', 1) ? (date("Y") + 1) : date("Y");
    }
}
