<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\AuditLog;
use App\Models\Investment;
use App\Models\Investor;
use App\Models\KycDocument;
use App\Services\PaystackService;
use App\Services\ReportService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class AdminController extends Controller
{
    public function __construct(
        protected ReportService $reportService,
        protected PaystackService $paystackService
    ) {}

    /**
     * Get all investments
     * GET /api/admin/investments
     */
    public function investments(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'status' => 'nullable|in:pending_payment,payment_confirmed,agreement_pending,active,completed,cancelled',
            'payment_status' => 'nullable|in:pending,processing,confirmed,failed,refunded',
            'tier' => 'nullable|in:growth,strategic,anchor',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'min_amount' => 'nullable|numeric|min:0',
            'max_amount' => 'nullable|numeric|min:0',
            'search' => 'nullable|string|max:255',
            'per_page' => 'nullable|integer|min:10|max:100',
            'page' => 'nullable|integer|min:1',
        ]);

        $query = Investment::with(['investor', 'paymentTransactions'])
            ->orderByDesc('created_at');

        // Apply filters
        if (!empty($validated['status'])) {
            $query->where('status', $validated['status']);
        }
        if (!empty($validated['payment_status'])) {
            $query->where('payment_status', $validated['payment_status']);
        }
        if (!empty($validated['tier'])) {
            $query->where('investment_tier', $validated['tier']);
        }
        if (!empty($validated['start_date'])) {
            $query->where('created_at', '>=', $validated['start_date']);
        }
        if (!empty($validated['end_date'])) {
            $query->where('created_at', '<=', $validated['end_date'] . ' 23:59:59');
        }
        if (!empty($validated['min_amount'])) {
            $query->where('investment_amount', '>=', $validated['min_amount']);
        }
        if (!empty($validated['max_amount'])) {
            $query->where('investment_amount', '<=', $validated['max_amount']);
        }
        if (!empty($validated['search'])) {
            $search = $validated['search'];
            $query->where(function ($q) use ($search) {
                $q->where('reference', 'like', "%{$search}%")
                    ->orWhere('investor_name', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%");
            });
        }

        $perPage = $validated['per_page'] ?? 20;
        $investments = $query->paginate($perPage);

        return response()->json([
            'success' => true,
            'data' => $investments->items(),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
                'pagination' => [
                    'current_page' => $investments->currentPage(),
                    'last_page' => $investments->lastPage(),
                    'per_page' => $investments->perPage(),
                    'total' => $investments->total(),
                ],
            ],
        ]);
    }

    /**
     * Get single investment
     * GET /api/admin/investment/{id}
     */
    public function investment(string $id): JsonResponse
    {
        $investment = Investment::with([
            'investor',
            'paymentTransactions',
            'dividendPayments',
            'emailLogs',
        ])->findOrFail($id);

        return response()->json([
            'success' => true,
            'data' => [
                'investment' => $investment,
                'expected_roi' => $investment->getExpectedRoi(),
                'expected_returns' => $investment->calculateExpectedReturns(),
            ],
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Update investment
     * PUT /api/admin/investment/{id}
     */
    public function updateInvestment(Request $request, string $id): JsonResponse
    {
        $validated = $request->validate([
            'status' => 'sometimes|in:pending_payment,payment_confirmed,agreement_pending,active,completed,cancelled',
            'notes' => 'sometimes|nullable|string|max:2000',
        ]);

        $investment = Investment::findOrFail($id);
        $oldValues = $investment->only(['status', 'notes']);

        $investment->update($validated);

        // Log the action
        AuditLog::log(
            'investment.update',
            'investment',
            $investment->id,
            $oldValues,
            $validated,
            'Investment updated by admin'
        );

        return response()->json([
            'success' => true,
            'data' => $investment->fresh(),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Process refund
     * POST /api/admin/investment/{id}/refund
     */
    public function refund(Request $request, string $id): JsonResponse
    {
        $validated = $request->validate([
            'reason' => 'nullable|string|max:500',
        ]);

        $investment = Investment::findOrFail($id);

        // Check if can be refunded
        if ($investment->payment_status !== 'confirmed') {
            return response()->json([
                'error' => true,
                'message' => 'Only confirmed payments can be refunded',
                'code' => 'CANNOT_REFUND',
            ], 400);
        }

        $transaction = $investment->paymentTransactions()->successful()->first();

        if (!$transaction) {
            return response()->json([
                'error' => true,
                'message' => 'No successful transaction found',
                'code' => 'NO_TRANSACTION',
            ], 400);
        }

        $result = $this->paystackService->initiateRefund($transaction, $validated['reason'] ?? null);

        if (!$result['success']) {
            return response()->json([
                'error' => true,
                'message' => $result['message'],
                'code' => 'REFUND_FAILED',
            ], 400);
        }

        // Log the action
        AuditLog::log(
            'investment.refund',
            'investment',
            $investment->id,
            [],
            ['reason' => $validated['reason'] ?? null],
            'Refund processed by admin'
        );

        return response()->json([
            'success' => true,
            'data' => [
                'investment' => $investment->fresh(),
                'refund' => $result['data'],
            ],
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Get dashboard statistics
     * GET /api/admin/dashboard-stats
     */
    public function dashboardStats(): JsonResponse
    {
        $stats = $this->reportService->getDashboardStats();

        return response()->json([
            'success' => true,
            'data' => $stats,
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Get CEO Dashboard statistics
     * GET /api/admin/ceo-dashboard
     */
    public function ceoDashboard(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'period' => 'string|in:week,month,quarter,year',
        ]);

        $period = $validated['period'] ?? 'month';
        $cacheKey = "ceo_dashboard_stats_{$period}";

        // Cache for 10 minutes
        $stats = \Illuminate\Support\Facades\Cache::remember($cacheKey, 600, function () use ($period) {
            return $this->reportService->getCeoDashboardStats($period);
        });

        return response()->json([
            'success' => true,
            'data' => $stats,
            'meta' => [
                'timestamp' => now()->toIso8601String(),
                'period' => $period,
                'cached' => true,
            ],
        ]);
    }

    /**
     * Get all investors
     * GET /api/admin/investors
     */
    public function investors(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'kyc_status' => 'nullable|in:not_started,pending,approved,rejected',
            'search' => 'nullable|string|max:255',
            'per_page' => 'nullable|integer|min:10|max:100',
        ]);

        $query = Investor::withCount('investments')
            ->orderByDesc('created_at');

        if (!empty($validated['kyc_status'])) {
            $query->where('kyc_status', $validated['kyc_status']);
        }

        if (!empty($validated['search'])) {
            $search = $validated['search'];
            $query->where(function ($q) use ($search) {
                $q->where('full_name', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%");
            });
        }

        $perPage = $validated['per_page'] ?? 20;
        $investors = $query->paginate($perPage);

        return response()->json([
            'success' => true,
            'data' => $investors->items(),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
                'pagination' => [
                    'current_page' => $investors->currentPage(),
                    'last_page' => $investors->lastPage(),
                    'per_page' => $investors->perPage(),
                    'total' => $investors->total(),
                ],
            ],
        ]);
    }

    /**
     * Get pending KYC documents
     * GET /api/admin/kyc/pending
     */
    public function pendingKyc(): JsonResponse
    {
        $documents = KycDocument::with(['investor'])
            ->pending()
            ->orderBy('created_at')
            ->get();

        return response()->json([
            'success' => true,
            'data' => $documents,
            'meta' => [
                'timestamp' => now()->toIso8601String(),
                'count' => $documents->count(),
            ],
        ]);
    }

    /**
     * Get audit logs
     * GET /api/admin/audit-logs
     */
    public function auditLogs(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'action' => 'nullable|string',
            'entity_type' => 'nullable|string',
            'admin_user_id' => 'nullable|uuid',
            'per_page' => 'nullable|integer|min:10|max:100',
        ]);

        $query = AuditLog::with('adminUser')
            ->orderByDesc('created_at');

        if (!empty($validated['action'])) {
            $query->forAction($validated['action']);
        }
        if (!empty($validated['entity_type'])) {
            $query->forEntity($validated['entity_type']);
        }
        if (!empty($validated['admin_user_id'])) {
            $query->byAdmin($validated['admin_user_id']);
        }

        $perPage = $validated['per_page'] ?? 50;
        $logs = $query->paginate($perPage);

        return response()->json([
            'success' => true,
            'data' => $logs->items(),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
                'pagination' => [
                    'current_page' => $logs->currentPage(),
                    'last_page' => $logs->lastPage(),
                    'per_page' => $logs->perPage(),
                    'total' => $logs->total(),
                ],
            ],
        ]);
    }

    /**
     * Create a new investor
     * POST /api/admin/investors
     */
    public function createInvestor(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'email' => 'required|email|unique:investors,email',
            'full_name' => 'required|string|max:255',
            'phone' => 'nullable|string|max:50',
            'country' => 'nullable|string|max:100',
            'investor_type' => 'nullable|in:individual,company,fund,family_office,institution',
            'kyc_status' => 'nullable|in:not_started,pending,approved,rejected',
            'risk_profile' => 'nullable|in:conservative,moderate,aggressive',
            'dashboard_access' => 'nullable|boolean',
        ]);

        $validated['email'] = strtolower($validated['email']);
        $validated['investor_type'] = $validated['investor_type'] ?? 'individual';
        $validated['kyc_status'] = $validated['kyc_status'] ?? 'not_started';

        $investor = Investor::create($validated);

        // Log the action
        AuditLog::log(
            'investor.create',
            'investor',
            $investor->id,
            [],
            $validated,
            'Investor created by admin'
        );

        return response()->json([
            'success' => true,
            'data' => $investor,
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ], 201);
    }

    /**
     * Get single investor with investments
     * GET /api/admin/investor/{id}
     */
    public function investor(string $id): JsonResponse
    {
        $investor = Investor::with([
            'investments' => function ($query) {
                $query->orderByDesc('created_at');
            },
            'investments.paymentTransactions',
            'kycDocuments',
            'dividendPayments',
        ])->findOrFail($id);

        // Calculate summary stats
        $totalInvested = $investor->investments
            ->where('payment_status', 'confirmed')
            ->sum('investment_amount');
        
        $activeInvestments = $investor->investments
            ->whereIn('status', ['payment_confirmed', 'agreement_pending', 'active'])
            ->count();

        return response()->json([
            'success' => true,
            'data' => [
                'investor' => $investor,
                'summary' => [
                    'total_invested' => $totalInvested,
                    'active_investments' => $activeInvestments,
                    'total_investments' => $investor->investments->count(),
                ],
            ],
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Update an investor
     * PUT /api/admin/investor/{id}
     */
    public function updateInvestor(Request $request, string $id): JsonResponse
    {
        $investor = Investor::findOrFail($id);

        $validated = $request->validate([
            'email' => 'sometimes|email|unique:investors,email,' . $investor->id,
            'full_name' => 'sometimes|string|max:255',
            'phone' => 'sometimes|nullable|string|max:50',
            'country' => 'sometimes|nullable|string|max:100',
            'investor_type' => 'sometimes|in:individual,company,fund,family_office,institution',
            'kyc_status' => 'sometimes|in:not_started,pending,approved,rejected',
            'risk_profile' => 'sometimes|nullable|in:conservative,moderate,aggressive',
            'dashboard_access' => 'sometimes|boolean',
            'pep_status' => 'sometimes|boolean',
            'sanctions_checked' => 'sometimes|boolean',
        ]);

        if (isset($validated['email'])) {
            $validated['email'] = strtolower($validated['email']);
        }

        $oldValues = $investor->only(array_keys($validated));
        $investor->update($validated);

        // Log the action
        AuditLog::log(
            'investor.update',
            'investor',
            $investor->id,
            $oldValues,
            $validated,
            'Investor updated by admin'
        );

        return response()->json([
            'success' => true,
            'data' => $investor->fresh(),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Delete an investor
     * DELETE /api/admin/investor/{id}
     */
    public function deleteInvestor(string $id): JsonResponse
    {
        $investor = Investor::findOrFail($id);

        // Check for active investments
        $activeCount = $investor->investments()
            ->whereIn('status', ['payment_confirmed', 'agreement_pending', 'active'])
            ->count();

        if ($activeCount > 0) {
            return response()->json([
                'error' => true,
                'message' => 'Cannot delete investor with active investments',
                'code' => 'HAS_ACTIVE_INVESTMENTS',
                'data' => [
                    'active_investments_count' => $activeCount,
                ],
            ], 400);
        }

        // Log before deletion
        AuditLog::log(
            'investor.delete',
            'investor',
            $investor->id,
            $investor->toArray(),
            [],
            'Investor deleted by admin'
        );

        $investor->delete();

        return response()->json([
            'success' => true,
            'message' => 'Investor deleted successfully',
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * Create a new investment (admin bypass for manual entry)
     * POST /api/admin/investments
     * 
     * Share price: $100 per share
     */
    public const SHARE_PRICE = 100;

    public function createInvestment(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'investor_id' => 'required|uuid|exists:investors,id',
            'investment_tier' => 'required|in:growth,strategic,anchor',
            'shares' => 'required_without:investment_amount|nullable|integer|min:1',
            'investment_amount' => 'required_without:shares|nullable|numeric|min:0',
            'currency' => 'nullable|in:USD,KES',
            'investment_term' => 'nullable|integer|min:1|max:10',
            'status' => 'nullable|in:pending_payment,payment_confirmed,agreement_pending,active,completed,cancelled',
            'payment_status' => 'nullable|in:pending,processing,confirmed,failed,refunded',
            'notes' => 'nullable|string|max:2000',
        ]);

        $investor = Investor::findOrFail($validated['investor_id']);

        // Calculate shares and amount - shares take priority
        if (isset($validated['shares']) && $validated['shares'] > 0) {
            $shares = $validated['shares'];
            $amount = $shares * self::SHARE_PRICE;
        } else {
            $amount = $validated['investment_amount'];
            $shares = (int) floor($amount / self::SHARE_PRICE);
        }

        $investmentData = [
            'reference' => Investment::generateReference(),
            'investor_id' => $investor->id,
            'investor_name' => $investor->full_name,
            'email' => $investor->email,
            'phone' => $investor->phone,
            'country' => $investor->country,
            'investor_type' => $investor->investor_type,
            'investment_tier' => $validated['investment_tier'],
            'investment_amount' => $amount,
            'shares' => $shares,
            'share_price' => self::SHARE_PRICE,
            'currency' => $validated['currency'] ?? 'USD',
            'investment_term' => $validated['investment_term'] ?? 1,
            'status' => $validated['status'] ?? 'active',
            'payment_status' => $validated['payment_status'] ?? 'confirmed',
            'notes' => $validated['notes'] ?? 'Created by admin',
            'terms_accepted' => true,
            'memorandum_read' => true,
            'risks_understood' => true,
            'risk_tolerance_confirmed' => true,
        ];

        // Set payment_completed_at if payment is confirmed
        if (($validated['payment_status'] ?? 'confirmed') === 'confirmed') {
            $investmentData['payment_completed_at'] = now();
        }

        $investment = Investment::create($investmentData);

        // Update investor aggregates
        $investor->updateAggregates();

        // Log the action
        AuditLog::log(
            'investment.create',
            'investment',
            $investment->id,
            [],
            $investmentData,
            'Investment created by admin'
        );

        return response()->json([
            'success' => true,
            'data' => $investment->load('investor'),
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ], 201);
    }

    /**
     * Delete an investment
     * DELETE /api/admin/investment/{id}
     */
    public function deleteInvestment(string $id): JsonResponse
    {
        $investment = Investment::findOrFail($id);

        // Only allow deletion of non-active investments or with override
        if (in_array($investment->status, ['active']) && $investment->payment_status === 'confirmed') {
            return response()->json([
                'error' => true,
                'message' => 'Cannot delete an active investment with confirmed payment. Cancel or refund first.',
                'code' => 'CANNOT_DELETE_ACTIVE',
            ], 400);
        }

        $investor = $investment->investor;

        // Log before deletion
        AuditLog::log(
            'investment.delete',
            'investment',
            $investment->id,
            $investment->toArray(),
            [],
            'Investment deleted by admin'
        );

        $investment->delete();

        // Update investor aggregates if investor exists
        if ($investor) {
            $investor->updateAggregates();
        }

        return response()->json([
            'success' => true,
            'message' => 'Investment deleted successfully',
            'meta' => [
                'timestamp' => now()->toIso8601String(),
            ],
        ]);
    }
}
