<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Client\PendingRequest;
use Exception;

class PowerDNSService
{
    protected string $apiUrl;
    protected string $apiKey;
    protected string $serverId;
    protected int $timeout;

    public function __construct()
    {
        $this->apiUrl = "http://powerdns.serversistemleri.com:8081";
        $this->apiKey = "c394d5e9162ce7f16a56cca8da45dbe4";
        $this->serverId = "localhost";
        $this->timeout = (int) config('powerdns.timeout', 30);
    }

    /**
     * HTTP Client oluştur
     */
    protected function client(): PendingRequest
    {
        return Http::withHeaders([
            'X-API-Key' => $this->apiKey,
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ])->timeout($this->timeout);
    }

    /**
     * Base URL oluştur
     */
    protected function baseUrl(): string
    {
        return "{$this->apiUrl}/api/v1/servers/{$this->serverId}";
    }

    /**
     * Tüm zone'ları getir
     */
    public function getZones(): array
    {
        try {
            $response = $this->client()->get("{$this->baseUrl()}/zones");

            if ($response->successful()) {
                return $response->json() ?? [];
            }

            Log::error('PowerDNS getZones failed', [
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return [];
        } catch (Exception $e) {
            Log::error('PowerDNS getZones exception', ['error' => $e->getMessage()]);
            return [];
        }
    }

    /**
     * Sadece WHMCS account'una ait zone'ları getir
     */
    public function getWhmcsZones(): array
    {
        $zones = $this->getZones();
        $whmcsAccount = strtolower(config('powerdns.whmcs_account', 'whmcs'));

        return array_values(array_filter($zones, function (array $zone) use ($whmcsAccount): bool {
            return isset($zone['account']) && strtolower($zone['account']) === $whmcsAccount;
        }));
    }

    /**
     * Zone detaylarını getir
     */
    public function getZone(string $zoneId): ?array
    {
        try {
            // Zone ID'nin sonunda nokta yoksa ekle
            $zoneId = rtrim($zoneId, '.') . '.';

            $response = $this->client()->get("{$this->baseUrl()}/zones/{$zoneId}");

            if ($response->successful()) {
                return $response->json();
            }

            Log::error('PowerDNS getZone failed', [
                'zone_id' => $zoneId,
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return null;
        } catch (Exception $e) {
            Log::error('PowerDNS getZone exception', [
                'zone_id' => $zoneId,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * Zone'un WHMCS'e ait olup olmadığını kontrol et
     */
    public function isWhmcsZone(string $zoneId): bool
    {
        $zone = $this->getZone($zoneId);

        if ($zone === null) {
            return false;
        }

        $whmcsAccount = strtolower(config('powerdns.whmcs_account', 'whmcs'));
        return isset($zone['account']) && strtolower($zone['account']) === $whmcsAccount;
    }

    /**
     * Yeni zone oluştur
     */
    public function createZone(string $name, array $nameservers = [], string $account = 'whmcs'): ?array
    {
        try {
            $name = rtrim($name, '.') . '.';

            $data = [
                'name' => $name,
                'kind' => 'Native',
                'account' => $account,
                'nameservers' => $nameservers,
            ];

            $response = $this->client()->post("{$this->baseUrl()}/zones", $data);

            if ($response->successful()) {
                return $response->json();
            }

            Log::error('PowerDNS createZone failed', [
                'name' => $name,
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return null;
        } catch (Exception $e) {
            Log::error('PowerDNS createZone exception', [
                'name' => $name,
                'error' => $e->getMessage()
            ]);
            return null;
        }
    }

    /**
     * Zone sil
     */
    public function deleteZone(string $zoneId): bool
    {
        try {
            $zoneId = rtrim($zoneId, '.') . '.';

            $response = $this->client()->delete("{$this->baseUrl()}/zones/{$zoneId}");

            if ($response->successful()) {
                return true;
            }

            Log::error('PowerDNS deleteZone failed', [
                'zone_id' => $zoneId,
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return false;
        } catch (Exception $e) {
            Log::error('PowerDNS deleteZone exception', [
                'zone_id' => $zoneId,
                'error' => $e->getMessage()
            ]);
            return false;
        }
    }

    /**
     * DNS kayıtlarını güncelle (PATCH)
     */
    public function updateRecords(string $zoneId, array $rrsets): bool
    {
        try {
            $zoneId = rtrim($zoneId, '.') . '.';

            $response = $this->client()->patch("{$this->baseUrl()}/zones/{$zoneId}", [
                'rrsets' => $rrsets
            ]);

            if ($response->successful()) {
                return true;
            }

            Log::error('PowerDNS updateRecords failed', [
                'zone_id' => $zoneId,
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return false;
        } catch (Exception $e) {
            Log::error('PowerDNS updateRecords exception', [
                'zone_id' => $zoneId,
                'error' => $e->getMessage()
            ]);
            return false;
        }
    }

    /**
     * Kayıt ekle
     */
    public function addRecord(string $zoneId, string $name, string $type, string $content, int $ttl = 3600): bool
    {
        $name = rtrim($name, '.') . '.';

        $rrsets = [
            [
                'name' => $name,
                'type' => strtoupper($type),
                'ttl' => $ttl,
                'changetype' => 'REPLACE',
                'records' => [
                    [
                        'content' => $content,
                        'disabled' => false,
                    ]
                ]
            ]
        ];

        return $this->updateRecords($zoneId, $rrsets);
    }

    /**
     * Kayıt sil
     */
    public function deleteRecord(string $zoneId, string $name, string $type): bool
    {
        $name = rtrim($name, '.') . '.';

        $rrsets = [
            [
                'name' => $name,
                'type' => strtoupper($type),
                'changetype' => 'DELETE',
                'records' => []
            ]
        ];

        return $this->updateRecords($zoneId, $rrsets);
    }

    /**
     * Zone metadata güncelle
     */
    public function updateZoneMetadata(string $zoneId, array $metadata): bool
    {
        try {
            $zoneId = rtrim($zoneId, '.') . '.';

            $response = $this->client()->put("{$this->baseUrl()}/zones/{$zoneId}", $metadata);

            if ($response->successful()) {
                return true;
            }

            Log::error('PowerDNS updateZoneMetadata failed', [
                'zone_id' => $zoneId,
                'status' => $response->status(),
                'body' => $response->body()
            ]);

            return false;
        } catch (Exception $e) {
            Log::error('PowerDNS updateZoneMetadata exception', [
                'zone_id' => $zoneId,
                'error' => $e->getMessage()
            ]);
            return false;
        }
    }

    /**
     * Domain'in zone olarak var olup olmadığını kontrol et
     */
    public function zoneExists(string $domain): bool
    {
        return $this->getZone($domain) !== null;
    }

    /**
     * Server bilgilerini getir
     */
    public function getServerInfo(): ?array
    {
        try {
            $response = $this->client()->get("{$this->apiUrl}/api/v1/servers/{$this->serverId}");

            if ($response->successful()) {
                return $response->json();
            }

            return null;
        } catch (Exception $e) {
            Log::error('PowerDNS getServerInfo exception', ['error' => $e->getMessage()]);
            return null;
        }
    }

    /**
     * API bağlantısını test et
     */
    public function testConnection(): bool
    {
        return $this->getServerInfo() !== null;
    }
}
