<?php

namespace App\Modules\Xero\Services;

use App\Modules\Xero\Models\XeroToken;
use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class XeroValidationService
{
    protected $authService;
    
    public function __construct(XeroAuthService $authService)
    {
        $this->authService = $authService;
    }
    
    /**
     * Comprehensive validation of Xero integration
     */
    public function validateIntegration(): array
    {
        $results = [
            'status' => 'unknown',
            'issues' => [],
            'warnings' => [],
            'details' => []
        ];
        
        // Check 1: Settings configuration
        $settingsCheck = $this->validateSettings();
        $results['details']['settings'] = $settingsCheck;
        
        if (!$settingsCheck['valid']) {
            $results['issues'][] = 'Xero settings not properly configured';
            $results['status'] = 'error';
        }
        
        // Check 2: Database table
        $tableCheck = $this->validateDatabaseTable();
        $results['details']['database'] = $tableCheck;
        
        if (!$tableCheck['valid']) {
            $results['issues'][] = 'Xero database table missing';
            $results['status'] = 'error';
        }
        
        // Check 3: Token availability
        $tokenCheck = $this->validateTokens();
        $results['details']['tokens'] = $tokenCheck;
        
        if (!$tokenCheck['valid']) {
            $results['issues'][] = 'No valid Xero tokens found';
            $results['status'] = 'error';
        }
        
        // Check 4: API connectivity
        $apiCheck = $this->validateApiConnectivity();
        $results['details']['api'] = $apiCheck;
        
        if (!$apiCheck['valid']) {
            $results['issues'][] = 'Xero API connectivity failed';
            $results['status'] = 'error';
        }
        
        // Determine overall status
        if (empty($results['issues'])) {
            $results['status'] = 'success';
        } elseif (empty($results['issues']) && !empty($results['warnings'])) {
            $results['status'] = 'warning';
        }
        
        return $results;
    }
    
    /**
     * Validate Xero settings configuration
     */
    private function validateSettings(): array
    {
        $clientId = Setting::get('integrations.xero.client_id');
        $clientSecret = Setting::get('integrations.xero.client_secret');
        $redirectUri = Setting::get('integrations.xero.redirect_uri');
        
        $valid = !empty($clientId) && !empty($clientSecret) && !empty($redirectUri);
        
        return [
            'valid' => $valid,
            'client_id' => !empty($clientId),
            'client_secret' => !empty($clientSecret),
            'redirect_uri' => !empty($redirectUri),
            'message' => $valid ? 'Settings properly configured' : 'Missing required settings'
        ];
    }
    
    /**
     * Validate database table exists
     */
    private function validateDatabaseTable(): array
    {
        try {
            $tokenCount = XeroToken::count();
            return [
                'valid' => true,
                'token_count' => $tokenCount,
                'message' => "Database table exists with {$tokenCount} tokens"
            ];
        } catch (\Exception $e) {
            return [
                'valid' => false,
                'error' => $e->getMessage(),
                'message' => 'Database table does not exist'
            ];
        }
    }
    
    /**
     * Validate token availability and validity
     */
    private function validateTokens(): array
    {
        try {
            $systemTokens = XeroToken::whereNull('user_id')->count();
            $userTokens = XeroToken::whereNotNull('user_id')->count();
            $validTokens = XeroToken::where('expires_at', '>', Carbon::now())->count();
            $expiredTokens = XeroToken::where('expires_at', '<=', Carbon::now())->count();
            
            $valid = $validTokens > 0;
            
            return [
                'valid' => $valid,
                'system_tokens' => $systemTokens,
                'user_tokens' => $userTokens,
                'valid_tokens' => $validTokens,
                'expired_tokens' => $expiredTokens,
                'message' => $valid ? "Found {$validTokens} valid tokens" : 'No valid tokens found'
            ];
        } catch (\Exception $e) {
            return [
                'valid' => false,
                'error' => $e->getMessage(),
                'message' => 'Error checking tokens'
            ];
        }
    }
    
    /**
     * Validate API connectivity
     */
    private function validateApiConnectivity(): array
    {
        try {
            $token = $this->authService->getValidToken();
            
            if (!$token) {
                return [
                    'valid' => false,
                    'message' => 'No valid token available for API test'
                ];
            }
            
            // Test API call using the same pattern as XeroService
            $url = rtrim($this->authService->getBaseUrl(), '/') . '/Organisation';
            $response = $this->authService->httpClient()->get($url);
            
            return [
                'valid' => $response->successful(),
                'status_code' => $response->status(),
                'tenant_name' => $token->tenant_name,
                'message' => $response->successful() ? 'API connectivity successful' : 'API connectivity failed'
            ];
            
        } catch (\Exception $e) {
            return [
                'valid' => false,
                'error' => $e->getMessage(),
                'message' => 'API connectivity test failed'
            ];
        }
    }
    
    /**
     * Get detailed connection status for admin interface
     */
    public function getConnectionStatus(): array
    {
        $validation = $this->validateIntegration();
        
        $status = [
            'connected' => $validation['status'] === 'success',
            'status' => $validation['status'],
            'last_check' => now()->toISOString(),
            'issues' => $validation['issues'],
            'warnings' => $validation['warnings'],
            'details' => $validation['details']
        ];
        
        // Add token information
        try {
            $tokens = XeroToken::all();
            $status['tokens'] = $tokens->map(function ($token) {
                return [
                    'id' => $token->id,
                    'tenant_name' => $token->tenant_name,
                    'tenant_id' => $token->tenant_id,
                    'expires_at' => $token->expires_at?->toISOString(),
                    'is_expired' => $token->isExpired(),
                    'minutes_until_expiry' => $token->minutesUntilExpiry(),
                    'connected_at' => $token->connected_at?->toISOString()
                ];
            });
        } catch (\Exception $e) {
            $status['tokens'] = [];
        }
        
        return $status;
    }
    
    /**
     * Test invoice sending capability
     */
    public function testInvoiceSending(): array
    {
        try {
            $validation = $this->validateIntegration();
            
            if ($validation['status'] !== 'success') {
                return [
                    'success' => false,
                    'message' => 'Integration not properly configured',
                    'issues' => $validation['issues']
                ];
            }
            
            // Create a test invoice data structure
            $testInvoice = (object) [
                'id' => 'test',
                'invoice_number' => 'TEST-001',
                'total' => 100.00,
                'status' => 'DRAFT',
                'xeroId' => null
            ];
            
            // This would test the actual invoice sending logic
            // For now, just validate the integration is ready
            return [
                'success' => true,
                'message' => 'Integration ready for invoice sending',
                'test_invoice' => $testInvoice
            ];
            
        } catch (\Exception $e) {
            return [
                'success' => false,
                'message' => 'Test failed: ' . $e->getMessage(),
                'error' => $e->getMessage()
            ];
        }
    }
} 