<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Rap2hpoutre\FastExcel\FastExcel;
use App\Models\Categorie;
use App\Models\Conto;
use App\Models\User;
use App\Models\ImportRule;


class Movimenti extends Model
{
    use HasFactory;
    protected $dates = ['mov_data'];
    protected $casts = [ 'mov_data'=>'datetime'];

    protected $fillable = [
        'mov_data',
        'mov_fk_categoria',
        'mov_descrizione',
        'mov_importo_dare',
        'mov_importo_avere',
        'mov_inserito_da',
        'mov_fk_tags',
        'conto_id_da',
        'conto_id_a',
        'import_hash',
    ];

   /*
    public static $query = 'SELECT
        a.id,
        a.mov_data,
        a.mov_importo_dare,
        a.mov_importo_avere,
        a.mov_descrizione,
        c.cat_name,
        t.tag_name,
        (SELECT Count(entity_id) as quanti FROM gen_docs WHERE entity=0 AND entity_id = a.id) as quanti
    FROM movimentis as a
    JOIN tags as t ON a.mov_fk_tags=t.id
    JOIN categories as c ON a.mov_fk_categoria=c.id';
    */

    public function ContoDa()
{
    return $this->belongsTo(Conto::class, 'conto_id_da');
}

public function ContoA()
{
    return $this->belongsTo(Conto::class, 'conto_id_a');
}

    public function User()
    {
        return $this->belongsTo(User::class);
    }

    public function Categorie()
    {
        return $this->belongsTo(Categorie::class, 'mov_fk_categoria');
    }

    public function Tags()
    {
        return $this->belongsTo(tag::class);
    }

    public static function getList() {

        // ISSUE #3 - Aggiunta visualizzazione conto da e conto a nella lista dei movimenti
        // e risoluzione duplicazione movimenti.

       return self::with(['Tags', 'Categorie', 'ContoDa', 'ContoA'])->orderBy('mov_data','desc')->get();
    }

    public static function getSaldo($date) {
        $dare=DB::table('movimentis')->whereYear('mov_data','=',$date)->sum('mov_importo_dare');
        $avere=DB::table('movimentis')->whereYear('mov_data','=',$date)->sum('mov_importo_avere');
        return $dare-$avere;
    }

    public static function getSaldoTot() {

        $importo_dare = DB::table('movimentis')->sum('mov_importo_dare');
        $importo_avere = DB::table('movimentis')->sum('mov_importo_avere');
        return $mov_importo=$importo_avere-$importo_dare;
    }

    public static function insSpesa( $request) {
        DB::table('movimentis')->insert(
            [
                'mov_data'=>$request->mov_data,
                'mov_fk_categoria'=>$request->mov_fk_categoria,
                'mov_descrizione'=>$request->mov_descrizione,
                'mov_importo_dare'=>$request->mov_importo,
                'mov_fk_tags'=>$request->mov_fk_tags,
                'mov_inserito_da'=>$request->userid,
                'conto_id_da'=>$request->conto_id_da,
                'conto_id_a'=>$request->conto_id_a,
                // 'conto_id_da'=>$request->conto_id_da,
                // 'conto_id_a'=>$request->conto_id_a,
            ]);
    }

    public static function giroconto($request){

        $requestUscita=$request;
        $requestEntrata=$request;

        $requestUscita['conto_id']=$requestUscita->daConto;
        $requestUscita['mov_fk_tags']=1;
        $rqUscita = $requestUscita;
         self::insSpesa($rqUscita);

        $requestEntrata['conto_id']=$requestEntrata->aConto;
        $requestEntrata['mov_fk_tags']=1;
        $rqEntrata = $requestEntrata;
        self::insEntrata($rqEntrata);
        unset($requestUscita['daConto']);
        unset($requestEntrata['aConto']);

    }

    public static function insEntrata( $request) {
        DB::table('movimentis')->insert(
            [
                'mov_data'=>$request['mov_data'],
                'mov_fk_categoria'=>$request['mov_fk_categoria'],
                'mov_descrizione'=>$request['mov_descrizione'],
                'mov_importo_avere'=>$request['mov_importo'],
                'mov_fk_tags'=>$request['mov_fk_tags'],
                'mov_inserito_da'=>$request['userid'],
                //'conto_id'=>$request->conto_id,
                'conto_id_da'=>$request->conto_id_da,
                'conto_id_a'=>$request->conto_id_a,
            ]);
    }

    public static function export() {
        return DB::table('movimentis')
        ->join('categories','movimentis.mov_fk_categoria','=','categories.id')
        ->join('tags','movimentis.mov_fk_tags','=','tags.id')
        ->selectRaw('
            mov_data AS Data,
            cat_name AS Categoria,
            tag_name AS Tag,
            mov_descrizione AS Descrizione,
            mov_importo_dare AS Importo_dare,
            mov_importo_avere AS Importo_avere')
        ->orderBy('Data','asc')
        ->get();
    }

    public static function reportSpesa($year,$month) {
        return DB::table('movimentis')
        ->selectRaw('ABS(Sum(movimentis.mov_importo_dare)) as resoconto, categories.cat_name,categories.id')
        ->join('categories','movimentis.mov_fk_categoria','=','categories.id')
       // ->where('mov_importo_','<',0)
        ->whereYear('mov_data',$year)
        ->whereMonth('mov_data',$month)
        ->groupBy('cat_name','categories.id')
        ->get();
    }

    public static function reportEntrate($year,$month) {
        return DB::table('movimentis')
        ->selectRaw('ABS(Sum(movimentis.mov_importo_avere)) as resoconto, categories.cat_name,categories.id')
        ->join('categories','movimentis.mov_fk_categoria','=','categories.id')
        //->where('mov_importo','>',0)
        ->whereYear('mov_data',$year)
        ->whereMonth('mov_data',$month)
        ->groupBy('cat_name','categories.id')
        ->get();
    }

    public static function getMovimentoById($id) {
        return DB::table('movimentis')
        ->join('categories','movimentis.mov_fk_categoria','=','categories.id')
        ->join('tags','movimentis.mov_fk_tags','=','tags.id')
        ->where('movimentis.id','=',$id)
        ->get();
    }

    public static function updateMovimenti($request) {
                $updateData = [];
        if (isset($request['mov_data'])) $updateData['mov_data'] = $request['mov_data'];
        if (isset($request['mov_fk_categoria'])) $updateData['mov_fk_categoria'] = $request['mov_fk_categoria'];
        if (isset($request['mov_descrizione'])) $updateData['mov_descrizione'] = $request['mov_descrizione'];
        if (isset($request['mov_importo_dare'])) $updateData['mov_importo_dare'] = $request['mov_importo_dare'];
        if (isset($request['mov_importo_avere'])) $updateData['mov_importo_avere'] = $request['mov_importo_avere'];
        if (isset($request['mov_fk_tags'])) $updateData['mov_fk_tags'] = $request['mov_fk_tags'];
        if (isset($request['userid'])) $updateData['mov_inserito_da'] = $request['userid'];

        self::where('id', $request['id'])->update($updateData);

    }

    public static function deleteMovimento($id) {
        DB::table('movimentis')
        ->where('id','=', $id)
        ->delete();
    }

    public static function listByCatMonth($month,$cat,$year) {

    return self::with(['Tags', 'Categorie'])
    ->whereMonth('mov_data', $month)
    ->whereYear('mov_data', $year)
    ->where('mov_fk_categoria', $cat)
    ->get();
    }

    public static function listByCategory($cat) {

        return self::with(['Tags', 'Categorie'])
        ->where('mov_fk_categoria', $cat)
        ->get();

    }

    public static function makeHash($data,$movimento_dare, $movimento_avere, $descrizione)
    {
        // crea l'hash (serve per evitare duplicati nei movimenti)
        return md5($data.$movimento_dare.$movimento_avere.$descrizione);
    }

    public static function importHashExists($hash)
    {
        return self::where('import_hash', $hash)->exists();
    }

    public static function importNoDuplicate($data)
    {
        $hash = Movimenti::makeHash($data['mov_data'], $data['mov_importo_dare'], $data['mov_importo_avere'], $data['mov_descrizione']);
        $exists = self::where('import_hash', $hash)->exists();
        if (!$exists) {
            self::create([
                // TODO: ...altri campi...
                'mov_data' => $data['mov_data'],
                'mov_fk_categoria' => $data['mov_fk_categoria'],
                'mov_descrizione' => $data['mov_descrizione'],
                'mov_importo_dare' => $data['mov_importo_dare'],
                'mov_importo_avere' => $data['mov_importo_avere'],
                'mov_inserito_da' => 1,
                'conto_id_da' => 1,
                'conto_id_a' => 1,
                'mov_fk_tags' => 1,
                'import_hash' => $hash,
            ]);
        }
    }

    public static function getByTag($tag) {
        $expression=DB::raw('SELECT
        a.id,
        a.mov_data,
        a.mov_importo_dare,
        a.mov_importo_avere,
        a.mov_descrizione,
        c.cat_name,
        t.tag_name,
        (SELECT Count(entity_id) as quanti FROM gen_docs WHERE entity=0 AND entity_id = a.id) as quanti
    FROM movimentis as a
    JOIN tags as t ON a.mov_fk_tags=t.id
    JOIN categories as c ON a.mov_fk_categoria=c.id
    WHERE a.mov_fk_tags = '.$tag );
    $query = $expression->getValue(DB::connection()->getQueryGrammar());
    return DB::select($query);
    }

    public static function importEstrattoIng($filename)
    {

        $inputPath='/var/www/html/gestionale2025/storage/app/public/'.$filename;
        // $outputPath='/var/www/html/gestionale_mt/public/tenant'.tenant('id').'/import/'.$filename.'.csv';
        $outputPath = $inputPath.'.csv';
        rename($inputPath,$outputPath);
        $collection = (new FastExcel)->configureCsv(";")->import($outputPath, function ($line){
            if($line['DATA VALUTA'])
            {
                if($line['ENTRATE']!=null)
                {
                    $importo = $line['ENTRATE'];
                } elseif($line['USCITE']!=null)
                {
                    $importo = $line['USCITE'];
                }
                $euro=str_replace(',','.',str_replace('+','',str_replace('.','', $importo)));
                list($giorno,$mese,$anno) = explode('/',$line['DATA VALUTA']);
                $data="$anno-$mese-$giorno";
                self::insEntrata([
                    'mov_data'=>self::dateFormat(0,$line['DATA VALUTA']),
                    'mov_fk_categoria'=>1,
                    'mov_descrizione'=>$line['DESCRIZIONE OPERAZIONE'],
                    'mov_importo'=>$euro,
                    'mov_fk_tags'=>1,
                    'userid'=>1,
                ]);
            }
        });
        unlink($outputPath);

    }

    public static function importEstrattoCR($filename)
    {
        $inputPath='/var/www/html/gestionale2025/storage/app/public/'.$filename;
        // $outputPath='/var/www/html/gestionale_mt/public/'.tenant('id')."/app/".$filename;
        $outputPath = $inputPath.'.csv';
        rename($inputPath,$outputPath);

        //$outputPath="/var/www/html/gestionale_mt/storage/tenant".tenant('id')."/app/".$filename;

        $collection = (new FastExcel)->configureCsv(';')->import($outputPath, function ($line){
            if($line['VALUTA'])
            {
                if($line['DARE']<>'')
                {
                $dati=[
                    'mov_data'=>self::dateFormat(0,$line['VALUTA']),
                //     date_format(date_create($movimento->mov_data),'d/m/Y'
                //    'mov_data'=>date_format(date_create($line['VALUTA']),'Y-m-d'),
                    'mov_fk_categoria'=>1,
                    'mov_descrizione'=>$line['DESCRIZIONE OPERAZIONE'],
                    'mov_importo'=>'-'.trim(str_replace(',','.',(str_replace('.','',$line['DARE'])))),
                    'mov_fk_tags'=>1,
                    'userid'=>1,
                ];
                }
                if($line['AVERE']<>'')
                {
                    $dati=[
                        'mov_data'=>self::dateFormat(0,$line['VALUTA']),
                        //'mov_data'=>date_format(date_create($line['VALUTA']),'Y-m-d'),
                        'mov_fk_categoria'=>1,
                        'mov_descrizione'=>$line['DESCRIZIONE OPERAZIONE'],
                        'mov_importo'=>trim(str_replace(',','.',(str_replace('.','',$line['AVERE'])))),
                        'mov_fk_tags'=>1,
                        'userid'=>1,
                    ];
                }
                self::insEntrata($dati);
            }
        });
        unlink($outputPath);
    }

    // Test filtri categoria
    public static function retrieveHeaders($filename)
    {
        $inputPath= Storage::path($filename);
        $outputPath = $inputPath.'.csv';
        rename($inputPath,$outputPath);

        $rows = (new FastExcel)->configureCsv(';')->import($outputPath);
        $headers = array_keys($rows->first());
        return $headers;
    }

    public static function getDbFields()
    {
        return  [
            "Data movimento"=>"mov_data",
            "Descrizione"=>"mov_descrizione",
            "Importo Dare"=>"mov_importo_dare",
            "Importo Avere"=>"mov_importo_avere",
            "Categoria"=>"mov_fk_categoria",
            "Tag"=>"mov_fk_tags",
            "Conto prelievo"=>"conto_id_da",
            "Conto versamento"=>"conto_id_a",
        ];
    }



    // Ritorna la categoria suggerita in base alla descrizione del movimento da utilizzare sul db
    public static function getSuggestedCategory($descrizione)
    {
        $rule = ImportRule::whereRaw('? LIKE CONCAT("%", pattern, "%")', [$descrizione])->first();
        return $rule ? $rule->category_id : 1;
    }

    public static function setCategoriesFromCsv($descrizione)
    {
        $rules = ImportRule::all();
        $categoria = 1; // Default category

        foreach ($rules as $rule) {
            if (preg_match("/$rule->pattern/i", $descrizione)) {
                $categoria = $rule->category_id;
                break;
            }
        }

        return $categoria;
    }




    // Ritorna gli anni presenti nei movimenti
    public static function getYearsFromMovimenti()
    {
        if (env('DB_CONNECTION')!='sqlite') {
            return self::selectRaw('DISTINCT YEAR(mov_data) as anno')
            ->orderBy('anno', 'desc')
            ->get();
        } else
        {
        return self::selectRaw("strftime('%Y', mov_data) as anno")
        ->distinct()
        ->orderBy('anno', 'desc')
        ->get();
        }
    }


    private static function dateFormat($type,$string)
    {
        // $string=(string)$string;
        if($type)
        {
           // $string=$string->format('Y-m-d');
            list($year,$month,$day) = explode('-',$string);
            return $day.'/'.$month.'/'.$year;
        } else {
           // $string=$string->format('d/m/Y');
            list($day,$month,$year) =explode('/',$string);
            return $year.'-'.$month.'-'.$day;
        }
    }

    // Ritorna la somma delle entrate per un anno specifico
    public static function getEntrate($year)
    {
        return self::whereYear('mov_data', $year)
        ->sum('mov_importo_avere');
    }

    // Ritorna la somma delle uscite per un anno specifico
    public static function getUscite($year)
    {
        return self::whereYear('mov_data', $year)
        ->sum('mov_importo_dare');
    }

    public static function cleanImporto($importo){
        // Rimuove i punti e sostituisce la virgola con un punto
        $importo = str_replace('.', '', $importo);
        $importo = str_replace(',', '.', $importo);
        $importo = str_replace('-', '', $importo);
        $importo = str_replace('+', '', $importo);
        return $importo;
    }

    public static function getDocumentiByMovimento($id)
    {
        $documenti = \App\Models\GenDoc::where('entity_id','=',$id)->count();
        return $documenti;
    }

}
