<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Simulatore contabilità
 *
 * @package    mod_mtcontabilita
 * @copyright  2026 Mediatouch 2000 Srl <https://www.mediatouch.it>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @author     Marco Cappuccio <m.cappuccio@mediatouch.it>
 */

require_once('../../../config.php');
require_once('locallib.php');
require_once('../question2/locallib.php');

$cmid      = required_param('id', PARAM_INT);
$uid       = required_param('uid', PARAM_INT);
$attemptid = required_param('attemptid', PARAM_INT);
$tp        = required_param('tp', PARAM_ALPHA);

list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'mtcontabilita');
require_course_login($course, true, $cm);
$context  = context_module::instance($cm->id);
$contextc = context_course::instance($course->id);

if (!has_capability('mod/mtcontabilita:addinstance', $contextc)) {
    throw new \moodle_exception('nopermissions', 'error', '', get_string('nopermissions', 'mod_mtcontabilita'));
}

$binit = $DB->get_field('mtcontabilita', 'binit', ['id' => $cm->instance]);
if (!$binit) {
    $tp = "s";
}

$bdecimali = $DB->get_field('mtcontabilita', 'bdecimali', ['id' => $cm->instance]);
$bdecimali = (int)($bdecimali ?? 2);
$ndec = mtc_get_ndec_for_mtcontabilita($cm->instance, $bdecimali);

$tp = ($tp === 's') ? 's' : 'i'; // Default i.
$totalscore = 0.0; // Somma automatica da DB (ai.score).
$totalmanual = 0.0; // Somma dei punteggi manuali.
$totalmax    = 0.0; // Ssomma dei punteggi massimi configurati.
$totaleffective = 0.0; // Punteggio effettivo (manuale se presente, altrimenti automatico).
$initialtotalmaxfromconfig = false;

$PAGE->set_context($context);
$PAGE->set_url(new moodle_url('/mod/mtcontabilita/evaluation/details.php', [
    'id' => $cmid, 'uid' => $uid, 'attemptid' => $attemptid, 'tp' => $tp,
]));

$sort     = optional_param('sort', ($tp === 'i' ? 'scheme' : 'id'), PARAM_ALPHANUMEXT);
$dir      = optional_param('dir', 'ASC', PARAM_ALPHA);
$page     = optional_param('page', 0, PARAM_INT);
$perpage  = optional_param('perpage', 30, PARAM_INT);
$action   = optional_param('action', '', PARAM_ALPHA);
$sesskeyok = optional_param('sesskey', '', PARAM_RAW);
// Salvataggio punteggio manuale (se/quando vorrai implementarlo).
$action    = optional_param('action', '', PARAM_ALPHA);

// Salvataggio punteggi manuali.
if ($action === 'save' && confirm_sesskey()) {
    require_sesskey();
    require_capability('mod/mtcontabilita:addinstance', $contextc);

    $manual = optional_param_array('manualscore', [], PARAM_RAW);

    $transaction = $DB->start_delegated_transaction();

    if ($tp === 's') {
        // SCRITTURE: il key è il NUMERO SCRITTURA (itemnum).
        foreach ($manual as $itemnum => $val) {
            $itemnum = (int)$itemnum;
            $val = trim((string)$val);

            // Tutte le righe di questa scrittura.
            $items = $DB->get_records('mtcontabilita_attempt_items', [
                'attemptid' => $attemptid,
                'bitem'     => 's',
                'itemnum'   => $itemnum,
            ], 'id ASC');

            if (!$items) {
                continue;
            }

            if ($val === '') {
                // Cancello il manuale da tutte le righe.
                foreach ($items as $it) {
                    $DB->set_field('mtcontabilita_attempt_items', 'scoremanual', 0, ['id' => $it->id]);
                }
            } else {
                $num = unformat_float($val);
                $itemcount = count($items);
                $totalcents = (int)round($num * 100);
                $basecents = intdiv($totalcents, $itemcount);
                $remainder = $totalcents % $itemcount;
                $i = 0;
                foreach ($items as $it) {
                    $rowcents = $basecents;
                    if ($i < abs($remainder)) {
                        $rowcents += ($remainder > 0) ? 1 : -1;
                    }
                    $DB->set_field('mtcontabilita_attempt_items', 'scoremanual', $rowcents / 100, ['id' => $it->id]);
                    $i++;
                }
            }
        }
    } else {
        // INIZIALE: il key è l'ID di ai.
        foreach ($manual as $itemid => $val) {
            $itemid = (int)$itemid;
            $val = trim((string)$val);
            if ($val === '') {
                $DB->set_field('mtcontabilita_attempt_items', 'scoremanual', 0, ['id' => $itemid]);
            } else {
                $num = unformat_float($val);
                $DB->set_field('mtcontabilita_attempt_items', 'scoremanual', $num, ['id' => $itemid]);
            }
        }
    }

    $transaction->allow_commit();

    redirect(new moodle_url($PAGE->url), get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
    exit;
}

$fullname = fullname(core_user::get_user($uid));
$isenglish = (strpos(current_language(), 'en') === 0);

$currenttab = "TAB".$tp;

echo $OUTPUT->header();
echo $OUTPUT->heading($fullname);

if ($binit) {
    include_once('tabs.php');
}

// Columns dinamiche
if ($tp === 'i') {
    $columns = ['conto', 'itemamount', 'scheme', 'dareavere'];
    if (!$isenglish) {
        $columns[] = 'macroclasse';
    }
    $columns[] = 'score';
    $columns[] = 'scoremanual';
} else {
    // n°, data, conto, dare, avere, punteggio sistema, punteggio manuale, vedi soluzione
    $columns = ['num', 'date', 'conto', 'd', 'a', 'score', 'scoremanual', 'showcorrectsolution'];
}

$sortcol = ['conto', 'scheme', 'score', 'importo'];
if (!$isenglish) {
    $sortcol[] = 'macroclasse';
}

// Preparazione header clickabili (solo dove ha senso).
$header = [];
foreach ($columns as $column) {
    // Label diversa per alcune colonne "speciali" delle scritture.
    switch ($column) {
        case 'num':
            $label = '#';
            break;
        case 'conto':
            $label = get_string('conto2', 'mtcontabilita');
            break;
        case 'date':
            $label = get_string('date'); // stringa standard core
            break;
        case 'd':
            $label = get_string('d', 'mtcontabilita');
            break;
        case 'a':
            $label = get_string('a', 'mtcontabilita');
            break;
        default:
            $label = get_string($column, 'mtcontabilita');
    }

    $columndir = ($sort === $column && strtoupper($dir) === 'ASC') ? 'DESC' : 'ASC';

    // Ordino solo su alcuni campi
    $sortable = in_array($column, $sortcol)
        || ($tp === 'i' && in_array($column, ['conto', 'importo']))
        || ($tp === 's' && in_array($column, ['conto', 'score']));

    if ($sortable) {
        $header[] = html_writer::link(
            new moodle_url($PAGE->url, ['sort' => $column, 'dir' => $columndir]),
            $label
        );
    } else {
        $header[] = $label;
    }
}

// Query
list($extrasql, $params) = ["", []];
$records = mtcontabilita_evaluation_details::get_users_listing($cm->instance, $uid, $attemptid, $tp,
    $sort, $dir, $page * $perpage, $perpage, '', '', '', $extrasql, $params, $context);

$maxbyitemnum = [];
$totalmax = 0.0;

if ($tp === 'i') {
    $totalmax = (float)$DB->get_field_sql("
        SELECT COALESCE(SUM(score), 0)
         FROM {mtcontabilita_itemdet}
         WHERE mtcontabilitaid = :mtid
           AND itemnum = :itemnum
           AND type > 0
    ", ['mtid' => $cm->instance, 'itemnum' => '0']);
    $initialtotalmaxfromconfig = ($totalmax > 0.0);
} else if ($tp === 's') {
    $maxbyitemnum = $DB->get_records_sql_menu("
        SELECT itemnum, SUM(score) AS scoremax
          FROM {mtcontabilita_itemdet}
         WHERE mtcontabilitaid = :mtid
           AND type = 0
         GROUP BY itemnum
         ORDER BY itemnum
    ", ['mtid' => $cm->instance]);

    // Totale massimo COMPLETO (tutte le scritture previste).
    foreach ($maxbyitemnum as $n => $mx) {
        $totalmax += (float)$mx;
    }
}



// Count (se vuoi barra paging “vera”, metti una count separata; qui riciclo la tua).
$usercount = mtcontabilita_evaluation_details::count_items($cm->instance, $uid, $attemptid, $tp,
    '', '', '', $extrasql, $params, $context);

echo $OUTPUT->paging_bar($usercount, $page, $perpage, $PAGE->url);

// Helpers parsing JSON (robusti a formati parziali).
$parseiniziale = function(?string $json, $fallbackside = null) {
    $out = ['importo' => null, 'side' => $fallbackside];
    if ($json) {
        $j = json_decode($json, true);
        if (is_array($j)) {
            // Adatta le chiavi alle tue: provo vari nomi comuni
            $ini = $j['iniziale'] ?? $j['initial'] ?? null;
            if (is_array($ini)) {
                $out['importo'] = isset($ini['importo']) ? (float)$ini['importo'] : (isset($ini['amount']) ? (float)$ini['amount'] : null);
                $out['side']    = $ini['side'] ?? $out['side'];
            }
        }
    }
    return $out;
};
$parsescritture = function(?string $json) {
    // Restituisce array di righe ['d' => float|null, 'a' => float|null].
    $rows = [];
    if (!$json) {
        return $rows;
    }

    $j = json_decode($json, true);
    if (!is_array($j)) {
        return $rows;
    }

    // Può essere un array "puro" oppure dentro 'righe' / 'rows'.
    if (isset($j['righe']) && is_array($j['righe'])) {
        $j = $j['righe'];
    } else if (isset($j['rows']) && is_array($j['rows'])) {
        $j = $j['rows'];
    }

    $norm = function($v) {
        if ($v === '' || $v === null) {
            return null;
        }
        $v = trim((string)$v);
        if ($v === '' || $v === 'x') {
            return null;
        }
        // come normalizza_valore() in saveattemptmastrino.php
        // $v = str_replace('.', '', $v);
        $v = str_replace(',', '.', $v);
        if ($v === '' || !is_numeric($v)) {
            return null;
        }
        return (float)$v;
    };

    foreach ($j as $r) {
        if (!is_array($r)) {
            continue;
        }
        $d = $norm($r['d'] ?? null);
        $a = $norm($r['a'] ?? null);
        if ($d === null && $a === null) {
            continue;
        }
        $rows[] = ['d' => $d, 'a' => $a];
    }

    return $rows;
};


$table = new html_table();
$table->attributes['class'] = 'admintable generaltable table-sm';


// Colonne diverse per tp = i / s
if ($tp === 'i') {
    // ['conto', 'itemamount', 'scheme', 'dareavere', 'macroclasse?', 'score', 'scoremanual']
    $table->colclasses = [
        '',            // conto
        'text-right',  // importo
        '',            // scheme
        '',            // dare/avere
    ];
    if (!$isenglish) {
        $table->colclasses[] = ''; // macroclasse
    }
    $table->colclasses[] = 'text-right'; // punteggio sistema
    $table->colclasses[] = ''; // punteggio manuale
} else {
    // ['num', 'date', 'conto', 'd', 'a', 'score', 'scoremanual', 'showcorrectsolution']
    $table->colclasses = [
        '',            // num
        '',            // date
        '',            // conto
        'text-right',  // dare
        'text-right',  // avere
        'text-right',  // punteggio sistema
        '',            // punteggio manuale
        '',            // icona vedi soluzione
    ];
}

$table->head = $header;

// Form per punteggio manuale
echo html_writer::start_tag('form', ['method' => 'post', 'action' => $PAGE->url]);
echo html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()]);
echo html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'action',  'value' => 'save']);


if ($records) {

    if ($tp === 's') {
        $grouped = [];

        foreach ($records as $r) {
            $key = $r->attemptitemnum ?? $r->itemnum ?? $r->id;

            if (!isset($grouped[$key])) {
                $grouped[$key] = (object)[
                    'attemptitemnum' => $r->attemptitemnum ?? $r->itemnum ?? '',
                    'itemdate'       => $r->itemdate,
                    'rows'           => [],    // <- qui mettiamo le righe conto/d/a
                    'score'          => 0.0,
                    'scoremanual'    => 0.0,
                    'hasmanual'      => false,
                    'scoremax' => 0.0,
                ];
            }

            $g =& $grouped[$key];

            // if ($g->scoremax === null && isset($r->scoremax) && $r->scoremax !== null) {
            //     // max della scrittura (uno solo)
            //     $g->scoremax = (float)$r->scoremax;
            // }
            // Conto testuale
            $contostr = format_string($r->conto ?? '');

            // Righe D/A dal JSON dell'utente
            $righe = $parsescritture($r->daamount);

            if ($righe) {
                foreach ($righe as $rig) {
                    $g->rows[] = [
                        'conto' => $contostr,
                        'd'     => $rig['d'],
                        'a'     => $rig['a'],
                    ];
                }
            } else {
                // Nessuna riga nel JSON: comunque aggiungo il conto "vuoto"
                $g->rows[] = [
                    'conto' => $contostr,
                    'd'     => null,
                    'a'     => null,
                ];
            }

            // Punteggi.
            if (!is_null($r->score)) {
                $g->score += (float)$r->score;
            }
            if (!is_null($r->scoremanual) && (float)$r->scoremanual > 0) {
                $g->scoremanual += (float)$r->scoremanual;
                $g->hasmanual = true;
            }

            if ($g->scoremax == 0.0 && isset($r->scoremax) && $r->scoremax !== null) {
                $g->scoremax = (float)$r->scoremax;
            }

        }

        $records = array_values($grouped);
    }

    foreach ($records as $r) {
        $rowmax = null;

        if ($tp === 'i') {
            // ----------------- SITUAZIONE DI PARTENZA (come prima) -----------------
            $sidedb = isset($r->da) ? strtoupper($r->da) : null;

            $ini = $parseiniziale($r->daamount, $sidedb);

            $importo = $ini['importo'];
            if (is_null($importo) && isset($r->importo)) {
                $importo = (float)$r->importo;
            }

            if (!$ini['side'] && is_numeric($importo)) {
                $ini['side'] = ($importo < 0) ? 'A' : 'D';
                $importo = abs($importo);
            }

            $row = [];
            $row[] = format_string($r->conto ?? '');
            $row[] = is_null($importo) ? '' : mtc_get_db($importo, $ndec);
            $scheme = strtolower(trim((string)($r->scheme ?? '')));
            $row[] = $scheme !== '' ? get_string($scheme, 'mtcontabilita') : '';
            $row[] = ($ini['side'] === 'D' ? get_string('d', 'mtcontabilita') : ($ini['side'] === 'A' ? get_string('a', 'mtcontabilita') : ''));
            if (!$isenglish) {
                $row[] = s($r->macroclasse ?? '');
            }
            $row[] = is_null($r->score) ? '' : format_float($r->score, 2);
            $row[] = html_writer::empty_tag('input', [
                'type'  => 'number',
                'step'  => '0.01',
                'name'  => "manualscore[{$r->id}]",
                'value' => (!is_null($r->scoremanual) && (float)$r->scoremanual > 0)
                    ? format_float($r->scoremanual, 2)
                    : '',
                'class' => 'form-control form-control-sm',
                'style' => 'width:7rem',
            ]);

            $rowauto = is_null($r->score) ? null : (float)$r->score;
            $rowmanual = (!is_null($r->scoremanual) && (float)$r->scoremanual > 0)
                ? (float)$r->scoremanual
                : null;

            $rowmax = (isset($r->scoremax) && $r->scoremax !== null) ? (float)$r->scoremax : null;

            $table->data[] = $row;

        } else {
            // ----------------- SCRITTURE: UNA RIGA PER SCRITTURA -----------------
            $row = [];
            // N° = numero scrittura.
            $row[] = $r->attemptitemnum;
            // data
            $row[] = $r->itemdate ? userdate($r->itemdate, get_string('strftimedate', 'langconfig')) : '';
            // Prepariamo le tre colonne riga-per-riga.
            $contilines = [];
            $dlines     = [];
            $alines     = [];

            foreach ($r->rows as $line) {
                $contilines[] = $line['conto'];

                $dlines[] = is_null($line['d'])
                    ? ''
                    : mtc_get_db($line['d'], $ndec);

                $alines[] = is_null($line['a'])
                    ? ''
                    : mtc_get_db($line['a'], $ndec);
            }

            // Conto: una riga per mastrino.
            $row[] = implode('<br>', $contilines);
            // Dare.
            $row[] = implode('<br>', $dlines);
            // Avere.
            $row[] = implode('<br>', $alines);

            // Punteggio sistema (somma delle righe).
            $row[] = $r->score ? format_float($r->score, 2) : '';
            // Punteggio manuale: uno solo per scrittura, indicizzato per itemnum.
            $row[] = html_writer::empty_tag('input', [
                'type'  => 'number',
                'step'  => '0.01',
                'name'  => "manualscore[{$r->attemptitemnum}]",
                'value' => $r->hasmanual ? format_float($r->scoremanual, 2) : '',
                'class' => 'form-control form-control-sm',
                'style' => 'width:7rem',
            ]);

            // Pulsante "Vedi soluzione" (sempre per itemnum).
            $detailurl = new moodle_url('/mod/mtcontabilita/evaluation/solution.php', [
                'id'      => $cmid,
                'mtid'    => $cm->instance,
                'itemnum' => $r->attemptitemnum,
            ]);

            $icon = new pix_icon('t/preview', get_string('showcorrectsolution', 'mtcontabilita'));
            $popupaction = new popup_action('click', $detailurl, 'scritturasol' . $r->attemptitemnum, [
                'height' => 500,
                'width'  => 700,
            ]);

            $row[] = $OUTPUT->action_icon($detailurl, $icon, $popupaction);

            $table->data[] = $row;

            // Totali per scrittura.
            $rowauto   = $r->score ? (float)$r->score : null;
            $rowmanual = ($r->hasmanual && $r->scoremanual > 0) ? (float)$r->scoremanual : null;
            $rowmax = isset($r->scoremax) ? (float)$r->scoremax : null;
        }

        // --- Totali globali ---
        if (!is_null($rowauto)) {
            $totalscore += $rowauto;
        }
        if (!is_null($rowmanual)) {
            $totalmanual += $rowmanual;
        }
        if (!is_null($rowmanual)) {
            $totaleffective += $rowmanual;
        } else if (!is_null($rowauto)) {
            $totaleffective += $rowauto;
        }
        if (!is_null($rowmax) && ($tp !== 'i' || !$initialtotalmaxfromconfig)) {
            $totalmax += $rowmax;
        }


    }

} else {
    $table->data[] = [get_string('nothingtodisplay')];
}

echo html_writer::start_tag('div', ['class' => 'no-overflow']);
echo html_writer::table($table);
echo html_writer::end_tag('div');

// Totali.
$totalshtml = html_writer::div(
    html_writer::tag('strong', 'Tot: ')
    .format_float($totaleffective, 2)
    .' / '.format_float($totalmax, 2)
    , 'mt-2'
);

echo $totalshtml;

// Bottoni: Salva e Torna alla lista.
$backurl = new moodle_url('/mod/mtcontabilita/evaluation/', ['id' => $cmid]);
echo html_writer::start_div('mt-3');
echo html_writer::tag('button', get_string('savechanges'), ['type' => 'submit', 'class' => 'btn btn-primary me-2']);
echo html_writer::link($backurl, get_string('back2list', 'mtcontabilita'), ['class' => 'btn btn-secondary']);
echo html_writer::end_div();

echo html_writer::end_tag('form');

echo $OUTPUT->paging_bar($usercount, $page, $perpage, $PAGE->url);
echo $OUTPUT->footer();
