<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class IDVE_CSS_Generator {

    private $rules = array();

    public function generate( $tree ) {
        $this->rules = array();

        if ( ! isset( $tree['sections'] ) || ! is_array( $tree['sections'] ) ) {
            return '';
        }

        foreach ( $tree['sections'] as $section ) {
            $this->process_section( $section );
        }

        if ( empty( $this->rules ) ) {
            return '';
        }

        $css = "/* IDVE Generated Styles */\n";
        foreach ( $this->rules as $selector => $props ) {
            if ( empty( $props ) ) {
                continue;
            }
            $css .= $selector . " {\n";
            foreach ( $props as $prop => $value ) {
                if ( null === $value || '' === $value ) {
                    continue;
                }
                $css .= '    ' . $prop . ': ' . $value . ";\n";
            }
            $css .= "}\n";
        }
        return $css;
    }

    private function process_section( $section ) {
        $settings = isset( $section['settings'] ) ? $section['settings'] : array();
        $id       = isset( $section['id'] ) ? $section['id'] : '';

        if ( $id ) {
            $props = array();
            if ( ! empty( $settings['backgroundColor'] ) ) {
                $props['background-color'] = $this->sanitize_color( $settings['backgroundColor'] );
            }
            $this->apply_background_image( $props, $settings );
            $padding = $this->format_spacing( isset( $settings['padding'] ) ? $settings['padding'] : null );
            if ( $padding ) {
                $props['padding'] = $padding;
            }
            $margin = $this->format_spacing( isset( $settings['margin'] ) ? $settings['margin'] : null );
            if ( $margin ) {
                $props['margin'] = $margin;
            }

            $stretch = isset( $settings['stretch'] ) ? $settings['stretch'] : 'default';
            if ( 'default' !== $stretch ) {
                $props['width']        = '100vw';
                $props['margin-left']  = 'calc(-50vw + 50%)';
                $props['margin-right'] = '0';
            }

            $this->apply_border( $props, $settings );
            if ( ! empty( $props ) ) {
                $this->rules[ '[data-idve-id="' . $id . '"]' ] = $props;
            }

            // Inner container for stretch-bg mode.
            if ( 'full-bg' === $stretch ) {
                $inner_props = array(
                    'max-width'    => ! empty( $settings['contentMaxWidth'] ) ? esc_attr( $settings['contentMaxWidth'] ) : '1200px',
                    'margin-left'  => 'auto',
                    'margin-right' => 'auto',
                );
                $this->rules[ '[data-idve-id="' . $id . '"] > .idve-section-inner' ] = $inner_props;
            }
        }

        if ( isset( $section['rows'] ) && is_array( $section['rows'] ) ) {
            foreach ( $section['rows'] as $row ) {
                $this->process_row( $row );
            }
        }
    }

    private function process_row( $row ) {
        $settings = isset( $row['settings'] ) ? $row['settings'] : array();
        $id       = isset( $row['id'] ) ? $row['id'] : '';

        if ( $id ) {
            $props = array();
            if ( ! empty( $settings['backgroundColor'] ) ) {
                $props['background-color'] = $this->sanitize_color( $settings['backgroundColor'] );
            }
            $this->apply_background_image( $props, $settings );
            $padding = $this->format_spacing( isset( $settings['padding'] ) ? $settings['padding'] : null );
            if ( $padding ) {
                $props['padding'] = $padding;
            }
            $margin = $this->format_spacing( isset( $settings['margin'] ) ? $settings['margin'] : null );
            if ( $margin ) {
                $props['margin'] = $margin;
            }
            if ( ! empty( $settings['equalHeight'] ) ) {
                $props['display']     = 'flex';
                $props['flex-wrap']   = 'wrap';
                $props['align-items'] = 'stretch';
            }
            if ( ! empty( $settings['gap'] ) ) {
                $props['gap'] = esc_attr( $settings['gap'] );
            }
            $this->apply_border( $props, $settings );
            if ( ! empty( $props ) ) {
                $this->rules[ '[data-idve-id="' . $id . '"]' ] = $props;
            }
        }

        $equal_height = ! empty( $settings['equalHeight'] );
        $gap          = ! empty( $settings['gap'] ) ? $settings['gap'] : '';
        $col_count    = isset( $row['columns'] ) ? count( $row['columns'] ) : 0;

        if ( isset( $row['columns'] ) && is_array( $row['columns'] ) ) {
            foreach ( $row['columns'] as $col ) {
                $this->process_column( $col, $equal_height, $gap, $col_count );
            }
        }
    }

    private function process_column( $col, $equal_height = false, $gap = '', $col_count = 0 ) {
        $settings = isset( $col['settings'] ) ? $col['settings'] : array();
        $id       = isset( $col['id'] ) ? $col['id'] : '';

        if ( $id ) {
            $props = array();
            $padding = $this->format_spacing( isset( $settings['padding'] ) ? $settings['padding'] : null );
            if ( $padding ) {
                $props['padding'] = $padding;
            }
            $margin = $this->format_spacing( isset( $settings['margin'] ) ? $settings['margin'] : null );
            if ( $margin ) {
                $props['margin'] = $margin;
            }
            if ( ! empty( $settings['backgroundColor'] ) ) {
                $props['background-color'] = $this->sanitize_color( $settings['backgroundColor'] );
            }
            $this->apply_background_image( $props, $settings );
            if ( $gap && $col_count > 1 ) {
                $col_width = isset( $col['width'] ) ? $col['width'] : '1/1';
                $width_map = array(
                    '1/1' => 100, '1/2' => 50, '1/3' => 33.333, '2/3' => 66.667,
                    '1/4' => 25, '3/4' => 75, '1/5' => 20, '2/5' => 40, '3/5' => 60, '4/5' => 80,
                );
                $pct      = isset( $width_map[ $col_width ] ) ? $width_map[ $col_width ] : 100;
                $gaps     = $col_count - 1;
                $adjusted = 'calc(' . $pct . '% - ' . $gaps . ' * ' . esc_attr( $gap ) . ' / ' . $col_count . ')';
                $props['flex-basis'] = $adjusted;
                $props['max-width']  = $adjusted;
            }
            if ( $equal_height ) {
                $props['display']        = 'flex';
                $props['flex-direction'] = 'column';
                if ( ! empty( $settings['verticalAlign'] ) && 'top' !== $settings['verticalAlign'] ) {
                    $map = array( 'center' => 'center', 'bottom' => 'flex-end' );
                    if ( isset( $map[ $settings['verticalAlign'] ] ) ) {
                        $props['justify-content'] = $map[ $settings['verticalAlign'] ];
                    }
                }
            } else {
                if ( ! empty( $settings['verticalAlign'] ) && 'top' !== $settings['verticalAlign'] ) {
                    $map = array( 'center' => 'center', 'bottom' => 'flex-end' );
                    if ( isset( $map[ $settings['verticalAlign'] ] ) ) {
                        $props['align-self'] = $map[ $settings['verticalAlign'] ];
                    }
                }
            }
            $this->apply_border( $props, $settings );
            if ( ! empty( $props ) ) {
                $this->rules[ '[data-idve-id="' . $id . '"]' ] = $props;
            }
        }

        if ( isset( $col['blocks'] ) && is_array( $col['blocks'] ) ) {
            foreach ( $col['blocks'] as $block ) {
                $this->process_block( $block );
            }
        }
    }

    private function process_block( $block ) {
        $type     = isset( $block['type'] ) ? $block['type'] : '';
        $data     = isset( $block['data'] ) ? $block['data'] : array();
        $settings = isset( $block['settings'] ) ? $block['settings'] : array();
        $id       = isset( $block['id'] ) ? $block['id'] : '';

        if ( ! $id ) {
            return;
        }

        $props = array();

        $margin = $this->format_spacing( isset( $settings['margin'] ) ? $settings['margin'] : null );
        if ( $margin ) {
            $props['margin'] = $margin;
        }
        $padding = $this->format_spacing( isset( $settings['padding'] ) ? $settings['padding'] : null );
        if ( $padding ) {
            $props['padding'] = $padding;
        }
        if ( ! empty( $settings['backgroundColor'] ) ) {
            $props['background-color'] = $this->sanitize_color( $settings['backgroundColor'] );
        }
        $this->apply_background_image( $props, $settings );
        $this->apply_border( $props, $settings );

        $visible = isset( $settings['visible'] ) ? $settings['visible'] : true;
        if ( ! $visible ) {
            $props['display'] = 'none';
        }

        // Block-type specific styles
        switch ( $type ) {
            case 'text':
                if ( ! empty( $data['alignment'] ) ) {
                    $props['text-align'] = sanitize_key( $data['alignment'] );
                }
                if ( ! empty( $data['textColor'] ) ) {
                    $props['color'] = $this->sanitize_color( $data['textColor'] );
                }
                if ( ! empty( $data['fontSize'] ) ) {
                    $props['font-size'] = esc_attr( $data['fontSize'] );
                }
                break;

            case 'heading':
                if ( ! empty( $data['alignment'] ) ) {
                    $props['text-align'] = sanitize_key( $data['alignment'] );
                }
                if ( ! empty( $data['color'] ) ) {
                    $props['color'] = $this->sanitize_color( $data['color'] );
                }
                if ( ! empty( $data['fontSize'] ) ) {
                    $props['font-size'] = esc_attr( $data['fontSize'] );
                }
                break;

            case 'image':
                if ( ! empty( $data['alignment'] ) ) {
                    $props['text-align'] = sanitize_key( $data['alignment'] );
                }
                break;

            case 'button':
                if ( ! empty( $data['alignment'] ) ) {
                    $props['text-align'] = sanitize_key( $data['alignment'] );
                }
                break;

            case 'spacer':
                $height = isset( $data['height'] ) ? absint( $data['height'] ) : 40;
                $props['height'] = $height . 'px';
                break;

            case 'divider':
                $thickness = isset( $data['thickness'] ) ? absint( $data['thickness'] ) : 2;
                $div_color = isset( $data['color'] ) && ! empty( $data['color'] ) ? $this->sanitize_color( $data['color'] ) : '#cccccc';
                $props['border-width']    = '0';
                $props['height']          = $thickness . 'px';
                $props['background-color'] = $div_color;
                $props['color']           = $div_color;
                if ( ! empty( $data['width'] ) ) {
                    $props['width'] = esc_attr( $data['width'] );
                }
                $div_align = isset( $data['alignment'] ) ? $data['alignment'] : 'center';
                if ( 'left' === $div_align ) {
                    $props['margin'] = '0 auto 0 0';
                } elseif ( 'right' === $div_align ) {
                    $props['margin'] = '0 0 0 auto';
                } else {
                    $props['margin'] = '0 auto';
                }
                break;

            case 'group':
                if ( ! empty( $data['minHeight'] ) ) {
                    $props['min-height'] = esc_attr( $data['minHeight'] );
                }
                if ( ! empty( $settings['verticalAlign'] ) && 'top' !== $settings['verticalAlign'] ) {
                    $props['display']        = 'flex';
                    $props['flex-direction'] = 'column';
                    $map = array( 'center' => 'center', 'bottom' => 'flex-end' );
                    if ( isset( $map[ $settings['verticalAlign'] ] ) ) {
                        $props['justify-content'] = $map[ $settings['verticalAlign'] ];
                    }
                }
                break;
        }

        if ( ! empty( $props ) ) {
            if ( 'button' === $type || 'image' === $type ) {
                // For buttons and images, only alignment + visibility go on the wrapper
                $wrapper_props = array();
                if ( isset( $props['text-align'] ) ) {
                    $wrapper_props['text-align'] = $props['text-align'];
                    unset( $props['text-align'] );
                }
                if ( isset( $props['display'] ) ) {
                    $wrapper_props['display'] = $props['display'];
                    unset( $props['display'] );
                }
                if ( ! empty( $wrapper_props ) ) {
                    $this->rules[ '[data-idve-id="' . $id . '"]' ] = $wrapper_props;
                }
                // Remaining props (margin, padding, border, bg) move to child element
            } else {
                $this->rules[ '[data-idve-id="' . $id . '"]' ] = $props;
            }
        }

        // Child-element styles
        if ( 'image' === $type ) {
            $img_props = array();
            if ( ! empty( $data['maxWidth'] ) ) {
                $img_props['max-width'] = esc_attr( $data['maxWidth'] );
            }
            // Merge settings-level styles (moved from wrapper) onto the img
            $img_props = array_merge( $props, $img_props );
            if ( ! empty( $img_props ) ) {
                $this->rules[ '[data-idve-id="' . $id . '"] img' ] = $img_props;
            }
        }

        if ( 'button' === $type ) {
            $btn_props = array();
            if ( ! empty( $data['backgroundColor'] ) ) {
                $btn_props['background-color'] = $this->sanitize_color( $data['backgroundColor'] );
            }
            if ( ! empty( $data['textColor'] ) ) {
                $btn_props['color'] = $this->sanitize_color( $data['textColor'] );
            }
            // Merge settings-level styles (moved from wrapper) onto the <a>
            $btn_props = array_merge( $props, $btn_props );
            if ( ! empty( $btn_props ) ) {
                $this->rules[ '[data-idve-id="' . $id . '"] .idve-button' ] = $btn_props;
            }
        }

        // Recursive children for group blocks
        if ( 'group' === $type && ! empty( $block['blocks'] ) ) {
            foreach ( $block['blocks'] as $child ) {
                $this->process_block( $child );
            }
        }
    }

    private function sanitize_color( $color ) {
        if ( empty( $color ) || 'transparent' === $color ) {
            return $color ?: '';
        }
        $hex = sanitize_hex_color( $color );
        if ( $hex ) {
            return $hex;
        }
        if ( preg_match( '/^rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(,\s*(0|1|0?\.\d+))?\s*\)$/', $color ) ) {
            return $color;
        }
        return '';
    }

    private function apply_background_image( &$props, $settings ) {
        if ( empty( $settings['backgroundImage'] ) ) {
            return;
        }
        $props['background-image']    = 'url(' . esc_url( $settings['backgroundImage'] ) . ')';
        $props['background-size']     = ! empty( $settings['backgroundSize'] ) ? esc_attr( $settings['backgroundSize'] ) : 'cover';
        $props['background-position'] = ! empty( $settings['backgroundPosition'] ) ? esc_attr( $settings['backgroundPosition'] ) : 'center';
        $props['background-repeat']   = ! empty( $settings['backgroundRepeat'] ) ? esc_attr( $settings['backgroundRepeat'] ) : 'no-repeat';
    }

    private function apply_border( &$props, $settings ) {
        if ( empty( $settings['border'] ) || ! is_array( $settings['border'] ) ) {
            return;
        }
        $border = $settings['border'];
        $color  = ! empty( $border['color'] ) ? $this->sanitize_color( $border['color'] ) : '#000000';
        $style  = ! empty( $border['style'] ) ? sanitize_key( $border['style'] ) : 'solid';

        if ( ! empty( $border['width'] ) && is_array( $border['width'] ) ) {
            $sides = array( 'top', 'right', 'bottom', 'left' );
            foreach ( $sides as $side ) {
                $w = isset( $border['width'][ $side ] ) ? absint( $border['width'][ $side ] ) : 0;
                if ( $w > 0 && $color ) {
                    $props[ 'border-' . $side ] = $w . 'px ' . $style . ' ' . $color;
                }
            }
        }

        if ( ! empty( $border['radius'] ) && is_array( $border['radius'] ) ) {
            $tl = isset( $border['radius']['topLeft'] ) ? absint( $border['radius']['topLeft'] ) : 0;
            $tr = isset( $border['radius']['topRight'] ) ? absint( $border['radius']['topRight'] ) : 0;
            $br = isset( $border['radius']['bottomRight'] ) ? absint( $border['radius']['bottomRight'] ) : 0;
            $bl = isset( $border['radius']['bottomLeft'] ) ? absint( $border['radius']['bottomLeft'] ) : 0;
            if ( $tl || $tr || $br || $bl ) {
                $props['border-radius'] = $tl . 'px ' . $tr . 'px ' . $br . 'px ' . $bl . 'px';
            }
        }
    }

    private function format_spacing( $spacing ) {
        if ( empty( $spacing ) ) {
            return '';
        }
        if ( is_string( $spacing ) ) {
            $spacing = trim( $spacing );
            return ! empty( $spacing ) && '0' !== $spacing ? $spacing : '';
        }
        if ( is_array( $spacing ) ) {
            $top    = isset( $spacing['top'] ) ? intval( $spacing['top'] ) : 0;
            $right  = isset( $spacing['right'] ) ? intval( $spacing['right'] ) : 0;
            $bottom = isset( $spacing['bottom'] ) ? intval( $spacing['bottom'] ) : 0;
            $left   = isset( $spacing['left'] ) ? intval( $spacing['left'] ) : 0;

            if ( 0 === $top && 0 === $right && 0 === $bottom && 0 === $left ) {
                return '';
            }
            return $top . 'px ' . $right . 'px ' . $bottom . 'px ' . $left . 'px';
        }
        return '';
    }
}
