<?php

namespace App\Http\Controllers;

use App\Models\PaymentLog;
use App\Services\PaymentConfigurationService as ConfigurationService;
use App\Services\PaymentProvider;
use App\Services\PaymentService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

/**
 * PaymentConfigurationController
 * 
 * Handles all payment configuration management operations.
 * Provides dashboard, CRUD operations, connection testing, and logging views.
 * All access is restricted to Super Manager role as per requirements.
 * 
 * @package PaymentConfigurationModule
 * @author SSHIA Development Team
 */
class PaymentConfigurationController extends Controller
{
    /**
     * Configuration service instance.
     *
     * @var ConfigurationService
     */
    protected ConfigurationService $configService;

    /**
     * Payment provider instance.
     *
     * @var PaymentProvider
     */
    protected PaymentProvider $provider;

    /**
     * Payment service instance.
     *
     * @var PaymentService
     */
    protected PaymentService $paymentService;

    /**
     * Create a new controller instance.
     *
     * @param ConfigurationService $configService
     * @param PaymentProvider $provider
     * @param PaymentService $paymentService
     */
    public function __construct(
        ConfigurationService $configService,
        PaymentProvider $provider,
        PaymentService $paymentService
    ) {
        $this->configService = $configService;
        $this->provider = $provider;
        $this->paymentService = $paymentService;
    }

    /**
     * Display the payment configuration dashboard.
     * 
     * Shows configuration status, statistics, and recent logs.
     *
     * @return \Illuminate\View\View
     */
    public function index()
    {
        // Permission check - Super Manager only
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can access payment configuration.');

        // Get configuration status
        $configuration = $this->configService->getConfiguration();
        $statusSummary = $this->configService->getStatusSummary();
        $maskedConfig = $this->configService->getMaskedConfiguration();

        // Get recent logs for dashboard
        $recentLogs = PaymentLog::latest()
            ->limit(5)
            ->get();

        // Get log statistics
        $logStats = PaymentLog::getStatistics();

        // Get today's statistics
        $todayStats = [
            'total' => PaymentLog::today()->count(),
            'successful' => PaymentLog::today()->successful()->count(),
            'failed' => PaymentLog::today()->failed()->count(),
        ];

        return view('config.payment.index', compact(
            'configuration',
            'statusSummary',
            'maskedConfig',
            'recentLogs',
            'logStats',
            'todayStats'
        ));
    }

    /**
     * Show the form for creating a new configuration.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can create payment configuration.');

        // Check if configuration already exists
        $existingConfig = $this->configService->getConfiguration();

        return view('config.payment.form', [
            'configuration' => $existingConfig,
            'isEdit' => $existingConfig !== null,
        ]);
    }

    /**
     * Store a newly created configuration in storage.
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can create payment configuration.');

        // Validate input
        $validated = $request->validate([
            'collection_api_user' => 'nullable|string|max:191',
            'collection_api_key' => 'nullable|string|max:500',
            'collection_subscription_key' => 'nullable|string|max:191',
            'disbursement_api_user' => 'nullable|string|max:191',
            'disbursement_api_key' => 'nullable|string|max:500',
            'disbursement_subscription_key' => 'nullable|string|max:191',
            'environment' => 'required|in:sandbox,production',
            'currency' => 'required|in:SSP,USD',
        ], [
            'environment.required' => 'Please select an environment.',
            'environment.in' => 'Environment must be sandbox or production.',
            'currency.required' => 'Please select a payment currency.',
            'currency.in' => 'Currency must be SSP or USD.',
        ]);

        // XSS Prevention - sanitize text inputs
        foreach ($validated as $key => $value) {
            if (is_string($value)) {
                $validated[$key] = strip_tags($value);
            }
        }

        // Validate that at least one API type is configured
        $hasCollection = !empty($validated['collection_api_user']) 
            && !empty($validated['collection_api_key']) 
            && !empty($validated['collection_subscription_key']);

        $hasDisbursement = !empty($validated['disbursement_api_user']) 
            && !empty($validated['disbursement_api_key']) 
            && !empty($validated['disbursement_subscription_key']);

        if (!$hasCollection && !$hasDisbursement) {
            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['error' => 'Please configure at least Collection or Disbursement API credentials.']);
        }

        try {
            $configuration = $this->configService->saveConfiguration($validated);

            Log::info('Payment configuration saved', [
                'user_id' => auth()->id(),
                'environment' => $configuration->environment,
            ]);

            return redirect()
                ->route('config.payment.index')
                ->with('success', 'Payment configuration saved successfully!');

        } catch (\Exception $e) {
            Log::error('Failed to save payment configuration', [
                'error' => $e->getMessage(),
                'user_id' => auth()->id(),
            ]);

            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['error' => 'Failed to save configuration: ' . $e->getMessage()]);
        }
    }

    /**
     * Show the form for editing the configuration.
     *
     * @return \Illuminate\View\View
     */
    public function edit()
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can edit payment configuration.');

        $configuration = $this->configService->getConfiguration();

        if (!$configuration) {
            return redirect()
                ->route('config.payment.create')
                ->with('info', 'No configuration found. Please create one.');
        }

        return view('config.payment.form', [
            'configuration' => $configuration,
            'isEdit' => true,
        ]);
    }

    /**
     * Update the configuration in storage.
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Request $request)
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can update payment configuration.');

        // Validate input
        $validated = $request->validate([
            'collection_api_user' => 'nullable|string|max:191',
            'collection_api_key' => 'nullable|string|max:500',
            'collection_subscription_key' => 'nullable|string|max:191',
            'disbursement_api_user' => 'nullable|string|max:191',
            'disbursement_api_key' => 'nullable|string|max:500',
            'disbursement_subscription_key' => 'nullable|string|max:191',
            'environment' => 'required|in:sandbox,production',
            'currency' => 'required|in:SSP,USD',
        ]);

        // XSS Prevention
        foreach ($validated as $key => $value) {
            if (is_string($value)) {
                $validated[$key] = strip_tags($value);
            }
        }

        try {
            $configuration = $this->configService->saveConfiguration($validated);

            Log::info('Payment configuration updated', [
                'user_id' => auth()->id(),
                'environment' => $configuration->environment,
            ]);

            return redirect()
                ->route('config.payment.index')
                ->with('success', 'Payment configuration updated successfully!');

        } catch (\Exception $e) {
            Log::error('Failed to update payment configuration', [
                'error' => $e->getMessage(),
                'user_id' => auth()->id(),
            ]);

            return redirect()
                ->back()
                ->withInput()
                ->withErrors(['error' => 'Failed to update configuration: ' . $e->getMessage()]);
        }
    }

    /**
     * Test API connection.
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
     */
    public function testConnection(Request $request)
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can test payment connections.');

        $type = $request->input('type', 'collection');

        // Validate type
        if (!in_array($type, ['collection', 'disbursement'])) {
            if ($request->ajax() || $request->wantsJson()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid connection type. Must be collection or disbursement.',
                ], 400);
            }

            return redirect()
                ->back()
                ->withErrors(['error' => 'Invalid connection type.']);
        }

        // Test the connection
        $result = $this->provider->testConnection($type);

        Log::info('Connection test performed', [
            'user_id' => auth()->id(),
            'type' => $type,
            'success' => $result['success'],
        ]);

        if ($request->ajax() || $request->wantsJson()) {
            return response()->json($result);
        }

        if ($result['success']) {
            return redirect()
                ->back()
                ->with('success', $result['message']);
        }

        return redirect()
            ->back()
            ->withErrors(['error' => $result['message']]);
    }

    /**
     * Display API logs.
     *
     * @param Request $request
     * @return \Illuminate\View\View
     */
    public function logs(Request $request)
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can view payment logs.');

        $query = PaymentLog::query()->latest();

        // Filter by type
        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        // Filter by status
        if ($request->filled('status')) {
            if ($request->status === 'success') {
                $query->successful();
            } elseif ($request->status === 'failed') {
                $query->failed();
            }
        }

        // Filter by date range
        if ($request->filled('date_from')) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }
        if ($request->filled('date_to')) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        // Search by reference
        if ($request->filled('search')) {
            $query->where('transaction_reference', 'like', '%' . $request->search . '%');
        }

        $logs = $query->paginate(20)->withQueryString();

        // Get statistics for the view
        $stats = PaymentLog::getStatistics($request->type);

        return view('config.payment.logs', compact('logs', 'stats'));
    }

    /**
     * Display the test interface.
     *
     * @return \Illuminate\View\View
     */
    public function test()
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can access the test interface.');

        $statusSummary = $this->configService->getStatusSummary();
        $serviceStatus = $this->paymentService->getStatus();

        // Get recent test logs
        $testLogs = PaymentLog::tests()
            ->latest()
            ->limit(10)
            ->get();

        return view('config.payment.test', compact(
            'statusSummary',
            'serviceStatus',
            'testLogs'
        ));
    }

    /**
     * Display the integration documentation.
     *
     * @return \Illuminate\View\View
     */
    public function documentation()
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can access payment documentation.');

        $serviceStatus = $this->paymentService->getStatus();

        return view('config.payment.documentation', compact('serviceStatus'));
    }

    /**
     * Delete the configuration.
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy()
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403, 
            'Only Super Managers can delete payment configuration.');

        try {
            $deleted = $this->configService->deleteConfiguration();

            if ($deleted) {
                Log::info('Payment configuration deleted', [
                    'user_id' => auth()->id(),
                ]);

                return redirect()
                    ->route('config.payment.index')
                    ->with('success', 'Payment configuration deleted successfully!');
            }

            return redirect()
                ->route('config.payment.index')
                ->with('info', 'No configuration found to delete.');

        } catch (\Exception $e) {
            Log::error('Failed to delete payment configuration', [
                'error' => $e->getMessage(),
                'user_id' => auth()->id(),
            ]);

            return redirect()
                ->back()
                ->withErrors(['error' => 'Failed to delete configuration: ' . $e->getMessage()]);
        }
    }

    /**
     * Get a single log entry (AJAX).
     *
     * @param PaymentLog $log
     * @return \Illuminate\Http\JsonResponse
     */
    public function showLog(PaymentLog $log)
    {
        // Permission check
        abort_unless(auth()->user()->hasRole('Super Manager'), 403);

        return response()->json([
            'success' => true,
            'log' => [
                'id' => $log->id,
                'type' => $log->type,
                'type_label' => $log->getTypeLabel(),
                'endpoint' => $log->endpoint,
                'request_payload' => $log->request_payload,
                'response_status' => $log->response_status,
                'response_body' => $log->response_body,
                'transaction_reference' => $log->transaction_reference,
                'execution_time_ms' => $log->execution_time_ms,
                'error_message' => $log->error_message,
                'created_at' => $log->created_at->format('Y-m-d H:i:s'),
                'is_successful' => $log->isSuccessful(),
                'status_color' => $log->getStatusColor(),
            ],
        ]);
    }
}
