<?php

/**
 * Product Releases Controller V1
 *
 * Meta-backed release registry for Licenzo products.
 *
 * @package Licenzo\Http\Controller\Api\V1
 */

namespace Licenzo\Http\Controller\Api\V1;

use Licenzo\Framework\Http\Request;
use Licenzo\Http\Traits\HandlesErrors;
use Licenzo\Services\Updates\ProductReleaseService;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class ProductReleasesController
{
    use HandlesErrors;

    /**
     * @var ProductReleaseService
     */
    private $service;

    public function __construct(?ProductReleaseService $service = null)
    {
        $this->service = $service ?? new ProductReleaseService();
    }

    public function index(Request $request, $productId = null): array
    {
        try {
            $resolvedProductId = $this->resolveProductId($request, $productId);
            $filters = $request->getSafe([
                'status' => 'sanitize_text_field',
                'channel' => 'sanitize_text_field',
                'search' => 'sanitize_text_field',
                'page' => 'absint',
                'per_page' => 'absint',
            ]);

            $result = $this->service->listForProduct($resolvedProductId, $filters);

            return [
                'success' => true,
                'product' => $result['product'],
                'releases' => $result['items'],
                'pagination' => $result['pagination'],
                'filters' => $result['filters'],
            ];
        } catch (\Throwable $e) {
            return $this->handleError($e, 'Failed to retrieve product releases');
        }
    }

    public function store(Request $request, $productId = null): array
    {
        try {
            $resolvedProductId = $this->resolveProductId($request, $productId);
            $payload = $this->extractReleasePayload($request);
            $release = $this->service->createRelease($resolvedProductId, $payload);

            return [
                'success' => true,
                'message' => 'Release created successfully',
                'release' => $release,
            ];
        } catch (\Throwable $e) {
            return $this->handleError($e, 'Failed to create release');
        }
    }

    public function show(Request $request, $productId = null, $releaseUuid = null): array
    {
        try {
            $resolvedProductId = $this->resolveProductId($request, $productId);
            $releaseUuid = sanitize_text_field((string) ($releaseUuid ?: $request->get('release_uuid')));
            if ($releaseUuid === '') {
                return $this->validationError(['release_uuid' => 'Release UUID is required.']);
            }

            $release = $this->service->getRelease($resolvedProductId, $releaseUuid);
            if (!$release) {
                return $this->notFoundError('Release not found');
            }

            return [
                'success' => true,
                'release' => $release,
            ];
        } catch (\Throwable $e) {
            return $this->handleError($e, 'Failed to retrieve release');
        }
    }

    public function update(Request $request, $productId = null, $releaseUuid = null): array
    {
        try {
            $resolvedProductId = $this->resolveProductId($request, $productId);
            $releaseUuid = sanitize_text_field((string) ($releaseUuid ?: $request->get('release_uuid')));
            if ($releaseUuid === '') {
                return $this->validationError(['release_uuid' => 'Release UUID is required.']);
            }

            $payload = $this->extractReleasePayload($request);
            $release = $this->service->updateRelease($resolvedProductId, $releaseUuid, $payload);

            return [
                'success' => true,
                'message' => 'Release updated successfully',
                'release' => $release,
            ];
        } catch (\Throwable $e) {
            return $this->handleError($e, 'Failed to update release');
        }
    }

    public function destroy(Request $request, $productId = null, $releaseUuid = null): array
    {
        try {
            $resolvedProductId = $this->resolveProductId($request, $productId);
            $releaseUuid = sanitize_text_field((string) ($releaseUuid ?: $request->get('release_uuid')));
            if ($releaseUuid === '') {
                return $this->validationError(['release_uuid' => 'Release UUID is required.']);
            }

            $deleted = $this->service->deleteRelease($resolvedProductId, $releaseUuid);
            if (!$deleted) {
                return $this->notFoundError('Release not found');
            }

            return [
                'success' => true,
                'message' => 'Release deleted successfully',
            ];
        } catch (\Throwable $e) {
            return $this->handleError($e, 'Failed to delete release');
        }
    }

    private function resolveProductId(Request $request, $routeProductId): int
    {
        $productId = absint($routeProductId ?: $request->getSafe('product_id', 'absint', 0));
        if ($productId <= 0) {
            throw new \InvalidArgumentException('Product ID is required.');
        }

        return $productId;
    }

    /**
     * @return array<string,mixed>
     */
    private function extractReleasePayload(Request $request): array
    {
        $base = [];

        $scalarFields = [
            'title' => 'sanitize_text_field',
            'version' => 'sanitize_text_field',
            'status' => 'sanitize_text_field',
            'channel' => 'sanitize_text_field',
            'release_date' => 'sanitize_text_field',
            'changelog' => 'sanitize_textarea_field',
        ];

        foreach ($scalarFields as $field => $sanitizer) {
            if (!$request->has($field)) {
                continue;
            }

            $base[$field] = $request->getSafe($field, $sanitizer);
        }

        if ($request->has('is_available')) {
            $base['is_available'] = $request->get('is_available', null);
        }

        $variationPackages = $request->get('variation_packages', null);
        if (is_string($variationPackages) && $variationPackages !== '') {
            $decoded = json_decode($variationPackages, true);
            $variationPackages = is_array($decoded) ? $decoded : null;
        }
        if (is_array($variationPackages)) {
            $base['variation_packages'] = $variationPackages;
        }

        $sdkMeta = $request->get('sdk_meta', null);
        if (is_string($sdkMeta) && $sdkMeta !== '') {
            $decoded = json_decode($sdkMeta, true);
            $sdkMeta = is_array($decoded) ? $decoded : null;
        }
        if (is_array($sdkMeta)) {
            $base['sdk_meta'] = $sdkMeta;
        }

        $metadata = $request->get('metadata', null);
        if (is_string($metadata) && $metadata !== '') {
            $decoded = json_decode($metadata, true);
            $metadata = is_array($decoded) ? $decoded : null;
        }
        if (is_array($metadata)) {
            $base['metadata'] = $metadata;
        }

        return $base;
    }
}
