<?php

namespace App\Services;

use App\Repositories\SiteExportRepository;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Schema;
use Mtc\MercuryDataModels\Setting;

class SiteDownloadService
{
    private string $baseUrl;
    private string $token;
    private string $email;
    private string $tenantId;

    public function __construct(
        protected SiteExportRepository $repository
    ) {}

    /**
     * Configure the service with remote connection details
     */
    public function setConfig(string $baseUrl, string $token, string $email, string $tenantId): self
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->token = $token;
        $this->email = $email;
        $this->tenantId = $tenantId;

        return $this;
    }

    /**
     * Test connection to the remote server
     */
    public function testConnection(): array
    {
        try {
            $response = Http::timeout(30)
                ->withHeaders($this->getHeaders())
                ->post($this->getEndpoint('tables'), [
                    'include_vehicles' => false,
                ]);

            if ($response->successful()) {
                return [
                    'success' => true,
                    'message' => 'Connection successful',
                ];
            }

            if ($response->status() === 403) {
                return [
                    'success' => false,
                    'message' => 'Authentication failed. Please check your token and email.',
                ];
            }

            return [
                'success' => false,
                'message' => 'Connection failed: ' . $response->status(),
            ];
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Connection error: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * Get list of available tables from remote
     */
    public function getTableList(bool $includeVehicles): array
    {
        $response = Http::timeout(60)
            ->withHeaders($this->getHeaders())
            ->post($this->getEndpoint('tables'), [
                'include_vehicles' => $includeVehicles,
            ]);

        if (!$response->successful()) {
            throw new \RuntimeException('Failed to fetch table list: ' . $response->status());
        }

        return $response->json('tables', []);
    }

    /**
     * Fetch paginated data for a specific table
     */
    public function fetchTableData(string $table, int $page = 1, bool $includeVehicles = false): array
    {
        $response = Http::timeout(120)
            ->withHeaders($this->getHeaders())
            ->post($this->getEndpoint("data/{$table}"), [
                'include_vehicles' => $includeVehicles,
                'page' => $page,
            ]);

        if (!$response->successful()) {
            throw new \RuntimeException("Failed to fetch data for table {$table}: " . $response->status());
        }

        return $response->json();
    }

    /**
     * Import a table's data locally with truncation
     */
    public function importTable(string $table, array $records): int
    {
        if (empty($records)) {
            return 0;
        }

        // Special handling for settings table
        if ($table === 'settings') {
            return $this->importSettings($records);
        }

        // Standard table import
        DB::table($table)->insert($records);

        return count($records);
    }

    /**
     * Truncate a table before import
     */
    public function truncateTable(string $table): void
    {
        if (!Schema::hasTable($table)) {
            return;
        }

        DB::statement('SET FOREIGN_KEY_CHECKS=0');
        DB::table($table)->truncate();
        DB::statement('SET FOREIGN_KEY_CHECKS=1');
    }

    /**
     * Import settings with special handling for encrypted secrets
     */
    private function importSettings(array $records): int
    {
        $imported = 0;

        foreach ($records as $record) {
            $isEncryptedWithToken = $record['encrypted_with_token'] ?? false;
            unset($record['_encrypted_with_token']);

            // Handle secret decryption
            if ($isEncryptedWithToken && ($record['type'] ?? '') === 'secret') {
                $record['value'] = $this->repository->decryptWithToken($record['value'], $this->token);
            }

            // For text/list types, ensure value_text is set correctly
            if (in_array($record['type'] ?? '', ['text', 'list'])) {
                // value_text should already be correct from export
            }

            // Use Setting model to properly encrypt secrets with local APP_KEY
            $setting = Setting::query()->updateOrCreate(
                ['config_key' => $record['config_key']],
                collect($record)->except(['id', 'created_at', 'updated_at'])->toArray()
            );

            if ($setting) {
                $imported++;
            }
        }

        return $imported;
    }

    /**
     * Get HTTP headers for API requests
     */
    private function getHeaders(): array
    {
        return [
            'x-token' => $this->token,
            'x-user' => $this->email,
            'Accept' => 'application/json',
            'Content-Type' => 'application/json',
        ];
    }

    /**
     * Build full endpoint URL
     */
    private function getEndpoint(string $path): string
    {
        return "{$this->baseUrl}/api/site-export/{$this->tenantId}/{$path}";
    }
}
