<?php
/**
 * OVP-Sponsorizare
 *
 * @package   OVPSPO_Sponsorizare
 * @author    Ovidiu Pantiru - OVP-Digital
 * @copyright 2024 Ovidiu Pantiru
 * @license   GPL-2.0+
 * @link      https://ovidiupantiru.ro
 */

if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Formular 230 ANAF oficial - OPANAF 103/2025 Anexa 2
 * Metoda: importa formularul ANAF ca imagine si suprapune textul
 * Coordonate exacte extrase din campurile PDF-ului oficial
 */
class OVPSPO_PDF_ANAF {

    public static function generate( $data, $id ) {
        if ( ! self::load_tcpdf() ) {
            return '';
        }

        $org_nume = OVPSPO_Settings::get( 'org_nume', '' );
        $org_cif  = OVPSPO_Settings::get( 'org_cif', '' );
        $org_iban = OVPSPO_Settings::get( 'org_iban', '' );
        $an       = str_pad( (string) OVPSPO_Settings::get( 'an_fiscal', gmdate('Y') - 1 ), 4, '0', STR_PAD_LEFT );

        $pdf = new OVPSPO_TCPDF( 'P', 'mm', 'A4', true, 'UTF-8', false );
        $pdf->SetCreator( 'Formular 230 Plugin' );
        $pdf->SetTitle( 'Formular 230 ANAF – ' . $data['nume'] . ' ' . $data['prenume'] );
        $pdf->SetMargins( 0, 0, 0 );
        $pdf->SetAutoPageBreak( false );
        $pdf->setPrintHeader( false );
        $pdf->setPrintFooter( false );
        $pdf->AddPage();

        // ── Fundalul: formularul ANAF oficial ca imagine ──
        $anaf_img = self::get_anaf_background();
        if ( $anaf_img ) {
            $pdf->Image( $anaf_img['path'], 0, 0, 210, 297, $anaf_img['type'] );
            if ( $anaf_img['temp'] ) wp_delete_file( $anaf_img['path'] );
        }

        $pdf->SetTextColor( 0, 0, 0 );

        // ── ANUL: 4 casute la x=105.91 y=35.61 w=25.31/4 h=6.91 ──
        $bw = 25.31 / 4;
        for ( $i = 0; $i < 4; $i++ ) {
            self::tc( $pdf, 105.91 + $i * $bw, 35.61, $bw, 6.91, $an[$i], 9, true );
        }

        // ── SECTIUNEA I ──
        self::tl( $pdf, 21.57,  56.74, 68.51, 5.09, $data['nume'], 8 );
        self::tc( $pdf, 103.05, 56.74,  8.98, 5.09, $data['initiala'], 8 );

        // CNP - 13 casute in campul x=116.44 y=59.53 w=84.76 h=5.75
        $cnp = str_pad( $data['cnp'], 13, ' ' );
        $cw  = 84.76 / 13;
        for ( $i = 0; $i < 13; $i++ ) {
            self::tc( $pdf, 116.44 + $i * $cw, 59.53, $cw, 5.75, trim( $cnp[$i] ?? '' ), 8, true );
        }

        self::tl( $pdf, 21.59,  64.59, 90.44, 5.09, $data['prenume'], 8 );
        self::tl( $pdf, 127.20, 68.32, 73.37, 5.33, $data['email'], 7 );
        self::tl( $pdf, 21.59,  72.49, 66.47, 5.09, $data['strada'], 8 );
        self::tc( $pdf, 100.68, 72.50, 11.38, 5.09, $data['nr'], 8 );
        self::tl( $pdf, 127.38, 77.85, 65.06, 5.31, $data['telefon'], 8 );
        self::tc( $pdf, 15.58,  80.44, 11.06, 5.09, $data['bloc'], 8 );
        self::tc( $pdf, 36.81,  80.44,  6.43, 5.09, $data['scara'], 8 );
        self::tc( $pdf, 50.86,  80.44,  7.12, 5.09, $data['etaj'], 8 );
        self::tc( $pdf, 64.33,  80.45,  6.49, 5.09, $data['apart'], 8 );
        self::tc( $pdf, 88.88,  80.44, 23.18, 5.09, $data['judet'], 7.5 );
        self::tl( $pdf, 22.89,  88.39, 52.01, 4.93, $data['localitate'], 8 );
        self::tc( $pdf, 91.97,  88.47, 20.09, 4.87, $data['cod_postal'], 8 );

        // ── SECTIUNEA II ──
        // X la "2. Sustinerea" (x=76.43 y=139.25 w=4.59 h=4.59)
        self::tc( $pdf, 76.43, 139.25, 4.59, 4.59, 'X', 8, true );

        // Optiune 2 ani (x=113.88 y=146.15 w=4.59 h=4.59)
        if ( $data['perioada'] == 2 ) {
            self::tc( $pdf, 113.88, 146.15, 4.59, 4.59, 'X', 8, true );
        }

        // CIF (x=84.26 y=153.28 w=40.43 h=4.76)
        self::tl( $pdf, 84.26, 153.28, 40.43, 4.76, $org_cif, 8 );

        // Denumire (x=62.39 y=160.74 w=137.80 h=5.11)
        self::tl( $pdf, 62.39, 160.74, 137.80, 5.11, $org_nume, 8 );

        // IBAN (x=35.22 y=168.54 w=104.75 h=5.11)
        self::tl( $pdf, 35.22, 168.54, 104.75, 5.11, $org_iban, 8 );

        // Procent 3,5 (x=41.99 y=176.48 w=27.87 h=5.11)
        self::tc( $pdf, 41.99, 176.48, 27.87, 5.11, '3,5', 9, true );

        // GDPR bifa (x=9.76 y=184.31 w=5.29 h=5.29)
        if ( $data['gdpr'] ) {
            self::tc( $pdf, 9.76, 184.31, 5.29, 5.29, 'X', 8, true );
        }

        // ── SECTIUNEA III: Date de identificare a împuternicitului ──
        $imp_nume     = OVPSPO_Settings::get( 'org_nume', '' ); // Denumirea organizatiei, nu reprezentantul
        $imp_cif      = OVPSPO_Settings::get( 'org_cif', '' );
        $imp_strada   = OVPSPO_Settings::get( 'org_strada', '' );
        $imp_judet    = OVPSPO_Settings::get( 'org_judet', '' );
        $imp_sector   = OVPSPO_Settings::get( 'org_sector', '' );
        $imp_localit  = OVPSPO_Settings::get( 'org_localitate', '' );
        $imp_postal   = OVPSPO_Settings::get( 'org_cod_postal', '' );
        $imp_telefon  = OVPSPO_Settings::get( 'org_telefon', '' );
        $imp_fax      = OVPSPO_Settings::get( 'org_fax', '' );
        $imp_email    = OVPSPO_Settings::get( 'org_email_public', '' );
        $imp_judet_s  = $imp_sector ? $imp_judet . ' S' . $imp_sector : $imp_judet;

        // Nume/Denumire org (x=45.10 y=202.94 w=90.26 h=5.25)
        self::tl( $pdf, 45.10, 202.94, 90.26, 5.25, $imp_nume, 8 );

        // CIF org - rect alb DOAR peste casute (sub label), nu peste label
        if ( ! empty( $imp_cif ) ) {
            $pdf->SetFillColor( 255, 255, 255 );
            $pdf->Rect( 136.50, 204.20, 65.00, 4.80, 'F' ); // acoperire casute, sub label
            self::tc( $pdf, 136.50, 204.20, 65.00, 4.80, $imp_cif, 8 );
        }

        // Strada (x=19.31 y=210.65 w=90.89 h=6.26)
        self::tl( $pdf, 19.31, 210.65, 90.89, 6.26, $imp_strada, 8 );

        // Judet/Sector (x=24.64 y=219.72 w=40.00 h=5.77)
        self::tl( $pdf, 24.64, 219.72, 40.00, 5.77, $imp_judet_s, 7.5 );

        // Localitate (x=81.28 y=219.88 w=54.39 h=5.26)
        self::tl( $pdf, 81.28, 219.88, 54.39, 5.26, $imp_localit, 8 );

        // Cod postal (x=153.95 y=219.50 w=46.63 h=5.70)
        self::tl( $pdf, 153.95, 219.50, 46.63, 5.70, $imp_postal, 8 );

        // Telefon (x=18.63 y=228.28 w=45.60 h=4.96)
        self::tl( $pdf, 18.63, 228.28, 45.60, 4.96, $imp_telefon, 8 );

        // Fax (x=74.09 y=228.28 w=49.43 h=4.99)
        self::tl( $pdf, 74.09, 228.28, 49.43, 4.99, $imp_fax, 8 );

        // Email (x=136.07 y=228.28 w=64.40 h=4.97)
        self::tl( $pdf, 136.07, 228.28, 64.40, 4.97, $imp_email, 7.5 );

        // ── SEMNATURA (x=48.61 y=256.36 w=47.32 h=5.32) ──
        if ( ! empty( $data['signature'] ) && strpos( $data['signature'], 'data:image' ) === 0 ) {
            $tmp = self::sig_to_file( $data['signature'] );
            if ( $tmp ) {
                $pdf->Image( $tmp, 48.61, 256.36, 47.32, 5.32, '', '', '', false, 150 );
                wp_delete_file( $tmp );
            }
        }

        // ── Salvare ──
        $upload_dir = wp_upload_dir();
        $dir = $upload_dir['basedir'] . '/formular230/';
        if ( ! file_exists($dir) ) wp_mkdir_p( $dir );
        $slug     = self::slugify( $data['nume'] . '_' . $data['prenume'] );
        $filepath = $dir . 'Formular_ANAF_Oficial_' . $slug . '_' . $id . '.pdf';
        $pdf->Output( $filepath, 'F' );
        return file_exists( $filepath ) ? $filepath : '';
    }

    /**
     * Obtine fundalul - formularul ANAF ca imagine PNG
     * Daca nu exista imaginea PNG, o genereaza din PDF
     */
    private static function get_anaf_background() {
        // Cauta imaginea PNG pre-generata
        $upload_dir = wp_upload_dir();
        $png_path   = trailingslashit( $upload_dir['basedir'] ) . 'ovp-sponsorizare/formular230-anaf-bg.png';
        if ( ! file_exists( dirname( $png_path ) ) ) {
            wp_mkdir_p( dirname( $png_path ) );
        }
        if ( file_exists( $png_path ) ) {
            return array( 'path' => $png_path, 'type' => 'PNG', 'temp' => false );
        }

        // Cauta PDF-ul original
        $pdf_path = OVPSPO_PATH . 'assets/formular230-anaf-oficial.pdf';
        if ( ! file_exists( $pdf_path ) ) {
            return null;
        }

        // Incearca sa converteasca PDF → PNG cu Imagick
        if ( class_exists('Imagick') ) {
            try {
                $im = new Imagick();
                $im->setResolution( 150, 150 );
                $im->readImage( $pdf_path . '[0]' );
                $im->setImageFormat('png');
                $im->writeImage( $png_path );
                $im->clear();
                if ( file_exists( $png_path ) ) {
                    return array( 'path' => $png_path, 'type' => 'PNG', 'temp' => false );
                }
            } catch ( Exception $e ) {
            }
        }

        // Incearca cu GhostScript
        $tmp_png = sys_get_temp_dir() . '/bf230_anaf_bg.png';
        $gs_cmd  = 'gs -dNOPAUSE -dBATCH -sDEVICE=png16m -r150 -dFirstPage=1 -dLastPage=1 '
                 . '-sOutputFile=' . escapeshellarg($tmp_png) . ' '
                 . escapeshellarg($pdf_path) . ' 2>/dev/null';
        exec( $gs_cmd ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.system_calls_exec
        if ( file_exists( $tmp_png ) ) {
            copy( $tmp_png, $png_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.copy
            wp_delete_file( $tmp_png );
            return array( 'path' => $png_path, 'type' => 'PNG', 'temp' => false );
        }

        // Ultimul fallback: foloseste direct PDF-ul (OVPSPO_TCPDF poate incarca PDF ca imagine pe unele servere)
        // In caz de esec, returnam PDF-ul direct
        return array( 'path' => $pdf_path, 'type' => 'PDF', 'temp' => false );
    }

    // ── Text aliniat stanga ──
    private static function tl( $pdf, $x, $y, $w, $h, $text, $size = 8 ) {
        if ( ! strlen( trim( (string)$text ) ) ) return;
        $pdf->SetFont( 'dejavusans', '', $size );
        $pdf->SetXY( $x + 0.8, $y + ( $h - $size * 0.3528 ) / 2 );
        $pdf->Cell( $w - 1, $size * 0.3528 + 1, (string)$text, 0, 0, 'L' );
    }

    // ── Text centrat ──
    private static function tc( $pdf, $x, $y, $w, $h, $text, $size = 8, $bold = false ) {
        if ( ! strlen( trim( (string)$text ) ) ) return;
        $pdf->SetFont( 'dejavusans', $bold ? 'B' : '', $size );
        $pdf->SetXY( $x, $y + ( $h - $size * 0.3528 ) / 2 );
        $pdf->Cell( $w, $size * 0.3528 + 1, (string)$text, 0, 0, 'C' );
    }

    private static function sig_to_file( $uri ) {
        $parts = explode( ',', $uri, 2 );
        if ( count($parts) < 2 ) return false;
        $img = base64_decode( $parts[1] );
        if ( ! $img ) return false;
        $tmp = wp_tempnam( 'ovpspo_sig_' ) . '.png'; // phpcs:ignore WordPress.WP.AlternativeFunctions
        file_put_contents( $tmp, $img ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
        return $tmp;
    }

    private static function slugify( $str ) {
        $str = iconv( 'UTF-8', 'ASCII//TRANSLIT', $str );
        $str = preg_replace( '/[^A-Za-z0-9_]/', '_', $str );
        return trim( $str, '_' );
    }

    private static function load_tcpdf() {
        if ( class_exists( 'OVPSPO_TCPDF' ) ) return true;

        $paths = array(
            // OVPSPO_TCPDF bundled in plugin (prioritate maxima)
            defined('OVPSPO_PATH') ? OVPSPO_PATH . 'lib/tcpdf/tcpdf.php' : '',
            defined('OVPSPO_PATH')    ? OVPSPO_PATH    . 'lib/tcpdf/tcpdf.php' : '',
            defined('OVPSPO_PATH')  ? OVPSPO_PATH  . 'lib/tcpdf/tcpdf.php' : '',
            // Instalat extern ca fallback
            defined('OVPSPO_TCPDF_PATH') ? OVPSPO_TCPDF_PATH : '',
            defined('OVPSPO_TCPDF_PATH')  ? OVPSPO_TCPDF_PATH  : '',
        );

        foreach ( $paths as $path ) {
            if ( $path && file_exists( $path ) ) {
                require_once $path;
                // Creeaza alias daca TCPDF e incarcat ca 'TCPDF' (bundled) in loc de 'OVPSPO_TCPDF'
                if ( class_exists( 'TCPDF' ) && ! class_exists( 'OVPSPO_TCPDF' ) ) {
                    class_alias( 'TCPDF', 'OVPSPO_TCPDF' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals
                }
                if ( class_exists( 'OVPSPO_TCPDF' ) ) return true;
            }
        }
        return false;
    }

    /**
     * Verifica daca OVPSPO_TCPDF e disponibil, altfel intoarce false
     * pentru a folosi fallback-ul
     */
    private static function has_tcpdf() {
        return self::load_tcpdf();
    }
}
