<?php

namespace App\Console\Commands;

use App\Master\SiteManager;
use App\Services\SiteDownloadService;
use Illuminate\Console\Command;
use Mtc\MercuryDataModels\Tenant;

class DownloadSiteCommand extends Command
{
    protected $signature = 'download:site
        {--environment= : Environment to connect to (production/staging/custom)}
        {--url= : Custom URL for the environment}
        {--token= : Access token from Content Sync section}
        {--email= : User email associated with the token}
        {--tenant= : Remote tenant ID to download from}
        {--local-tenant= : Local tenant ID to import into (for update mode)}
        {--site-name= : Name for new site (for new mode)}
        {--tier= : Tier for new site (lite/standard/pro/enterprise)}
        {--include-vehicles : Include vehicle tables in download}
        {--new : Create new site (default is update existing)}';

    protected $description = 'Download a complete site from a remote environment to local';

    private const ENVIRONMENTS = [
        'production' => 'https://admin.autonomy.mtcmedia.co.uk',
        'staging' => 'https://autonomy-staging.mtcmedia.co.uk',
    ];

    public function handle(SiteDownloadService $service, SiteManager $siteManager): int
    {

        // Get configuration from options or prompts
        $config = $this->getConfiguration();

        if (!$config) {
            return self::FAILURE;
        }

        // Configure the service
        $service->setConfig(
            $config['url'],
            $config['token'],
            $config['email'],
            $config['remote_tenant']
        );

        // Test connection
        $this->info('Testing connection...');
        $result = $service->testConnection();

        if (!$result['success']) {
            $this->error($result['message']);
            return self::FAILURE;
        }

        $this->info('Connection successful!');
        $this->newLine();

        // Get table list
        $this->info('Fetching table list...');

        try {
            $tables = $service->getTableList($config['include_vehicles']);
        } catch (\Exception $e) {
            $this->error('Failed to fetch table list: ' . $e->getMessage());
            return self::FAILURE;
        }

        if (empty($tables)) {
            $this->warn('No tables found to download.');
            return self::SUCCESS;
        }

        // Display tables to be downloaded
        $this->info('Tables to download:');
        $totalRecords = 0;
        foreach ($tables as $table) {
            $this->line("  - {$table['name']} ({$table['count']} records)");
            $totalRecords += $table['count'];
        }
        $this->newLine();
        $this->info("Total: " . count($tables) . " tables, {$totalRecords} records");
        $this->newLine();

        // Confirm before proceeding
        if (!$this->confirm('This will TRUNCATE local tables before importing. Continue?', false)) {
            $this->info('Operation cancelled.');
            return self::SUCCESS;
        }

        // Create or initialize tenant
        if ($config['is_new']) {
            $this->info("Creating new site: {$config['site_name']} (tier: {$config['tier']})...");
            $tenant = $siteManager->addSiteRecord($config['site_name'], '', $config['tier']);
            $this->info("Created tenant: {$tenant->id}");
        } else {
            $tenant = Tenant::find($config['local_tenant']);
            if (!$tenant) {
                $this->error("Local tenant not found: {$config['local_tenant']}");
                return self::FAILURE;
            }
        }

        // Initialize tenancy to switch to tenant database
        $this->info("Initializing tenancy for: {$tenant->name}...");
        tenancy()->initialize($tenant);
        $this->newLine();

        // Begin import process
        $this->info('Starting import...');
        $this->newLine();

        $importedTables = 0;
        $importedRecords = 0;
        $errors = [];

        foreach ($tables as $tableInfo) {
            $table = $tableInfo['name'];
            $recordCount = $tableInfo['count'];

            $this->info("Importing {$table}...");

            try {
                // Always truncate table first (new sites have seeded data)
                $service->truncateTable($table);

                if ($recordCount === 0) {
                    $this->line("  Skipped (empty table)");
                    continue;
                }

                // Calculate pages
                $perPage = 100;
                $totalPages = (int) ceil($recordCount / $perPage);

                // Create progress bar
                $progressBar = $this->output->createProgressBar($recordCount);
                $progressBar->start();

                $tableImported = 0;

                // Fetch and import each page
                for ($page = 1; $page <= $totalPages; $page++) {
                    $response = $service->fetchTableData($table, $page, $config['include_vehicles']);

                    $records = $response['data'] ?? [];

                    if (!empty($records)) {
                        $imported = $service->importTable($table, $records);
                        $tableImported += $imported;
                        $progressBar->advance(count($records));
                    }
                }

                $progressBar->finish();
                $this->newLine();
                $this->line("  Imported {$tableImported} records");

                $importedTables++;
                $importedRecords += $tableImported;

            } catch (\Exception $e) {
                $this->newLine();
                $this->error("  Error: " . $e->getMessage());
                $errors[] = [
                    'table' => $table,
                    'error' => $e->getMessage(),
                ];
            }
        }

        // Summary
        $this->newLine();
        $this->info('==================');
        $this->info('Import Complete!');
        $this->info('==================');
        $this->info("Tables imported: {$importedTables}/" . count($tables));
        $this->info("Records imported: {$importedRecords}");

        if (!empty($errors)) {
            $this->newLine();
            $this->warn('Errors occurred:');
            foreach ($errors as $error) {
                $this->error("  - {$error['table']}: {$error['error']}");
            }
            return self::FAILURE;
        }

        return self::SUCCESS;
    }

    /**
     * Get configuration from options or interactive prompts
     */
    private function getConfiguration(): ?array
    {
        // Environment selection
        $env = $this->option('environment');
        $url = $this->option('url');

        if (!$env && !$url) {
            $env = $this->choice(
                'Which environment to connect to?',
                ['production', 'staging', 'custom'],
                0
            );
        }

        if ($env === 'custom' || (!$env && $url)) {
            $url = $url ?: $this->ask('Enter the custom endpoint URL');
            if (!$url) {
                $this->error('URL is required for custom environment');
                return null;
            }
        } else {
            $url = self::ENVIRONMENTS[$env] ?? null;
            if (!$url) {
                $this->error("Unknown environment: {$env}");
                return null;
            }
        }

        // Token
        $token = $this->option('token') ?: $this->secret(
            'Enter the access token (from Content Sync section)'
        );

        if (!$token) {
            $this->error('Access token is required');
            return null;
        }

        // Email
        $email = $this->option('email') ?: $this->ask(
            'Enter your email address (associated with the token)'
        );

        if (!$email) {
            $this->error('Email is required');
            return null;
        }

        // Remote Tenant ID (to download from)
        $remoteTenant = $this->option('tenant') ?: $this->ask(
            'Enter the remote tenant ID to download from'
        );

        if (!$remoteTenant) {
            $this->error('Remote tenant ID is required');
            return null;
        }

        // New or update
        $isNew = $this->option('new');
        if (!$isNew && !$this->option('no-interaction')) {
            $mode = $this->choice(
                'Create new site or update existing?',
                ['update', 'new'],
                0
            );
            $isNew = $mode === 'new';
        }

        // Get local tenant or site name based on mode
        $localTenant = null;
        $siteName = null;

        if ($isNew) {
            $siteName = $this->option('site-name') ?: $this->ask(
                'Enter the name for the new site'
            );
            if (!$siteName) {
                $this->error('Site name is required for new sites');
                return null;
            }

            $tier = $this->option('tier') ?: $this->choice(
                'Select tier for the new site',
                ['lite', 'standard', 'pro', 'enterprise'],
                1
            );
        } else {
            $localTenant = $this->option('local-tenant') ?: $this->ask(
                'Enter the local tenant ID to import into'
            );
            if (!$localTenant) {
                $this->error('Local tenant ID is required for updates');
                return null;
            }
        }

        // Include vehicles
        $includeVehicles = $this->option('include-vehicles');
        if (!$includeVehicles && !$this->option('no-interaction')) {
            $includeVehicles = $this->confirm('Include vehicle tables? (vehicles, finance, tech data, etc.)');
        }

        // Show configuration summary
        $this->newLine();
        $this->info('Configuration:');
        $this->line("  Environment: {$url}");
        $this->line("  Remote Tenant: {$remoteTenant}");
        if ($isNew) {
            $this->line("  Mode: Create new site '{$siteName}' (tier: {$tier})");
        } else {
            $this->line("  Mode: Update existing tenant '{$localTenant}'");
        }
        $this->line("  Include vehicles: " . ($includeVehicles ? 'Yes' : 'No'));
        $this->newLine();

        if (!$this->confirm('Proceed with this configuration?', true)) {
            return null;
        }

        return [
            'url' => $url,
            'token' => $token,
            'email' => $email,
            'remote_tenant' => $remoteTenant,
            'local_tenant' => $localTenant,
            'site_name' => $siteName,
            'tier' => $tier ?? null,
            'is_new' => $isNew,
            'include_vehicles' => $includeVehicles,
        ];
    }
}
