<?php

/**
 * @package QuickStockForWooCommerce
 * @license GPL-2.0-or-later (https://www.gnu.org/licenses/gpl-2.0.html)
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
/**
 * Etiketten-Vorlagen (vom Admin verwaltet, gelten für alle Benutzer).
 *
 * Eine Vorlage beschreibt eine druckbare Etikette:
 *   - name                      Anzeigename
 *   - width_mm / height_mm      Etikettenmaße in mm
 *   - dpi                       Render-Auflösung (Canvas → PNG)
 *   - elements[<typ>]           pro Element: enabled, x, y, font, bold, align …
 *
 * Speicherung:
 *   Option qsfw_label_templates = array( id => array(...) )
 *   Option qsfw_label_default   = id der Standard-Vorlage
 */
class QSFW_Label_Templates {
    const OPTION = 'qsfw_label_templates';

    const DEFAULT = 'qsfw_label_default';

    /** Element-Typen + erlaubte Zusatzfelder je Typ. */
    public static function element_types() {
        $types = array(
            'price'   => __( 'Price', 'quickstock-for-woocommerce' ),
            'title'   => __( 'Product name', 'quickstock-for-woocommerce' ),
            'barcode' => __( 'Barcode', 'quickstock-for-woocommerce' ),
        );
        return $types;
    }

    /** Gängige Etikettenmaße (Breite × Höhe in mm). */
    public static function size_presets() {
        return array(
            array(
                'w'     => 54,
                'h'     => 17,
                'label' => __( '54 × 17 mm (default / shelf)', 'quickstock-for-woocommerce' ),
            ),
            array(
                'w'     => 38,
                'h'     => 21,
                'label' => '38 × 21 mm',
            ),
            array(
                'w'     => 40,
                'h'     => 24,
                'label' => '40 × 24 mm',
            ),
            array(
                'w'     => 63.5,
                'h'     => 29.6,
                'label' => '63.5 × 29.6 mm',
            ),
            array(
                'w'     => 70,
                'h'     => 37,
                'label' => '70 × 37 mm',
            ),
            array(
                'w'     => 105,
                'h'     => 48,
                'label' => '105 × 48 mm',
            ),
            array(
                'w'     => 105,
                'h'     => 57,
                'label' => '105 × 57 mm',
            ),
            array(
                'w'     => 105,
                'h'     => 74,
                'label' => '105 × 74 mm',
            )
        );
    }

    public static function barcode_formats() {
        return array('CODE128', 'EAN13', 'CODE39');
    }

    public static function aligns() {
        return array('left', 'center', 'right');
    }

    /**
     * Schema eines Elements mit Defaults. Beim Speichern/Lesen werden
     * unbekannte Keys verworfen und fehlende mit diesen Werten ergänzt.
     */
    public static function element_defaults( $type ) {
        $base = array(
            'enabled'       => 0,
            'x'             => 2.0,
            'y'             => 2.0,
            'w'             => 0,
            'h'             => 0,
            'font'          => 2.0,
            'bold'          => 0,
            'strike'        => 0,
            'align'         => 'left',
            'letterspacing' => 0,
        );
        switch ( $type ) {
            case 'price':
                return array_merge( $base, array(
                    'font'   => 3.2,
                    'bold'   => 1,
                    'prefix' => '',
                ) );
            case 'title':
                return array_merge( $base, array(
                    'font'     => 2.0,
                    'maxlines' => 2,
                    'after'    => '',
                    'gap'      => 2.0,
                ) );
            case 'barcode':
                return array_merge( $base, array(
                    'height_mm'   => 5.0,
                    'modulewidth' => 3,
                    'format'      => 'CODE128',
                ) );
        }
        return $base;
    }

    /**
     * Vollständige Vorlage mit allen Defaults (für „Neu" + Normalisierung).
     */
    public static function blank_template() {
        $elements = array();
        foreach ( array_keys( self::element_types() ) as $type ) {
            $elements[$type] = self::element_defaults( $type );
        }
        return array(
            'name'      => '',
            'width_mm'  => 54.0,
            'height_mm' => 17.0,
            'dpi'       => 300,
            'elements'  => $elements,
        );
    }

    /**
     * Standard-Vorlage, die das bisher fest verdrahtete 54×17-Etikett
     * (Preis links, Name rechts daneben, Barcode mittig, Website unten)
     * visuell reproduziert.
     */
    public static function default_template() {
        $t = self::blank_template();
        $t['name'] = __( 'Default 54 × 17', 'quickstock-for-woocommerce' );
        $t['width_mm'] = 54.0;
        $t['height_mm'] = 17.0;
        $t['dpi'] = 300;
        $t['elements']['price'] = array_merge( self::element_defaults( 'price' ), array(
            'enabled' => 1,
            'x'       => 2.8,
            'y'       => 1.5,
            'font'    => 3.2,
            'bold'    => 1,
            'align'   => 'left',
            'prefix'  => '',
        ) );
        $t['elements']['title'] = array_merge( self::element_defaults( 'title' ), array(
            'enabled'  => 1,
            'x'        => 2.8,
            'y'        => 1.8,
            'font'     => 2.0,
            'bold'     => 0,
            'align'    => 'left',
            'maxlines' => 2,
            'after'    => 'price',
            'gap'      => 2.0,
        ) );
        $t['elements']['barcode'] = array_merge( self::element_defaults( 'barcode' ), array(
            'enabled'     => 1,
            'x'           => 2.8,
            'y'           => 6.8,
            'height_mm'   => 5.5,
            'modulewidth' => 3,
            'format'      => 'CODE128',
        ) );
        return $t;
    }

    /* ===================================================================
     * Lesen
     * =================================================================== */
    public static function all() {
        $saved = get_option( self::OPTION, array() );
        if ( !is_array( $saved ) || empty( $saved ) ) {
            return array();
        }
        $out = array();
        foreach ( $saved as $id => $tpl ) {
            $out[$id] = self::normalize( $tpl );
        }
        return $out;
    }

    public static function get( $id ) {
        $all = self::all();
        return ( isset( $all[$id] ) ? $all[$id] : null );
    }

    public static function get_default_id() {
        $id = get_option( self::DEFAULT, '' );
        $all = self::all();
        if ( $id && isset( $all[$id] ) ) {
            return $id;
        }
        // Fallback: erste vorhandene Vorlage
        $keys = array_keys( $all );
        return ( !empty( $keys ) ? $keys[0] : '' );
    }

    public static function get_default() {
        $id = self::get_default_id();
        return ( $id ? self::get( $id ) : null );
    }

    /** Ergänzt fehlende Keys & verwirft Unbekanntes (defensiv gegen Altdaten). */
    public static function normalize( $tpl ) {
        $blank = self::blank_template();
        if ( !is_array( $tpl ) ) {
            return $blank;
        }
        $out = array(
            'name'      => ( isset( $tpl['name'] ) ? (string) $tpl['name'] : '' ),
            'width_mm'  => ( isset( $tpl['width_mm'] ) ? (float) $tpl['width_mm'] : $blank['width_mm'] ),
            'height_mm' => ( isset( $tpl['height_mm'] ) ? (float) $tpl['height_mm'] : $blank['height_mm'] ),
            'dpi'       => ( isset( $tpl['dpi'] ) ? (int) $tpl['dpi'] : $blank['dpi'] ),
            'elements'  => array(),
        );
        if ( $out['width_mm'] <= 0 ) {
            $out['width_mm'] = $blank['width_mm'];
        }
        if ( $out['height_mm'] <= 0 ) {
            $out['height_mm'] = $blank['height_mm'];
        }
        if ( $out['dpi'] < 72 || $out['dpi'] > 1200 ) {
            $out['dpi'] = 300;
        }
        foreach ( array_keys( self::element_types() ) as $type ) {
            $def = self::element_defaults( $type );
            $src = ( isset( $tpl['elements'][$type] ) && is_array( $tpl['elements'][$type] ) ? $tpl['elements'][$type] : array() );
            $el = array();
            foreach ( $def as $k => $dv ) {
                $el[$k] = ( array_key_exists( $k, $src ) ? $src[$k] : $dv );
            }
            $out['elements'][$type] = self::sanitize_element( $type, $el );
        }
        return $out;
    }

    private static function sanitize_element( $type, $el ) {
        $el['enabled'] = ( !empty( $el['enabled'] ) ? 1 : 0 );
        $el['x'] = (float) $el['x'];
        $el['y'] = (float) $el['y'];
        $el['w'] = max( 0, (float) $el['w'] );
        $el['h'] = max( 0, (float) $el['h'] );
        $el['font'] = max( 0.5, (float) $el['font'] );
        $el['bold'] = ( !empty( $el['bold'] ) ? 1 : 0 );
        $el['strike'] = ( !empty( $el['strike'] ) ? 1 : 0 );
        $el['align'] = ( in_array( $el['align'], self::aligns(), true ) ? $el['align'] : 'left' );
        $el['letterspacing'] = max( 0, (float) $el['letterspacing'] );
        if ( $type === 'barcode' ) {
            $el['height_mm'] = max( 1.0, (float) $el['height_mm'] );
            $el['modulewidth'] = min( 8, max( 1, (int) $el['modulewidth'] ) );
            $el['format'] = ( in_array( $el['format'], self::barcode_formats(), true ) ? $el['format'] : 'CODE128' );
        }
        if ( $type === 'title' ) {
            $el['maxlines'] = min( 4, max( 1, (int) $el['maxlines'] ) );
            $el['after'] = ( $el['after'] === 'price' ? 'price' : '' );
            $el['gap'] = (float) $el['gap'];
        }
        if ( $type === 'price' ) {
            // sanitize_text_field() würde Leading/Trailing-Spaces trimmen,
            // was hier unerwünscht ist – der User braucht z.B. "CHF " mit
            // abschließendem Leerzeichen für "CHF 9.90".
            $prefix = wp_check_invalid_utf8( (string) $el['prefix'] );
            $prefix = preg_replace( '/[\\r\\n\\t\\0\\x0B]/', '', $prefix );
            // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- wp_strip_all_tags() trimmt, das Leerzeichen muss aber bleiben (siehe oben)
            $prefix = strip_tags( $prefix );
            $el['prefix'] = $prefix;
        }
        return $el;
    }

    /* ===================================================================
     * Schreiben / Verwalten
     * =================================================================== */
    public static function save( $id, $tpl ) {
        $saved = get_option( self::OPTION, array() );
        if ( !is_array( $saved ) ) {
            $saved = array();
        }
        if ( empty( $id ) ) {
            $id = 'tpl' . substr( md5( uniqid( '', true ) ), 0, 8 );
        }
        $saved[$id] = self::normalize( $tpl );
        update_option( self::OPTION, $saved );
        // Erste Vorlage automatisch zum Standard machen.
        if ( !get_option( self::DEFAULT, '' ) ) {
            update_option( self::DEFAULT, $id );
        }
        return $id;
    }

    public static function delete( $id ) {
        $saved = get_option( self::OPTION, array() );
        if ( is_array( $saved ) && isset( $saved[$id] ) ) {
            unset($saved[$id]);
            update_option( self::OPTION, $saved );
        }
        if ( get_option( self::DEFAULT, '' ) === $id ) {
            $keys = ( is_array( $saved ) ? array_keys( $saved ) : array() );
            update_option( self::DEFAULT, ( !empty( $keys ) ? $keys[0] : '' ) );
        }
    }

    public static function duplicate( $id ) {
        $tpl = self::get( $id );
        if ( !$tpl ) {
            return '';
        }
        $tpl['name'] = trim( $tpl['name'] . ' ' . __( '(Copy)', 'quickstock-for-woocommerce' ) );
        return self::save( '', $tpl );
    }

    public static function set_default( $id ) {
        if ( $id && self::get( $id ) ) {
            update_option( self::DEFAULT, $id );
        }
    }

    /** Legt beim ersten Mal die Standard-Vorlage an (Aktivierung/Migration). */
    public static function maybe_seed_default() {
        $saved = get_option( self::OPTION, array() );
        if ( is_array( $saved ) && !empty( $saved ) ) {
            return;
        }
        $id = self::save( '', self::default_template() );
        update_option( self::DEFAULT, $id );
    }

}
