<?php
/*
 * OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
 * Copyright (C) DevCode s.r.l.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

include_once __DIR__.'/../../core.php';

use Modules\Anagrafiche\Anagrafica;
use Modules\Banche\Banca;
use Modules\Fatture\Fattura;

/**
 * Questo file gestisce la lettura delle informazioni di Scadenze e Fatture indicate per la generazione della Prima Nota. Per maggiori informazioni sulla grafica inerente alla visualizzazione delle diverse righe, consulare il file `movimenti.php`.
 *
 * Questo file prevede diverse operazioni per la generazione di un singolo array `$movimenti` contenente tutti i movimenti da presentare nella Prima Nota. In particolare:
 *  - Individua Scadenze e Fatture per ID da URL
 *  - Legge le informazioni relative alle Scadenze per presentare i movimenti in Dare e Avere
 *  - Legge le informazioni relative alla Scadenze le Fatture indicate (sola della prima Scadenza insoluta se `is_insoluto` impostato):
 *      - Per Fatture di vendita, il totale è Avere (a meno di Note di credito oppure insoluto)
 *      - Per Fatture di acquisto, il totale è Dare (a meno di Note di credito oppure insoluto)
 *  - Inverte Dare e Avere se l'importo indicato è negativo [TODO: documentare la casistica]
 *  - Genera la causale predefinita per la Prima Nota sulla base delle Scadenze indicate
 *
 * Nel caso in cui sia indicato una singola Scadenza (con o senza Fattura associata) viene permessa la gestione attraverso un Modello di Prima Nota, che prevede una compilazione di base per alcuni movimenti specificati nel relativo modulo.
 * Nota: questo comportamento viene abilitato dalla variabile `$permetti_modelli`.
 */
$module = Modules::get('Prima nota');
$movimenti = [];

// Registrazione da remoto
$id_records = get('id_records');
if (!empty($id_records)) {
    $id_records = str_replace(';', ',', $id_records);
    if (get('origine') == 'fatture') {
        $id_documenti = $id_records;
    } else {
        $id_scadenze = $id_records;
    }
}

// ID predefiniti
$singola_scadenza = get('single') != null;
$is_insoluto = get('is_insoluto') != null;

$id_documenti = $id_documenti ?: get('id_documenti');
$id_documenti = $id_documenti ? explode(',', $id_documenti) : [];

$id_scadenze = $id_scadenze ?: get('id_scadenze');
$id_scadenze = $id_scadenze ? explode(',', $id_scadenze) : [];

// Controllo per l'utilizzo dei modelli di Prima Nota (per singolo documento o singola scadenza)
$permetti_modelli = (count($id_documenti) + count($id_scadenze)) <= 1;

// Scadenze
foreach ($id_scadenze as $id_scadenza) {
    $scadenza = $database->fetchOne('SELECT *, SUM(da_pagare - pagato) AS rata FROM co_scadenziario WHERE id='.prepare($id_scadenza));
    if (!empty($scadenza['iddocumento'])) {
        $id_documenti[] = $scadenza['iddocumento'];
        continue;
    }
    $dir = $scadenza['rata'] > 0 ? 'entrata' : 'uscita';
    $scadenza['rata'] = abs($scadenza['rata']);

    $descrizione_conto = ($dir == 'entrata') ? 'Riepilogativo clienti' : 'Riepilogativo fornitori';
    $conto = $database->fetchOne('SELECT id FROM co_pianodeiconti3 WHERE descrizione = '.prepare($descrizione_conto));
    $id_conto_controparte = $conto['id'];

    $righe_documento = [];
    $righe_documento[] = [
        'iddocumento' => null,
        'id_scadenza' => $scadenza['id'],
        'id_conto' => null,
        'dare' => ($dir == 'uscita') ? 0 : $scadenza['rata'],
        'avere' => ($dir == 'uscita') ? $scadenza['rata'] : 0,
    ];

    $righe_documento[] = [
        'iddocumento' => null,
        'id_scadenza' => $scadenza['id'],
        'id_conto' => $id_conto_controparte,
        'dare' => ($dir == 'uscita') ? $scadenza['rata'] : 0,
        'avere' => ($dir == 'uscita') ? 0 : $scadenza['rata'],
    ];

    // Se è un insoluto, inverto i valori
    if ($is_insoluto) {
        foreach ($righe_documento as $key => $value) {
            $tmp = $value['avere'];
            $righe_documento[$key]['avere'] = $righe_documento[$key]['dare'];
            $righe_documento[$key]['dare'] = $tmp;
        }
    }

    $movimenti = array_merge($movimenti, $righe_documento);
}

// Fatture
$numeri_fatture = [];
$counter = 0;
$is_ultimo_importo_avere = false;

$id_documenti = array_unique($id_documenti);
$id_anagrafica_movimenti = null;
foreach ($id_documenti as $id_documento) {
    $fattura = Fattura::find($id_documento);
    $tipo = $fattura->tipo;
    $dir = $fattura->direzione;

    // Inclusione delle sole fatture in stato Emessa, Parzialmente pagato o Pagato
    if (!in_array($fattura->stato->descrizione, ['Emessa', 'Parzialmente pagato', 'Pagato'])) {
        ++$counter;
        continue;
    }

    if ($id_anagrafica_movimenti == null) {
        $id_anagrafica_movimenti = $fattura->idanagrafica;
    } elseif ($fattura->idanagrafica != $id_anagrafica_movimenti) {
        $id_anagrafica_movimenti = 0;
    }

    $numeri_fatture[] = !empty($fattura['numero_esterno']) ? $fattura['numero_esterno'] : $fattura['numero'];

    $is_nota_credito = $tipo->reversed;
    $is_importo_avere = ($dir == 'entrata' && !$is_nota_credito && !$is_insoluto) || ($dir == 'uscita' && ($is_nota_credito || $is_insoluto));

    // Predisposizione prima riga
    $banca = Banca::find($fattura->id_banca_azienda);
    $conto_field = 'idconto_'.($dir == 'entrata' ? 'vendite' : 'acquisti');
    $id_conto_aziendale = $banca->id_pianodeiconti3 ?: ($fattura->pagamento[$conto_field] ?: setting('Conto aziendale predefinito'));

    // Se sto registrando un insoluto, leggo l'ultima scadenza pagata altrimenti leggo la scadenza della fattura
    if ($is_insoluto) {
        $scadenze = $database->fetchArray('SELECT id, ABS(da_pagare) AS rata, iddocumento, tipo FROM co_scadenziario WHERE iddocumento='.prepare($id_documento).' AND ABS(da_pagare) = ABS(pagato) ORDER BY updated_at DESC LIMIT 0, 1');
    } else {
        $scadenze = $database->fetchArray('SELECT id, ABS(da_pagare - pagato) AS rata, iddocumento, tipo FROM co_scadenziario WHERE iddocumento='.prepare($id_documento).' AND ABS(da_pagare) > ABS(pagato)'.(!empty($id_scadenze) ? 'AND id IN('.implode(',', $id_scadenze).')' : '').' ORDER BY YEAR(scadenza) ASC, MONTH(scadenza) ASC');
    }

    // Selezione prima scadenza
    if ($singola_scadenza && !empty($scadenze)) {
        $scadenze = [$scadenze[0]];
    }

    $righe_documento = [];

    // Riga controparte
    foreach ($scadenze as $scadenza) {
        // Predisposizione conto
        if ($scadenza['tipo'] == 'ritenutaacconto') {
            $id_conto_controparte = setting("Conto per Erario c/ritenute d'acconto");
        } else {
            $conto_field = 'idconto_'.($dir == 'entrata' ? 'cliente' : 'fornitore');
            $id_conto_controparte = $fattura->anagrafica[$conto_field];
        }

        $righe_documento[] = [
            'iddocumento' => $scadenza['iddocumento'],
            'id_scadenza' => $scadenza['id'],
            'id_conto' => $id_conto_controparte,
            'dare' => $is_importo_avere ? 0 : $scadenza['rata'],
            'avere' => $is_importo_avere ? $scadenza['rata'] : 0,
        ];
    }

    // Riga aziendale
    $totale = sum(array_column($scadenze, 'rata'));

    $righe_documento[] = [
        'iddocumento' => $scadenze[0]['iddocumento'],
        'id_scadenza' => $scadenze[0]['id'],
        'id_conto' => $id_conto_aziendale,
        'dare' => $is_importo_avere ? $totale : 0,
        'avere' => $is_importo_avere ? 0 : $totale,
    ];

    $is_ultimo_importo_avere = $is_importo_avere;
    $movimenti = array_merge($movimenti, $righe_documento);
}

// Inverto dare e avere per importi negativi
foreach ($movimenti as $key => $value) {
    if ($movimenti[$key]['dare'] < 0 || $movimenti[$key]['avere'] < 0) {
        $tmp = abs($movimenti[$key]['dare']);
        $movimenti[$key]['dare'] = abs($movimenti[$key]['avere']);
        $movimenti[$key]['avere'] = $tmp;
    }
}

// Descrizione
$numero_scadenze = count($id_scadenze);
$numero_documenti = count($id_documenti);
if ($numero_documenti + $numero_scadenze > 1) {
    if (!empty($id_anagrafica_movimenti)) {
        $anagrafica_movimenti = Anagrafica::find($id_anagrafica_movimenti);

        $descrizione = $is_ultimo_importo_avere ? tr('Inc. fatture _NAME_ num. _LIST_') : tr('Pag. fatture _NAME_ num. _LIST_');
        $descrizione = replace($descrizione, [
            '_NAME_' => $anagrafica_movimenti->ragione_sociale ?: '',
            '_LIST_' => implode(', ', $numeri_fatture),
        ]);
    } else {
        $descrizione = $is_ultimo_importo_avere ? tr('Inc. fatture num. _LIST_') : tr('Pag. fatture _NAME_ num. _LIST_');
        $descrizione = replace($descrizione, [
            '_LIST_' => implode(', ', $numeri_fatture),
        ]);
    }
} elseif ($numero_documenti == 1) {
    $numero_fattura = !empty($fattura['numero_esterno']) ? $fattura['numero_esterno'] : $fattura['numero'];
    $tipo_fattura = $fattura->isNota() ? $tipo->descrizione : tr('Fattura');

    if (!empty($is_insoluto)) {
        $operation = tr('Registrazione insoluto');
    } else {
        $operation = $is_ultimo_importo_avere ? tr('Inc.') : tr('Pag.');
    }

    $descrizione = tr('_OP_ _DOC_ num. _NUM_ del _DATE_ (_NAME_)', [
        '_OP_' => $operation,
        '_DOC_' => strtolower($tipo_fattura),
        '_NUM_' => $numero_fattura,
        '_DATE_' => Translator::dateToLocale($fattura['data']),
        '_NAME_' => $fattura->anagrafica['ragione_sociale'],
    ]);
} elseif ($numero_scadenze == 1) {
    $descrizione = tr('Pag. _OP_ del _DATE_', [
        '_OP_' => $scadenza['descrizione'],
        '_DATE_' => Translator::dateToLocale($scadenza['scadenza']),
    ]);
}

if (!empty($id_records) && get('origine') == 'fatture' && !empty($counter)) {
    $descrizione_stati = [];
    $stati = $database->fetchArray("SELECT * FROM `co_statidocumento` WHERE descrizione IN ('Emessa', 'Parzialmente pagato', 'Pagato') ORDER BY descrizione");
    foreach ($stati as $stato) {
        $descrizione_stati[] = '<i class="'.$stato['icona'].'"></i> <small>'.$stato['descrizione'].'</small>';
    }

    echo '
<div class="alert alert-info">
<p>'.tr('Solo le fatture in stato _STATE_ possono essere registrate contabilmente ignorate', [
            '_STATE_' => implode(', ', $descrizione_stati),
        ]).'.</p>
<p><b>'.tr('Sono state ignorate _NUM_ fatture', [
            '_NUM_' => $counter,
        ]).'.</b></p>
</div>';
}
if (!empty(get('id_anagrafica'))) {
    $id_anagrafica = get('id_anagrafica');
} else {
    $id_anagrafica = $dbo->fetchOne('SELECT idanagrafica FROM co_documenti WHERE id IN('.(get('id_documenti') ?: '0').')')['idanagrafica'];
}
echo '
<form action="'.base_path().'/controller.php?id_module='.$module->id.'" method="post" id="add-form">
	<input type="hidden" name="op" value="add">
	<input type="hidden" name="backto" value="record-edit">
	<input type="hidden" name="crea_modello" id="crea_modello" value="0">
	<input type="hidden" name="idmastrino" id="idmastrino" value="0">
    <input type="hidden" name="is_insoluto" value="'.$is_insoluto.'">
    <input type="hidden" name="id_anagrafica" id="id_anagrafica" value="'.$id_anagrafica.'">';

if ($permetti_modelli) {
    echo '
	<div class="row">
		<div class="col-md-12">
			{[ "type": "select", "label": "'.tr('Modello prima nota').'", "name": "modello_primanota", "values": "query=SELECT idmastrino AS id, nome AS descrizione, descrizione as causale FROM co_movimenti_modelli GROUP BY idmastrino" ]}
		</div>
	</div>';
}

echo '
	<div class="row">
		<div class="col-md-4">
			{[ "type": "date", "label": "'.tr('Data movimento').'", "name": "data", "required": 1, "value": "-now-" ]}
		</div>

		<div class="col-md-8">
			{[ "type": "text", "label": "'.tr('Causale').'", "name": "descrizione", "id": "desc", "required": 1, "value": '.json_encode($descrizione).' ]}
		</div>
    </div>';

if (!empty($id_anagrafica)) {
    $id_conto_anticipo_fornitori = setting('Conto anticipo fornitori');
    $id_conto_anticipo_clienti = setting('Conto anticipo clienti');

    $anticipo_cliente = $dbo->fetchOne('SELECT ABS(SUM(totale)) AS totale FROM co_movimenti WHERE  co_movimenti.id_anagrafica='.prepare($id_anagrafica).' AND  co_movimenti.idconto='.prepare($id_conto_anticipo_clienti));

    $anticipo_fornitore = $dbo->fetchOne('SELECT ABS(SUM(totale)) AS totale FROM co_movimenti WHERE  co_movimenti.id_anagrafica='.prepare($id_anagrafica).' AND  co_movimenti.idconto='.prepare($id_conto_anticipo_fornitori));

    if ($anticipo_fornitore['totale'] != 0) {
        echo '
        <div class="alert alert-warning">
            '.tr('Attenzione: è stato anticipato al fornitore un importo di _TOTALE_',
                [
                    '_TOTALE_' => moneyFormat($anticipo_fornitore['totale']),
                ]
            ).'
        </div>';
    }

    if ($anticipo_cliente['totale'] != 0) {
        echo '
        <div class="alert alert-warning">
            '.tr('Attenzione: è stato ricevuto un anticipo dal cliente di _TOTALE_',
                [
                    '_TOTALE_' => moneyFormat($anticipo_cliente['totale']),
                ]
            ).'
        </div>';
    }
}

include $structure->filepath('movimenti.php');

echo '
	<!-- PULSANTI -->
	<div class="row">
		<div class="col-md-12 text-right">
			<button type="button" class="btn btn-info" disabled id="modello-button">
			    <i class="fa fa-plus"></i> '.tr('Aggiungi e crea modello').'
            </button>

			<button type="submit" class="btn btn-primary" disabled id="add-submit">
			    <i class="fa fa-plus"></i> '.tr('Aggiungi').'
            </button>
		</div>
	</div>
</form>';

echo '
<script type="text/javascript">
$("#modals > div #add-form").on("submit", function(e) {
    return controllaConti();
});
</script>';

if ($permetti_modelli) {
    $variables = Modules::get('Fatture di vendita')->getPlaceholders($id_documenti[0]);

    echo '
<script type="text/javascript">
    globals.prima_nota = {
        variables: '.json_encode($variables).',
        id_documento: "'.$id_documenti[0].'",
        translations: {
            nuovoModello: "'.tr('Aggiungi e crea modello').'",
            modificaModello: "'.tr('Aggiungi e modifica modello').'",
        },
        id_mastrino_input: input("idmastrino"),
        modello_input: input("modello_primanota"),
        modello_button: $("#modello-button"),
    };

    var modello_input = globals.prima_nota.modello_input;
    var id_mastrino_input = globals.prima_nota.id_mastrino_input;
    var modello_button = globals.prima_nota.modello_button;
    modello_button.prop("disabled", false);

    modello_input.change(function() {
        let id_mastrino = modello_input.get();
        if (id_mastrino) {
            $("#modello-button").html(`<i class="fa fa-edit"></i> ` + globals.prima_nota.translations.modificaModello);
            id_mastrino_input.set(id_mastrino);
        } else {
            $("#modello-button").html(`<i class="fa fa-plus"></i> ` + globals.prima_nota.translations.nuovoModello);
            id_mastrino_input.set(0);
            return;
        }

        // Aggiornamento della causale nel caso di Fattura
        let causale = modello_input.getData().causale;
        if (globals.prima_nota.id_documento !== "") {
            for ([key, value] of Object.entries(globals.prima_nota.variables)) {
                causale = causale.replace(key, value);
            }

            $("#modals > div #desc").val(causale);
        }

        if ($("#modals > div #desc").val() == "") {
            $("#modals > div #desc").val(causale);
        }

        $.get(globals.rootdir + "/ajax_complete.php?op=get_conti&idmastrino=" + id_mastrino, function(data) {
            let conti = data.split(",");
            let table = $("#modals table.scadenze").first();
            let button = table.parent().find("button").first();

            // Creazione delle eventuali righe aggiuntive
            let row_needed = conti.length;
            let row_count = table.find("tr").length - 2;
            while (row_count < row_needed) {
                button.click();
                row_count = table.find("tr").length - 2;
            }

            // Iterazione su tutti i conti del Modello
            let righe = table.find("tr");
            for (let i = 0; i < conti.length; i++) {
                const dati_conto = conti[i].split(";");

                let id_conto = parseInt(dati_conto[0]);
                let descrizione_conto = dati_conto[1];
                let totale = dati_conto[2];

                // Sostituzione del conto dell\'Anagrafica
                if (id_conto === -1 && globals.prima_nota.id_documento !== ""){
                    id_conto = parseInt(globals.prima_nota.variables["conto"]);
                    descrizione_conto = globals.prima_nota.variables["conto_descrizione"];
                }

                // Selezione del conto
                let select = $(righe[i + 1]).find("select");
                input(select).getElement()
                    .selectSetNew(id_conto, descrizione_conto);

                if(totale>0){
                    input_field = $(righe[i + 1]).find("input[id*=dare]");
                } else{
                    input_field = $(righe[i + 1]).find("input[id*=avere]");
                    totale = -totale;
                }
                input(input_field).getElement()
                        .val(totale).trigger("change");
            }
        });

    });

    $("#modals > div #modello-button").click(function() {
        $("#modals > div #crea_modello").val("1");
        $("#modals > div #add-form").submit();
    });
</script>';
}