<?php

declare(strict_types=1);

namespace WhmcsMigrate;

final class Validator
{
    public function __construct(
        private readonly Database $db,
        private readonly Logger $logger,
    ) {}

    /**
     * Validate an array of client records from WHMCS.
     *
     * @param array<int, array<string, mixed>> $clients
     *
     * @return array{valid: int, skipped: int, errors: list<string>}
     */
    public function validateClientsData(array $clients): array
    {
        $valid = 0;
        $skipped = 0;
        $errors = [];
        $seenEmails = [];

        foreach ($clients as $index => $client) {
            $clientId = $client['id'] ?? $client['userid'] ?? "index:{$index}";

            // Check required fields
            if (empty($client['email'])) {
                $errors[] = "Client #{$clientId}: missing email address.";
                $skipped++;

                continue;
            }

            if (empty($client['firstname'])) {
                $errors[] = "Client #{$clientId}: missing first name.";
                $skipped++;

                continue;
            }

            // Check for duplicate emails in source data
            $email = strtolower(trim($client['email']));
            if (isset($seenEmails[$email])) {
                $errors[] = "Client #{$clientId}: duplicate email '{$email}' (first seen in client #{$seenEmails[$email]}).";
                $skipped++;

                continue;
            }

            $seenEmails[$email] = $clientId;
            $valid++;
        }

        return [
            'valid' => $valid,
            'skipped' => $skipped,
            'errors' => $errors,
        ];
    }

    /**
     * Validate an array of product records from WHMCS.
     *
     * @param array<int, array<string, mixed>> $products
     *
     * @return array{valid: int, skipped: int, errors: list<string>}
     */
    public function validateProductsData(array $products): array
    {
        $valid = 0;
        $skipped = 0;
        $errors = [];

        foreach ($products as $index => $product) {
            $productId = $product['pid'] ?? $product['id'] ?? "index:{$index}";

            if (empty($product['name'])) {
                $errors[] = "Product #{$productId}: missing name.";
                $skipped++;

                continue;
            }

            // Check for pricing data — at least one pricing field should be present
            $hasPricing = ! empty($product['pricing'])
                || isset($product['monthly'])
                || isset($product['quarterly'])
                || isset($product['semiannually'])
                || isset($product['annually']);

            if (! $hasPricing) {
                $errors[] = "Product #{$productId} ({$product['name']}): no pricing data found.";
                $skipped++;

                continue;
            }

            $valid++;
        }

        return [
            'valid' => $valid,
            'skipped' => $skipped,
            'errors' => $errors,
        ];
    }

    /**
     * Perform a full pre-flight validation by testing WHMCS API connectivity
     * and fetching basic counts.
     */
    public function validateAll(WhmcsApi $api): bool
    {
        $this->logger->section('Pre-flight Validation');

        $allOk = true;

        // Test WHMCS API connectivity
        $this->logger->info('Testing WHMCS API connectivity...');

        try {
            $result = $api->call('GetClients', ['limitstart' => 0, 'limitnum' => 1]);
            $totalClients = (int) ($result['totalresults'] ?? 0);
            $this->logger->info("WHMCS API connected. Total clients: {$totalClients}");
        } catch (\RuntimeException $e) {
            $this->logger->error('WHMCS API connection failed: ' . $e->getMessage());
            $allOk = false;
        }

        // Test product listing
        try {
            $result = $api->call('GetProducts', ['limitstart' => 0, 'limitnum' => 1]);
            $totalProducts = (int) ($result['totalresults'] ?? 0);
            $this->logger->info("WHMCS products found: {$totalProducts}");
        } catch (\RuntimeException $e) {
            $this->logger->error('WHMCS GetProducts failed: ' . $e->getMessage());
            $allOk = false;
        }

        // Test EZSCALE database connectivity
        $this->logger->info('Testing EZSCALE database connectivity...');

        try {
            $row = $this->db->queryOne('SELECT 1 AS ok');

            if ($row !== null && ($row['ok'] ?? 0) === 1) {
                $this->logger->info('EZSCALE database connected.');
            } else {
                $this->logger->error('EZSCALE database query returned unexpected result.');
                $allOk = false;
            }
        } catch (\Throwable $e) {
            $this->logger->error('EZSCALE database connection failed: ' . $e->getMessage());
            $allOk = false;
        }

        // Verify essential tables exist
        $requiredTables = ['users', 'user_profiles', 'plans', 'plan_prices', 'subscriptions', 'subscription_items', 'services', 'invoices', 'invoice_items', 'payment_transactions', 'coupons', 'roles', 'model_has_roles'];
        foreach ($requiredTables as $table) {
            try {
                $this->db->query("SELECT 1 FROM `{$table}` LIMIT 0");
                $this->logger->debug("Table '{$table}' exists.");
            } catch (\Throwable $e) {
                $this->logger->error("Required table '{$table}' is missing or inaccessible.");
                $allOk = false;
            }
        }

        if ($allOk) {
            $this->logger->info('All pre-flight checks passed.');
        } else {
            $this->logger->error('Some pre-flight checks failed. Resolve issues before running the migration.');
        }

        return $allOk;
    }
}
