<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Batch;

/**
 * Batch Response Value Object
 *
 * Represents the response for a batch of operations.
 *
 * Example:
 * {
 *   "results": [
 *     {
 *       "success": true,
 *       "operationId": "op-1",
 *       "html": "<div>Counter: 5</div>",
 *       "state": {"count": 5}
 *     },
 *     {
 *       "success": false,
 *       "operationId": "op-2",
 *       "error": "Component not found",
 *       "errorCode": "COMPONENT_NOT_FOUND"
 *     }
 *   ],
 *   "totalOperations": 2,
 *   "successCount": 1,
 *   "failureCount": 1
 * }
 */
final readonly class BatchResponse
{
    /** @var array<BatchResult> */
    public array $results;

    public int $totalOperations;

    public int $successCount;

    public int $failureCount;

    /**
     * @param BatchResult ...$results - Variadic parameter for type safety
     */
    public function __construct(BatchResult ...$results)
    {
        $this->results = $results;
        $this->totalOperations = count($results);
        $this->successCount = count(array_filter($results, fn ($r) => $r->success));
        $this->failureCount = $this->totalOperations - $this->successCount;
    }

    /**
     * Create from array of results
     *
     * @param array<BatchResult> $results
     */
    public static function fromResults(array $results): self
    {
        return new self(...$results);
    }

    /**
     * Get result by index
     */
    public function getResult(int $index): ?BatchResult
    {
        return $this->results[$index] ?? null;
    }

    /**
     * Get all results
     *
     * @return array<BatchResult>
     */
    public function getResults(): array
    {
        return $this->results;
    }

    /**
     * Get only successful results
     *
     * @return array<BatchResult>
     */
    public function getSuccessfulResults(): array
    {
        return array_filter($this->results, fn ($r) => $r->success);
    }

    /**
     * Get only failed results
     *
     * @return array<BatchResult>
     */
    public function getFailedResults(): array
    {
        return array_filter($this->results, fn ($r) => ! $r->success);
    }

    /**
     * Check if all operations succeeded
     */
    public function isFullSuccess(): bool
    {
        return $this->failureCount === 0;
    }

    /**
     * Check if all operations failed
     */
    public function isFullFailure(): bool
    {
        return $this->successCount === 0;
    }

    /**
     * Check if there are partial failures
     */
    public function hasPartialFailure(): bool
    {
        return $this->successCount > 0 && $this->failureCount > 0;
    }

    /**
     * Convert to array for JSON response
     */
    public function toArray(): array
    {
        return [
            'results' => array_map(
                fn (BatchResult $result) => $result->toArray(),
                $this->results
            ),
            'total_operations' => $this->totalOperations,
            'success_count' => $this->successCount,
            'failure_count' => $this->failureCount,
        ];
    }
}
