<?php

namespace Convertforce\Blocks;

use Convertforce\Core\Post;
use Convertforce\Utils\StyleUtils;

class Conversion extends Base
{
    protected static $localize = true;

    public static function get_build_dir_name()
    {
        return 'conversion';
    }

    public static function localize_script($script_handle)
    {
        wp_localize_script($script_handle, 'CONVERTFORCE_CONFIG', [
            'base_url' => CONVERTFORCE_URL,
            'version' => CONVERTFORCE_VERSION,
            // Used by client-side page-view tracking for the `user_viewed_*`
            // conditions. Visitor/user state is evaluated server-side instead.
            'current_post_id' => get_queried_object_id(),
        ]);
    }


    public static function render($attributes, $content)
    {
        if (Post::$is_saving) {
            self::update_meta($attributes);
        }


        if (!isset($attributes['type']) || empty($attributes['type'])) {
            $attributes['type'] = 'initiator';
        }
        $type = esc_attr($attributes['type']);

        $innerClassName = "convertforce-conversion convertforce-conversion-{$type}";

        $display_options = $attributes['displayOptions'] ?? [];
        $entrance_animation = $display_options['entrance_animation'] ?? [];

        $light_box_backdrop = '';
        if ($type === 'light_box') {
            $light_box_backdrop = '<div class="convertforce-conversion-light_box-backdrop"></div>';
        } else if ($type === 'slide_in' && isset($entrance_animation['name'])) {
            $innerClassName .= ' cvf-animation-open__' . esc_attr($entrance_animation['name']);
        }

        $closer = self::get_closer_html($attributes['closer'] ?? []);

        $config = base64_encode(json_encode($attributes));
        $styleResult = self::get_style($attributes);
        $wrapperStyle = is_array($styleResult) ? $styleResult['inline'] : $styleResult;
        $marginClass = is_array($styleResult) ? ($styleResult['margin_class'] ?? '') : '';
        $marginStyleBlock = is_array($styleResult) ? ($styleResult['margin_style_block'] ?? '') : '';

        // TODO: Add a class in save function to avoid this
        // Use deprecated attribute to preserve the old posts
        // https://github.com/WordPress/gutenberg/issues/61833
        $content = substr_replace(ltrim($content), '<div style="display: contents;">', 0, 5);

        $layoutResult = self::get_layout_style($attributes);
        $layoutInline = $layoutResult['inline'];
        $layoutClass = $layoutResult['class'];
        $layoutStyleBlock = $layoutResult['style_block'];
        $layoutClassAttr = $layoutClass ? ' ' . esc_attr($layoutClass) : '';
        $fullStyleBlock = trim($marginStyleBlock . ' ' . $layoutStyleBlock);
        $styleBlockHtml = $fullStyleBlock ? '<style>' . wp_strip_all_tags($fullStyleBlock) . '</style>' : '';
        $marginClassAttr = $marginClass ? ' ' . esc_attr($marginClass) : '';

        $contentWrapperClass = 'convertforce-conversion convertforce-conversion-content-wrapper';
        $contentWrapperStyle = $wrapperStyle;
        $wrapperMarginClassAttr = $marginClassAttr;
        $innerStyle = $layoutInline;
        $innerMarginClassAttr = '';

        if ($type === 'slide_in') {
            $contentWrapperStyle = '';
            $wrapperMarginClassAttr = '';
            $innerMarginClassAttr = $marginClassAttr;
            $innerStyle = trim($wrapperStyle . ' ' . $layoutInline);
        }

        // @codingStandardsIgnoreStart
        $campaign_id = get_the_ID();
        $data = <<<HTML
        <div class="convertforce-conversion-wrapper" style="display: none;" data-type="{$type}" data-campaign-id="{$campaign_id}">
            {$styleBlockHtml}
            {$light_box_backdrop}
            <div class="{$contentWrapperClass}{$wrapperMarginClassAttr}" style="{$contentWrapperStyle}" data-config="{$config}">
                <div class="{$innerClassName}{$layoutClassAttr}{$innerMarginClassAttr}" style="{$innerStyle}">
                    {$content}
                    {$closer}
                </div>
            </div>
        </div>
        HTML;
        // @codingStandardsIgnoreEnd
        return $data;
    }

    private static function get_closer_html($props)
    {
        if (!$props['show_button']) {
            return '';
        }
        $style = self::get_closer_style($props);
        $content = esc_html($props['text'] ?? '');
        if ($props['type'] === 'icon') {
            $content = file_get_contents(CONVERTFORCE_DIR . '/assets/icons/times-bold.svg');
        }
        $aria_label = esc_attr($props['text'] ?? '') ?: esc_attr__('Close', 'convertforce');
        // @codingStandardsIgnoreStart
        return <<<HTML
            <button type="button" class="convertforce-conversion__closer" style="{$style}" aria-label="{$aria_label}">
                {$content}
            </button>
        HTML;
        // @codingStandardsIgnoreEnd
    }


    private static function get_style($attributes)
    {
        $type = $attributes['type'];
        $styleProps = $attributes['style'] ?? [];
        $sizeProps = $attributes['size'] ?? [];
        $positionProps = $attributes['position'] ?? [];
        $bgProps = $styleProps['background'] ?? [];
        $marginProps = $styleProps['margin'] ?? [];
        $isResponsiveMargin = isset($marginProps['desktop']) && is_array($marginProps['desktop']);

        $style = [
            'min-height' => isset($sizeProps['enable_min_height']) && $sizeProps['enable_min_height'] ? $sizeProps['min_height'] ?? null : null,
            'max-width' => $sizeProps['max_width'] ?? null,
            'background-color' => $bgProps['color'] ?? null,
            'background-size' => $bgProps['size'] ?? null,
            'background-position' => "center",
            'background-repeat' => "no-repeat",
            'box-shadow' => StyleUtils::get_box_shadow_string($styleProps['shadow'] ?? null),
        ]
            + (!$isResponsiveMargin ? StyleUtils::get_spacing_style($marginProps, 'margin') : [])
            + StyleUtils::get_border_css($styleProps['border'] ?? [])
            + StyleUtils::get_border_radius_css($styleProps['border_radius'] ?? []);

        $bgImages = [];
        if (isset($bgProps['gradient'])) {
            $bgImages[] = $bgProps['gradient'];
        }
        if (isset($bgProps['image'])) {
            $bgImages[] = "url({$bgProps['image']['url']})";
        }
        if (!empty($bgImages)) {
            $style["background-image"] = implode(', ', $bgImages);
        }

        $isBar = $type === 'bar';

        if ($isBar || $type === 'slide_in') {
            if ($isBar) {
                $style['position'] = [
                    'floating' => 'fixed',
                    'static' => 'static',
                    'sticky' => 'sticky',
                ][$positionProps['behavior'] ?? 'static'];
            } elseif ($type === 'slide_in') {
                $style['position'] = 'fixed';
            }
            $horizontal = $positionProps['horizontal'] ?? 'left';
            $vertical = $positionProps['vertical'] ?? 'top';
            $offsetX = $positionProps['offsetX'] ?? "0px";
            $offsetY = $positionProps['offsetY'] ?? "0px";
            $transformX = '';
            $transformY = '';
            
            if (!$isBar || $positionProps['behavior'] === 'floating') {
                if ($horizontal === 'left') {
                    $style['left'] = $offsetX;
                } else if ($horizontal === 'right') {
                    $style['right'] = $offsetX;
                } else {
                    $style['left'] = '50%';
                    $transformX = "translateX(calc(-50% + {$offsetX}))";
                }
            }

            if ($vertical === 'top') {
                $style['top'] = $offsetY;
            } else if ($vertical === 'bottom') {
                $style['bottom'] = $offsetY;
            } else {
                $style['top'] = '50%';
                $transformY = "translateY(calc(-50% + {$offsetY}))";
            }
            $style['transform'] = "{$transformX} {$transformY}";
        } else {
            $vertical = $positionProps['vertical'] ?? 'top';
            $offsetY = $positionProps['offsetY'] ?? "0px";
            $transformY = '';
            $style['left'] = '50%';
            if ($vertical === 'bottom') {
                $style['bottom'] = $offsetY;
            } else if ($vertical === 'top') {
                $style['top'] = $offsetY;
            } else {
                $style['top'] = '50%';
                $transformY = "translateY(calc(-50% + {$offsetY}))";
            }
            $style['transform'] = "translateX(-50%) {$transformY}";
        }

        if (!$isResponsiveMargin) {
            return StyleUtils::generate_css_string($style);
        }

        $marginClass = 'cvf-margin-' . wp_unique_id();
        $mobileMargin = $marginProps['mobile'] ?? $marginProps['tablet'] ?? $marginProps['desktop'] ?? [];
        $tabletMargin = $marginProps['tablet'] ?? $marginProps['desktop'] ?? [];
        $desktopMargin = $marginProps['desktop'] ?? [];
        $marginBlocks = [
            '.' . esc_attr($marginClass) . ' { ' . StyleUtils::build_css_string(StyleUtils::get_spacing_style($mobileMargin, 'margin')) . ' }',
            '@media (min-width: 600px) { .' . esc_attr($marginClass) . ' { ' . StyleUtils::build_css_string(StyleUtils::get_spacing_style($tabletMargin, 'margin')) . ' } }',
            '@media (min-width: 960px) { .' . esc_attr($marginClass) . ' { ' . StyleUtils::build_css_string(StyleUtils::get_spacing_style($desktopMargin, 'margin')) . ' } }',
        ];
        return [
            'inline' => StyleUtils::generate_css_string($style),
            'margin_class' => $marginClass,
            'margin_style_block' => implode(' ', $marginBlocks),
        ];
    }

    private static function get_layout_style($attributes)
    {
        $sizeProps = $attributes['size'] ?? [];
        $layoutAttr = $attributes['layout'] ?? [];
        $paddingProps = $attributes['style']['padding'] ?? [];
        $isResponsiveLayout = isset($layoutAttr['desktop']) && is_array($layoutAttr['desktop']);
        $isResponsivePadding = isset($paddingProps['desktop']) && is_array($paddingProps['desktop']);

        $minHeight = null;
        if (isset($sizeProps['enable_min_height']) && $sizeProps['enable_min_height']) {
            $minHeight = $sizeProps['min_height'];
        }

        $mobilePadding = $isResponsivePadding
            ? ($paddingProps['mobile'] ?? $paddingProps['tablet'] ?? $paddingProps['desktop'] ?? [])
            : $paddingProps;
        $tabletPadding = $isResponsivePadding ? ($paddingProps['tablet'] ?? $paddingProps['desktop'] ?? []) : [];
        $desktopPadding = $isResponsivePadding ? ($paddingProps['desktop'] ?? []) : [];

        $baseStyle = [
            'min-height' => $minHeight,
            'max-width' => $sizeProps['max_width'] ?? null,
        ];
        if (!$isResponsivePadding) {
            $baseStyle += StyleUtils::get_spacing_style($paddingProps, 'padding');
        } elseif (!$isResponsiveLayout) {
            $baseStyle += StyleUtils::get_spacing_style($mobilePadding, 'padding');
        }

        $mobile = $isResponsiveLayout ? ($layoutAttr['mobile'] ?? $layoutAttr['tablet'] ?? $layoutAttr['desktop']) : $layoutAttr;
        $tablet = $isResponsiveLayout ? ($layoutAttr['tablet'] ?? $layoutAttr['desktop']) : null;
        $desktop = $isResponsiveLayout ? $layoutAttr['desktop'] : null;

        if (!$isResponsiveLayout) {
            $inlineStyle = $baseStyle + self::layout_props_to_css($mobile);
            return [
                'inline' => StyleUtils::generate_css_string($inlineStyle),
                'style_block' => '',
                'class' => '',
            ];
        }

        $layoutClass = 'cvf-layout-' . wp_unique_id();
        $inlineCss = StyleUtils::generate_css_string($baseStyle);
        $mobileCss = self::layout_props_to_css($mobile) + ($isResponsivePadding ? StyleUtils::get_spacing_style($mobilePadding, 'padding') : []);
        $tabletCss = self::layout_props_to_css($tablet) + ($isResponsivePadding ? StyleUtils::get_spacing_style($tabletPadding, 'padding') : []);
        $desktopCss = self::layout_props_to_css($desktop) + ($isResponsivePadding ? StyleUtils::get_spacing_style($desktopPadding, 'padding') : []);
        $blocks = [
            '.' . esc_attr($layoutClass) . ' { ' . StyleUtils::build_css_string($mobileCss) . ' }',
            '@media (min-width: 600px) { .' . esc_attr($layoutClass) . ' { ' . StyleUtils::build_css_string($tabletCss) . ' } }',
            '@media (min-width: 960px) { .' . esc_attr($layoutClass) . ' { ' . StyleUtils::build_css_string($desktopCss) . ' } }',
        ];

        return [
            'inline' => $inlineCss,
            'style_block' => implode(' ', $blocks),
            'class' => $layoutClass,
        ];
    }

    /**
     * @param array<string, mixed> $layoutProps
     * @return array<string, string|null>
     */
    private static function layout_props_to_css($layoutProps)
    {
        if (empty($layoutProps)) {
            $layoutProps = ['type' => 'none'];
        }

        $style = [];
        if (($layoutProps['type'] ?? 'none') !== 'none') {
            $style['gap'] = $layoutProps['gap'] ?? null;
            if (($layoutProps['type'] ?? '') === 'grid') {
                $style['display'] = 'grid';
                if (($layoutProps['item_strategy'] ?? '') === 'size') {
                    $style['grid-template-columns'] = isset($layoutProps['item_size'])
                        ? "repeat(auto-fill, minmax({$layoutProps['item_size']}, 1fr))"
                        : null;
                } else {
                    $style['grid-template-columns'] = isset($layoutProps['item_count'])
                        ? "repeat({$layoutProps['item_count']}, 1fr)"
                        : null;
                }
            } else {
                $style['display'] = 'flex';
                $style['flex-direction'] = $layoutProps['direction'] ?? 'row';
                $style['flex-wrap'] = ($layoutProps['wrap'] ?? false) ? 'wrap' : 'nowrap';
                if (($layoutProps['direction'] ?? 'row') === 'column') {
                    $style['justify-content'] = $layoutProps['align'] ?? 'flex-start';
                    $style['align-items'] = $layoutProps['justify'] ?? 'center';
                } else {
                    $style['justify-content'] = $layoutProps['justify'] ?? 'flex-start';
                    $style['align-items'] = $layoutProps['align'] ?? 'center';
                }
            }
        }
        return $style;
    }

    private static function get_closer_style($props)
    {
        $styleProps = $props['style'] ?? [];
        $borderProps = $props['border'] ?? [];
        $borderRadiusProps = $props['border_radius'] ?? [];
        $paddingProps = $props['padding'] ?? [];

        $color = $styleProps['color'] ?? null;
        $backgroundColor = $styleProps['background_color'] ?? null;
        $backgroundGradient = $styleProps['background_gradient'] ?? null;

        $fontSize = $props['font_size'] ?? null;
        if ($props['type'] === 'icon') {
            $fontSize = $props['icon_size'] ?? null;
        }


        $style = [
            'color' => $color,
            'font-size' => $fontSize,
            'background-color' => $backgroundColor,
            'background-gradient' => $backgroundGradient,
            'box-shadow' => StyleUtils::get_box_shadow_string($styleProps['shadow'] ?? null),
            '--cvf-closer-hover-color' => $styleProps['hover_color'] ?? $color,
            '--cvf-closer-hover-background-color' => $styleProps['hover_background_color'] ?? $backgroundColor,
            '--cvf-closer-hover-background-gradient' => $styleProps['hover_background_gradient'] ?? $backgroundGradient,
        ]
            + StyleUtils::get_spacing_style($paddingProps, 'padding')
            + StyleUtils::get_border_css($borderProps)
            + StyleUtils::get_border_radius_css($borderRadiusProps);


        if (empty($props['is_static'])) {
            $position = $props['position'] ?? [];
            $horizontal = $position['horizontal'] ?? 'left';
            $vertical = $position['vertical'] ?? 'top';
            $offsetX = $position['offsetX'] ?? "0px";
            $offsetY = $position['offsetY'] ?? "0px";
            $transformX = '';
            $transformY = '';
            if ($horizontal === 'left') {
                $style['left'] = $offsetX;
            } else if ($horizontal === 'center') {
                $style['left'] = '50%';
                $transformX = "translateX(calc(-50% + {$offsetX}))";
            } else {
                $style['right'] = $offsetX;
            }
            if ($vertical === 'bottom') {
                $style['bottom'] = $offsetY;
            } else if ($vertical === 'center') {
                $style['top'] = '50%';
                $transformY = "translateY(calc(-50% + {$offsetY}))";
            } else {
                $style['top'] = $offsetY;
            }
            $style['transform'] = "{$transformX} {$transformY}";
            $style['position'] = 'absolute';
        }

        return StyleUtils::generate_css_string($style);
    }

    private static function update_meta($attributes)
    {
        $post_id = get_the_ID();
        $meta = get_post_meta($post_id, Post::META_KEY, true);
        if (!$meta) {
            $meta = [];
        }
        $display_options = $attributes['displayOptions'] ?? [];
        update_post_meta(
            $post_id,
            Post::META_KEY,
            array_merge($meta, [
                'displayOptions' => $display_options,
                'displayConditions' => $attributes['displayConditions'] ?? [],
                'advancedConditions' => $attributes['advancedConditions'] ?? [],
            ])
        );
    }
}
