<?php
namespace ShopyPress\Models;
if ( ! defined( 'ABSPATH' ) ) exit;

use ShopyPress\Config\SyncConfig;

class SyncState {
    const PHASE_SHOP_INIT = 'shop_init';
    const PHASE_COLLECTIONS = 'collections';
    const PHASE_PRODUCTS = 'products';
    const PHASE_CLEANUP = 'cleanup';

    const STATUS_WORKING = 'working';
    const STATUS_COMPLETED = 'completed';
    const STATUS_ERROR = 'error';

    public string $process_id;
    public string $status;
    public int $started_at;
    public int $updated_at;
    public string $phase;
    public int $offset;
    public int $total_processed;
    public int $total_products;
    public int $batch_size;
    public array $collection_ids;
    public array $product_ids;
    public ?string $cursor;
    public int $current_collection_index;
    public array $errors;

    public function __construct() {
        $this->process_id = $this->generateProcessId();
        $this->status = self::STATUS_WORKING;
        $this->started_at = time();
        $this->updated_at = time();
        $this->phase = self::PHASE_SHOP_INIT;
        $this->offset = 0;
        $this->total_processed = 0;
        $this->total_products = 0;
        $this->batch_size = SyncConfig::SYNC_BATCH_SIZE;
        $this->collection_ids = [];
        $this->product_ids = [];
        $this->cursor = null;
        $this->current_collection_index = 0;
        $this->errors = [];
    }

    public function toArray(): array {
        return [
            'process_id' => $this->process_id,
            'status' => $this->status,
            'started_at' => $this->started_at,
            'updated_at' => $this->updated_at,
            'phase' => $this->phase,
            'offset' => $this->offset,
            'total_processed' => $this->total_processed,
            'total_products' => $this->total_products,
            'batch_size' => $this->batch_size,
            'collection_ids' => $this->collection_ids,
            'product_ids' => $this->product_ids,
            'cursor' => $this->cursor,
            'current_collection_index' => $this->current_collection_index,
            'errors' => $this->errors,
        ];
    }

    public static function fromArray(array $data): self {
        $state = new self();
        $state->process_id = $data['process_id'] ?? $state->generateProcessId();
        $state->status = $data['status'] ?? self::STATUS_WORKING;
        $state->started_at = $data['started_at'] ?? time();
        $state->updated_at = $data['updated_at'] ?? time();
        $state->phase = $data['phase'] ?? self::PHASE_SHOP_INIT;
        $state->offset = $data['offset'] ?? 0;
        $state->total_processed = $data['total_processed'] ?? 0;
        $state->total_products = $data['total_products'] ?? 0;
        $state->batch_size = $data['batch_size'] ?? SyncConfig::SYNC_BATCH_SIZE;
        $state->collection_ids = $data['collection_ids'] ?? [];
        $state->product_ids = $data['product_ids'] ?? [];
        $state->cursor = $data['cursor'] ?? null;
        $state->current_collection_index = $data['current_collection_index'] ?? 0;
        $state->errors = $data['errors'] ?? [];
        return $state;
    }

    public function save(): bool {
        $this->updated_at = time();
        return update_option(SyncConfig::SYNC_STATE_OPTION_KEY, $this->toArray());
    }

    public static function load(): ?self {
        $data = get_option(SyncConfig::SYNC_STATE_OPTION_KEY);
        if (!$data || !is_array($data)) {
            return null;
        }
        return self::fromArray($data);
    }

    public static function delete(): bool {
        return delete_option(SyncConfig::SYNC_STATE_OPTION_KEY);
    }

    public function isWorking(): bool {
        return $this->status === self::STATUS_WORKING;
    }

    public function isCompleted(): bool {
        return $this->status === self::STATUS_COMPLETED;
    }

    public function hasError(): bool {
        return $this->status === self::STATUS_ERROR;
    }

    public function addError(string $error): void {
        $this->errors[] = [
            'message' => $error,
            'timestamp' => time(),
        ];
    }

    public function markCompleted(): void {
        $this->status = self::STATUS_COMPLETED;
        $this->updated_at = time();
    }

    public function markError(string $message): void {
        $this->status = self::STATUS_ERROR;
        $this->addError($message);
        $this->updated_at = time();
    }

    public function getProgressPercentage(): float {
        if ($this->total_products === 0) {
            return 0.0;
        }
        return round(($this->total_processed / $this->total_products) * 100, 2);
    }

    public function isStale(): bool {
        $one_hour = 3600;
        $elapsed = time() - $this->updated_at;
        return $elapsed > $one_hour;
    }

    private function generateProcessId(): string {
        return sprintf(
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
            wp_rand(0, 0xffff),
            wp_rand(0, 0xffff),
            wp_rand(0, 0xffff),
            wp_rand(0, 0x0fff) | 0x4000,
            wp_rand(0, 0x3fff) | 0x8000,
            wp_rand(0, 0xffff),
            wp_rand(0, 0xffff),
            wp_rand(0, 0xffff)
        );
    }
}
