<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\Policy;
use App\Models\Session;
use App\Models\Wallet;
use App\Models\WalletTransaction;
use App\Traits\ApiResponse;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use OpenApi\Attributes as OA;

class SessionController extends Controller
{
    use ApiResponse;

    /**
     * Start a PAYG session
     */
    #[OA\Post(
        path: '/api/v1/sessions/start',
        summary: 'Start PAYG session',
        description: 'Start a new Pay-As-You-Go insurance session. Requires active PAYG policy and minimum wallet balance of £10.',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['policy_id'],
                properties: [
                    new OA\Property(property: 'policy_id', type: 'integer', example: 1),
                ]
            )
        ),
        responses: [
            new OA\Response(
                response: 201,
                description: 'Session started successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                        new OA\Property(property: 'message', type: 'string', example: 'Session started successfully'),
                    ]
                )
            ),
            new OA\Response(
                response: 400,
                description: 'Bad request',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'You already have an active session'),
                    ]
                )
            ),
            new OA\Response(
                response: 404,
                description: 'Active PAYG policy not found',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Active PAYG policy not found'),
                    ]
                )
            ),
            new OA\Response(
                response: 422,
                description: 'Validation error',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Validation failed'),
                        new OA\Property(property: 'errors', type: 'object'),
                    ]
                )
            ),
        ]
    )]
    public function start(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'policy_id' => 'required|exists:policies,id',
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator->errors());
        }

        $user = $request->user();
        $policy = Policy::where('id', $request->policy_id)
            ->where('user_id', $user->id)
            ->where('product_type', 'PAYG')
            ->where('status', 'active')
            ->first();

        if (!$policy) {
            return $this->notFoundResponse('Active PAYG policy not found');
        }

        // Check for active session
        $activeSession = Session::where('user_id', $user->id)
            ->where('status', 'active')
            ->first();

        if ($activeSession) {
            return $this->errorResponse('You already have an active session');
        }

        // Check wallet balance (minimum £10)
        $wallet = $user->wallet;
        if (!$wallet) {
            $wallet = Wallet::create(['user_id' => $user->id, 'balance' => 0]);
        }

        if ($wallet->balance < 10) {
            return $this->errorResponse('Insufficient balance. Minimum balance of £10 required', null, 400);
        }

        $session = Session::create([
            'policy_id' => $policy->id,
            'user_id' => $user->id,
            'started_at' => now(),
            'status' => 'active',
            'hourly_rate' => 1.20, // Default rate
        ]);

        return $this->successResponse($session, 'Session started successfully', 201);
    }

    /**
     * Stop a PAYG session
     */
    #[OA\Post(
        path: '/api/v1/sessions/{id}/stop',
        summary: 'Stop PAYG session',
        description: 'Stop an active PAYG session and calculate the cost based on duration',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        parameters: [
            new OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), example: 1),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Session stopped successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object', properties: [
                            new OA\Property(property: 'cost', type: 'number', example: 2.40),
                            new OA\Property(property: 'duration_minutes', type: 'integer', example: 120),
                        ]),
                        new OA\Property(property: 'message', type: 'string', example: 'Session stopped successfully'),
                    ]
                )
            ),
            new OA\Response(
                response: 404,
                description: 'Active session not found',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Active session not found'),
                    ]
                )
            ),
        ]
    )]
    public function stop(Request $request, string $id): JsonResponse
    {
        $session = Session::where('id', $id)
            ->where('user_id', $request->user()->id)
            ->where('status', 'active')
            ->first();

        if (!$session) {
            return $this->notFoundResponse('Active session not found');
        }

        DB::transaction(function () use ($session) {
            $endedAt = now();
            $startedAt = $session->started_at;
            $durationMinutes = $startedAt->diffInMinutes($endedAt);
            $durationHours = $durationMinutes / 60;
            $cost = round($durationHours * $session->hourly_rate, 2);

            $session->update([
                'ended_at' => $endedAt,
                'status' => 'completed',
                'duration_minutes' => $durationMinutes,
                'cost' => $cost,
            ]);

            // Deduct from wallet
            $wallet = $session->user->wallet;
            $balanceBefore = $wallet->balance;
            $balanceAfter = $balanceBefore - $cost;

            $wallet->update(['balance' => max(0, $balanceAfter)]);

            // Create transaction
            WalletTransaction::create([
                'wallet_id' => $wallet->id,
                'user_id' => $session->user_id,
                'session_id' => $session->id,
                'type' => 'payment',
                'amount' => $cost,
                'balance_before' => $balanceBefore,
                'balance_after' => $wallet->balance,
                'status' => 'completed',
                'description' => "PAYG session payment - {$durationMinutes} minutes",
            ]);
        });

        $session->refresh();

        return $this->successResponse($session, 'Session stopped successfully');
    }

    /**
     * Get active session
     */
    #[OA\Get(
        path: '/api/v1/sessions/active',
        summary: 'Get active session',
        description: 'Retrieve the current active PAYG session with real-time cost calculation',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Active session retrieved successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object', nullable: true, properties: [
                            new OA\Property(property: 'current_cost', type: 'number', example: 1.20),
                            new OA\Property(property: 'duration_minutes', type: 'integer', example: 60),
                        ]),
                        new OA\Property(property: 'message', type: 'string', example: 'Active session retrieved successfully'),
                    ]
                )
            ),
        ]
    )]
    public function active(Request $request): JsonResponse
    {
        $session = Session::where('user_id', $request->user()->id)
            ->where('status', 'active')
            ->with(['policy', 'policy.vehicle'])
            ->first();

        if (!$session) {
            return $this->successResponse(null, 'No active session');
        }

        // Calculate current cost
        $durationMinutes = $session->started_at->diffInMinutes(now());
        $durationHours = $durationMinutes / 60;
        $currentCost = round($durationHours * $session->hourly_rate, 2);

        $session->current_cost = $currentCost;
        $session->duration_minutes = $durationMinutes;

        return $this->successResponse($session, 'Active session retrieved successfully');
    }

    /**
     * Display a listing of sessions
     */
    #[OA\Get(
        path: '/api/v1/sessions',
        summary: 'List all sessions',
        description: 'Retrieve paginated list of all PAYG sessions for the authenticated user',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Sessions retrieved successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object', properties: [
                            new OA\Property(property: 'data', type: 'array', items: new OA\Items(type: 'object')),
                            new OA\Property(property: 'current_page', type: 'integer'),
                            new OA\Property(property: 'total', type: 'integer'),
                        ]),
                        new OA\Property(property: 'message', type: 'string', example: 'Sessions retrieved successfully'),
                    ]
                )
            ),
        ]
    )]
    public function index(Request $request): JsonResponse
    {
        $sessions = Session::where('user_id', $request->user()->id)
            ->with(['policy', 'policy.vehicle'])
            ->orderBy('created_at', 'desc')
            ->paginate(20);

        return $this->successResponse($sessions, 'Sessions retrieved successfully');
    }

    /**
     * Display the specified session
     */
    #[OA\Get(
        path: '/api/v1/sessions/{id}',
        summary: 'Get session details',
        description: 'Retrieve details of a specific PAYG session',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        parameters: [
            new OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), example: 1),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Session retrieved successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                        new OA\Property(property: 'message', type: 'string', example: 'Session retrieved successfully'),
                    ]
                )
            ),
            new OA\Response(
                response: 404,
                description: 'Session not found',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Session not found'),
                    ]
                )
            ),
        ]
    )]
    public function show(Request $request, string $id): JsonResponse
    {
        $session = Session::where('id', $id)
            ->where('user_id', $request->user()->id)
            ->with(['policy', 'policy.vehicle'])
            ->first();

        if (!$session) {
            return $this->notFoundResponse('Session not found');
        }

        return $this->successResponse($session, 'Session retrieved successfully');
    }

    /**
     * Update location for active session
     */
    #[OA\Post(
        path: '/api/v1/sessions/{id}/location',
        summary: 'Update session location',
        description: 'Update location data for an active PAYG session',
        tags: ['Sessions'],
        security: [['sanctum' => []]],
        parameters: [
            new OA\Parameter(name: 'id', in: 'path', required: true, schema: new OA\Schema(type: 'integer'), example: 1),
        ],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['latitude', 'longitude'],
                properties: [
                    new OA\Property(property: 'latitude', type: 'number', format: 'float', example: 51.5074),
                    new OA\Property(property: 'longitude', type: 'number', format: 'float', example: -0.1278),
                ]
            )
        ),
        responses: [
            new OA\Response(
                response: 200,
                description: 'Location updated successfully',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                        new OA\Property(property: 'message', type: 'string', example: 'Location updated successfully'),
                    ]
                )
            ),
            new OA\Response(
                response: 404,
                description: 'Active session not found',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Active session not found'),
                    ]
                )
            ),
            new OA\Response(
                response: 422,
                description: 'Validation error',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: false),
                        new OA\Property(property: 'message', type: 'string', example: 'Validation failed'),
                        new OA\Property(property: 'errors', type: 'object'),
                    ]
                )
            ),
        ]
    )]
    public function updateLocation(Request $request, string $id): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        if ($validator->fails()) {
            return $this->validationErrorResponse($validator->errors());
        }

        $session = Session::where('id', $id)
            ->where('user_id', $request->user()->id)
            ->where('status', 'active')
            ->first();

        if (!$session) {
            return $this->notFoundResponse('Active session not found');
        }

        $locationData = $session->location_data ?? [];
        $locationData[] = [
            'latitude' => $request->latitude,
            'longitude' => $request->longitude,
            'timestamp' => now()->toIso8601String(),
        ];

        $session->update(['location_data' => $locationData]);

        return $this->successResponse($session, 'Location updated successfully');
    }
}
