<?php
/**
 * Product attribute groups — organize global WooCommerce attributes into named groups.
 */

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

const ZERTI_ATTRIBUTE_GROUPS_OPTION = 'zerti_attribute_groups';

function zerti_product_attribute_groups_available(): bool
{
    return zerti_product_attributes_available();
}

function zerti_user_can_manage_product_attribute_groups(): bool
{
    return zerti_user_can_manage_product_attributes();
}

/**
 * @return list<array<string, mixed>>
 */
function zerti_product_attribute_groups_raw(): array
{
    $stored = get_option(ZERTI_ATTRIBUTE_GROUPS_OPTION, []);
    if (!is_array($stored)) {
        return [];
    }

    $items = [];
    foreach ($stored as $row) {
        if (!is_array($row)) {
            continue;
        }
        $id = (int) ($row['id'] ?? 0);
        if ($id < 1) {
            continue;
        }
        $attribute_ids = [];
        if (isset($row['attribute_ids']) && is_array($row['attribute_ids'])) {
            foreach ($row['attribute_ids'] as $aid) {
                $aid = (int) $aid;
                if ($aid > 0) {
                    $attribute_ids[] = $aid;
                }
            }
        }
        $attribute_ids = array_values(array_unique($attribute_ids));
        $items[] = [
            'id' => $id,
            'name' => isset($row['name']) ? (string) $row['name'] : '',
            'slug' => isset($row['slug']) ? (string) $row['slug'] : '',
            'description' => isset($row['description']) ? (string) $row['description'] : '',
            'menu_order' => (int) ($row['menu_order'] ?? 0),
            'attribute_ids' => $attribute_ids,
        ];
    }

    usort(
        $items,
        static function (array $a, array $b): int {
            $oa = (int) ($a['menu_order'] ?? 0);
            $ob = (int) ($b['menu_order'] ?? 0);
            if ($oa !== $ob) {
                return $oa <=> $ob;
            }

            return strcasecmp((string) ($a['name'] ?? ''), (string) ($b['name'] ?? ''));
        }
    );

    return $items;
}

/**
 * @param list<array<string, mixed>> $items
 */
function zerti_product_attribute_groups_persist(array $items): void
{
    update_option(ZERTI_ATTRIBUTE_GROUPS_OPTION, array_values($items), false);
}

function zerti_product_attribute_groups_next_id(array $items): int
{
    $max = 0;
    foreach ($items as $row) {
        $max = max($max, (int) ($row['id'] ?? 0));
    }

    return $max + 1;
}

/**
 * @return list<array{id:int,name:string,slug:string}>
 */
function zerti_product_attribute_groups_available_attributes(): array
{
    $out = [];
    foreach (zerti_product_attributes_list() as $attr) {
        $id = (int) ($attr['id'] ?? 0);
        if ($id < 1) {
            continue;
        }
        $out[] = [
            'id' => $id,
            'name' => (string) ($attr['name'] ?? ''),
            'slug' => (string) ($attr['slug'] ?? ''),
        ];
    }

    return $out;
}

/**
 * @param array<string, mixed> $row
 * @return array<string, mixed>
 */
function zerti_product_attribute_group_to_item(array $row): array
{
    $attribute_ids = [];
    if (isset($row['attribute_ids']) && is_array($row['attribute_ids'])) {
        foreach ($row['attribute_ids'] as $aid) {
            $aid = (int) $aid;
            if ($aid > 0) {
                $attribute_ids[] = $aid;
            }
        }
    }
    $attribute_ids = array_values(array_unique($attribute_ids));

    return [
        'id' => (int) ($row['id'] ?? 0),
        'name' => (string) ($row['name'] ?? ''),
        'slug' => (string) ($row['slug'] ?? ''),
        'description' => (string) ($row['description'] ?? ''),
        'menu_order' => (int) ($row['menu_order'] ?? 0),
        'attribute_ids' => $attribute_ids,
        'attributes_count' => count($attribute_ids),
    ];
}

/**
 * @return list<array<string, mixed>>
 */
function zerti_product_attribute_groups_list(): array
{
    $items = [];
    foreach (zerti_product_attribute_groups_raw() as $row) {
        $items[] = zerti_product_attribute_group_to_item($row);
    }

    return $items;
}

/**
 * @return array<string, mixed>|null
 */
function zerti_product_attribute_group_get(int $group_id): ?array
{
    if ($group_id < 1) {
        return null;
    }

    foreach (zerti_product_attribute_groups_raw() as $row) {
        if ((int) ($row['id'] ?? 0) === $group_id) {
            return zerti_product_attribute_group_to_item($row);
        }
    }

    return null;
}

/**
 * @param array<string, mixed> $source
 * @return array{id:int,name:string,slug:string,description:string,menu_order:int,attribute_ids:list<int>}
 */
function zerti_product_attribute_group_payload_from_array(array $source): array
{
    $id = isset($source['id']) ? absint(wp_unslash((string) $source['id'])) : 0;
    $name = isset($source['name']) ? sanitize_text_field(wp_unslash((string) $source['name'])) : '';
    $slug = isset($source['slug']) ? sanitize_title(wp_unslash((string) $source['slug'])) : '';
    $description = isset($source['description']) ? sanitize_textarea_field(wp_unslash((string) $source['description'])) : '';
    $menu_order_raw = isset($source['menu_order']) ? trim(wp_unslash((string) $source['menu_order'])) : '0';
    $menu_order_latin = function_exists('zerti_to_latin_digits') ? zerti_to_latin_digits($menu_order_raw) : $menu_order_raw;
    $menu_order = absint($menu_order_latin);

    $attribute_ids = [];
    if (isset($source['attribute_ids'])) {
        $raw = wp_unslash($source['attribute_ids']);
        if (is_string($raw)) {
            $decoded = json_decode($raw, true);
            if (is_array($decoded)) {
                foreach ($decoded as $aid) {
                    $aid = (int) $aid;
                    if ($aid > 0) {
                        $attribute_ids[] = $aid;
                    }
                }
            }
        } elseif (is_array($raw)) {
            foreach ($raw as $aid) {
                $aid = (int) $aid;
                if ($aid > 0) {
                    $attribute_ids[] = $aid;
                }
            }
        }
    }

    return [
        'id' => $id,
        'name' => $name,
        'slug' => $slug,
        'description' => $description,
        'menu_order' => $menu_order,
        'attribute_ids' => array_values(array_unique($attribute_ids)),
    ];
}

/**
 * @return array{id:int,name:string,slug:string,description:string,menu_order:int,attribute_ids:list<int>}
 */
/**
 * @param list<int> $attribute_ids
 * @return list<int>
 */
function zerti_product_attribute_group_sanitize_attribute_ids(array $attribute_ids): array
{
    $valid = [];
    foreach (zerti_product_attributes_list() as $attr) {
        $id = (int) ($attr['id'] ?? 0);
        if ($id > 0) {
            $valid[$id] = true;
        }
    }

    $out = [];
    foreach ($attribute_ids as $aid) {
        $aid = (int) $aid;
        if ($aid > 0 && isset($valid[$aid])) {
            $out[] = $aid;
        }
    }

    return array_values(array_unique($out));
}

/**
 * @param array{id:int,name:string,slug:string,description:string,menu_order:int,attribute_ids:list<int>} $payload
 * @return array{ok:bool,item?:array<string,mixed>,message?:string,code?:string}
 */
function zerti_product_attribute_group_save(array $payload): array
{
    if (!zerti_product_attribute_groups_available()) {
        return ['ok' => false, 'message' => __('WooCommerce is not installed', 'zerti'), 'code' => 'woocommerce_missing'];
    }

    $name = trim((string) ($payload['name'] ?? ''));
    if ($name === '') {
        return ['ok' => false, 'message' => __('Name is required', 'zerti'), 'code' => 'name_required'];
    }

    $items = zerti_product_attribute_groups_raw();
    $id = (int) ($payload['id'] ?? 0);
    $slug = trim((string) ($payload['slug'] ?? ''));
    if ($slug === '') {
        $slug = sanitize_title($name);
    }

    foreach ($items as $row) {
        $row_id = (int) ($row['id'] ?? 0);
        if ($row_id === $id) {
            continue;
        }
        if ((string) ($row['slug'] ?? '') === $slug) {
            return ['ok' => false, 'message' => __('Slug is already in use', 'zerti'), 'code' => 'slug_exists'];
        }
    }

    $attribute_ids = zerti_product_attribute_group_sanitize_attribute_ids($payload['attribute_ids'] ?? []);
    $record = [
        'id' => $id > 0 ? $id : zerti_product_attribute_groups_next_id($items),
        'name' => $name,
        'slug' => $slug,
        'description' => (string) ($payload['description'] ?? ''),
        'menu_order' => (int) ($payload['menu_order'] ?? 0),
        'attribute_ids' => $attribute_ids,
    ];

    $found = false;
    foreach ($items as $index => $row) {
        if ((int) ($row['id'] ?? 0) === $record['id']) {
            $items[$index] = $record;
            $found = true;
            break;
        }
    }
    if (!$found) {
        $items[] = $record;
    }

    zerti_product_attribute_groups_persist($items);

    $item = zerti_product_attribute_group_get((int) $record['id']);

    return $item !== null
        ? ['ok' => true, 'item' => $item]
        : ['ok' => false, 'message' => __('Could not save group', 'zerti'), 'code' => 'save_failed'];
}

/**
 * @return array{ok:bool,message?:string,code?:string}
 */
function zerti_product_attribute_group_delete(int $group_id): array
{
    if ($group_id < 1) {
        return ['ok' => false, 'message' => __('Invalid group', 'zerti'), 'code' => 'invalid_id'];
    }

    $items = zerti_product_attribute_groups_raw();
    $before = count($items);
    $items = array_values(array_filter(
        $items,
        static function (array $row) use ($group_id): bool {
            return (int) ($row['id'] ?? 0) !== $group_id;
        }
    ));

    if (count($items) === $before) {
        return ['ok' => false, 'message' => __('Group not found', 'zerti'), 'code' => 'not_found'];
    }

    zerti_product_attribute_groups_persist($items);

    return ['ok' => true];
}

function zerti_product_attribute_group_error_message(string $code, string $fallback = ''): string
{
    $map = [
        'woocommerce_missing' => __('WooCommerce must be installed and active.', 'zerti'),
        'name_required' => __('Group name is required.', 'zerti'),
        'slug_exists' => __('Slug is already in use.', 'zerti'),
        'invalid_id' => __('Invalid group.', 'zerti'),
        'not_found' => __('Group not found.', 'zerti'),
        'forbidden' => __('You do not have permission to manage attribute groups.', 'zerti'),
    ];

    if ($code !== '' && isset($map[$code])) {
        return $map[$code];
    }

    return $fallback !== '' ? $fallback : __('Something went wrong.', 'zerti');
}
