<?php

namespace App\Core\License;

use App\Core\Product\AbstractProduct;
use App\Models\ClientLicense;

/**
 * 3rd-party subscription license base class (PRC-60).
 *
 * Software'den ayrımı:
 *   - Host binding YOK — key direkt müşteriye teslim
 *   - Lifetime YOK — daima subscription, period sonu renewal
 *   - Vendor API odaklı (genelde 3rd-party SaaS/plugin marketplace)
 */
abstract class AbstractLicense extends AbstractProduct
{
    /**
     * 3rd-party subscription key server-less'tir — vendor key delivery,
     * server account değil. Override edilmezse provisioning
     * `selectServer()`'da fail eder (PRC-450).
     */
    public function requiresServer(): bool
    {
        return false;
    }

    /**
     * Provisioning anında vendor'dan key al ve $license'a persist et.
     */
    abstract public function issueKey(ClientLicense $license, array $moduleConfig): array;

    /**
     * Period sonu renewal — vendor'a renewal request, key extend ya da
     * yeni key. Default impl: aynı issueKey'i tekrar çağır.
     */
    public function renewKey(ClientLicense $license, array $moduleConfig): array
    {
        return $this->issueKey($license, $moduleConfig);
    }

    /**
     * Vendor revoke + lokal flag.
     */
    public function revokeKey(ClientLicense $license, array $moduleConfig): array
    {
        $license->update(['revoked_at' => now()]);

        return $this->ok('Lisans revoked (lokal).');
    }

    public function createAccount(array $params): array
    {
        $license = $this->resolveOrCreateLicense($params);
        if (! $license) {
            return $this->fail('License bağlamı kurulamadı: client_product_id eksik.');
        }

        try {
            $this->issueKey($license, $params['module_config'] ?? []);
            $license->refresh();

            return $this->ok('Lisans key üretildi.', [
                'license_id' => $license->id,
                'issued' => $license->issued,
            ]);
        } catch (\Throwable $e) {
            $license->update([
                'last_error' => mb_substr($e->getMessage(), 0, 1000),
                'last_attempt_at' => now(),
            ]);

            return $this->fail('License issue hatası: ' . $e->getMessage());
        }
    }

    /**
     * Resolution: license_id → client_product_id fallback.
     * Admin terminate path `client_product_id`'yi sağlar.
     */
    public function terminateAccount(array $params): array
    {
        $license = null;

        $licenseId = $params['license_id'] ?? null;
        if ($licenseId) {
            $license = ClientLicense::find($licenseId);
        }

        if (! $license) {
            $clientProductId = $params['client_product_id']
                ?? $params['service_id']
                ?? $params['serviceid']
                ?? null;
            if ($clientProductId) {
                $license = ClientLicense::where('client_product_id', $clientProductId)
                    ->whereNull('revoked_at')
                    ->latest()
                    ->first();
            }
        }

        if ($license) {
            return $this->revokeKey($license, $params['module_config'] ?? []);
        }

        return $this->ok('License kaydı bulunamadı, no-op.');
    }

    public function suspendAccount(array $params): array
    {
        return $this->ok('License modülünde suspend yok (no-op).');
    }

    public function unsuspendAccount(array $params): array
    {
        return $this->ok('License modülünde unsuspend yok (no-op).');
    }

    public function changeAccountPassword(array $params): array
    {
        return $this->fail('License modülünde şifre değişimi yok.');
    }

    protected function resolveOrCreateLicense(array $params): ?ClientLicense
    {
        $licenseId = $params['license_id'] ?? null;
        if ($licenseId) {
            return ClientLicense::find($licenseId);
        }

        $clientProductId = $params['client_product_id']
            ?? $params['service_id']
            ?? $params['serviceid']
            ?? null;

        if ($clientProductId) {
            $existing = ClientLicense::where('client_product_id', $clientProductId)
                ->latest()
                ->first();
            if ($existing) {
                return $existing;
            }
        }

        $cp = $clientProductId
            ? \App\Models\ClientProduct::find($clientProductId)
            : null;
        if (! $cp) {
            return null;
        }

        return ClientLicense::create([
            'client_product_id' => $cp->id,
            'client_id' => $cp->client_id,
            'product_label' => $params['product_label'] ?? $cp->product?->name ?? null,
            'module' => strtolower((new \ReflectionClass(static::class))->getShortName()),
            'issued' => false,
            'expires_at' => $cp->next_due_date ?? now()->addYear(),
        ]);
    }

    protected function ok(string $message = '', array $data = []): array
    {
        return ['status' => 'success', 'message' => $message, 'data' => $data];
    }

    protected function fail(string $message, array $data = []): array
    {
        return ['status' => 'failed', 'message' => $message, 'data' => $data];
    }
}
