<?php

namespace App\Http\Controllers;

use App\Services\AlarmService;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Exception;
use App\Models\Device;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use App\Services\AdminService;
use Tymon\JWTAuth\Facades\JWTAuth;

class AlarmControllerCommon extends Controller
{
    protected $alarmService;

    public function __construct(AlarmService $alarmService)
    {
        $this->alarmService = $alarmService;
    }

    public function createOrUpdateAlarm(Request $request)
    {
        try {

            $alarmData = [
                'type'       => $request->type ?? null,
                'severity'       => $request->severity ?? null,
                'acknowledged'      => false,
                'cleared'    => false,
                'startTs'    => $request->startTs ?? Carbon::now()->timestamp,
                'endTs'    => $request->endTs ?? Carbon::now()->timestamp,
                'details' => $request->details ?? [],
                'propagate'    => true,
                'propagateToOwner'    => true,
                'propagateToTenant'    => true,
                'originator'    => $request->originator ?? 1,
                // 'assigneeId'    => $request->assigneeId ?? 1,
            ];

            // Handle updating existing alarm
            if (!empty($request->id)) {
                $alarmData['id'] = $request->id;
            }

            // Call Service to create/update device
            $apiResponse = $this->alarmService->createOrUpdateAlarm($alarmData);


            return jsonResponseWithSuccessMessage(
                !empty($request->id) ? 'Alarm updated successfully' : 'Alarm created successfully',
                ['api_response' => $apiResponse]
            );
        } catch (Exception $e) {
            Log::error("Error: " . $e->getMessage());

            $errorResponse = json_decode($e->getMessage(), true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return jsonResponseWithErrorMessage($errorResponse['message'] ?? 'Something went wrong', 400, $errorResponse);
            }

            return jsonResponseWithErrorMessage($e->getMessage(), 500);
        }
    }

    public function getAlarmById($id)
    {
        try {
            $token = app('App\Services\AdminService')->getToken();  // Fetch cached token
            $url = env('THINGSBOARD_URL') . "api/alarm/{$id}";

            $response = Http::withHeaders([
                'X-Authorization' => 'Bearer ' . $token,
                'accept' => 'application/json',
            ])->get($url);

            if ($response->successful()) {
                $responseData = $response->json();

                $data = $responseData['data'] ?? $responseData ?? [];

                if (empty($data)) {
                    return jsonResponseWithErrorMessage('No data found for the provided ID', 404);
                }
                $filteredData = [
                    'originator' => $data['originator'] ?? null,
                    'severity'   => $data['severity'] ?? null,
                    'startTs'    => $data['startTs'] ?? null,
                    'type'       => $data['type'] ?? null,
                    'status'     => $data['status'] ?? null,
                    'assignee'   => $data['assigneeId'] ?? null,
                ];

                return jsonResponseWithSuccessMessage('Alarm data fetched successfully', $filteredData);
            }
            return jsonResponseWithErrorMessage('Failed to fetch alarm data: ' . $response->body(), $response->status());
        } catch (\Exception $e) {
            return jsonResponseWithErrorMessage('An error occurred while fetching the alarm: ' . $e->getMessage(), 500);
        }
    }

    public function acknowledgeAlarmById($id)
    {
        try {
            $token = app('App\Services\AdminService')->getToken();  // Fetch cached token0
            $url = env('THINGSBOARD_URL') . "api/alarm/{$id}";

            $getResponse = Http::withHeaders([
                'X-Authorization' => 'Bearer ' . $token,
                'accept' => 'application/json',
            ])->get($url);

            if (!$getResponse->successful()) {
                return jsonResponseWithErrorMessage('Failed to fetch alarm: ' . $getResponse->body(), $getResponse->status());
            }

            $alarmData = $getResponse->json();

            if ($alarmData['acknowledged'] ?? false) {
                return jsonResponseWithSuccessMessage('Alarm is already acknowledged', [
                    'id' => $alarmData['id']['id'] ?? $id,
                    'acknowledged' => true,
                    'ackTs' => $alarmData['ackTs'] ?? null,
                    'status' => $alarmData['status'] ?? 'UNKNOWN'
                ]);
            }

            $ackUrl = env('THINGSBOARD_URL') . "api/alarm/{$id}/ack";

            $ackResponse = Http::withHeaders([
                'X-Authorization' => 'Bearer ' . $token,
                'accept' => 'application/json',
            ])->post($ackUrl);

            if ($ackResponse->successful()) {
                $ackData = $ackResponse->json();

                return jsonResponseWithSuccessMessage('Alarm acknowledged successfully', [
                    'id' => $ackData['id']['id'] ?? $id,
                    'acknowledged' => $ackData['acknowledged'] ?? true,
                    'ackTs' => $ackData['ackTs'] ?? now()->timestamp,
                    'status' => $ackData['status'] ?? 'ACTIVE_ACK'
                ]);
            }



            return jsonResponseWithErrorMessage('Failed to acknowledge alarm: ' . $ackResponse->body(), $ackResponse->status());
        } catch (\Exception $e) {
            return jsonResponseWithErrorMessage('An error occurred: ' . $e->getMessage(), 500);
        }
    }

    public function clearAlarmById($id)
    {
        try {
            $token = app(AdminService::class)->getToken(); // Fetch cached token
            $url = env('THINGSBOARD_URL') . "api/alarm/{$id}";

            // Fetch the alarm details first
            $getResponse = Http::withHeaders([
                'X-Authorization' => 'Bearer ' . $token,
                'accept' => 'application/json',
            ])->get($url);

            if (!$getResponse->successful()) {
                return jsonResponseWithErrorMessage('Failed to fetch alarm: ' . $getResponse->body(), $getResponse->status());
            }

            $alarmData = $getResponse->json();

            if ($alarmData['cleared'] ?? false) {
                return jsonResponseWithSuccessMessage('Alarm is already cleared', [
                    'id' => $alarmData['id']['id'] ?? $id,
                    'cleared' => true,
                    'clearTs' => $alarmData['clearTs'] ?? null,
                    'status' => $alarmData['status'] ?? 'UNKNOWN'
                ]);
            }

            // Clear the alarm
            $clearUrl = env('THINGSBOARD_URL') . "api/alarm/{$id}/clear";
            $clearResponse = Http::withHeaders([
                'X-Authorization' => 'Bearer ' . $token,
                'accept' => 'application/json',
            ])->post($clearUrl);

            if ($clearResponse->successful()) {
                $clearData = $clearResponse->json();

                return jsonResponseWithSuccessMessage('Alarm cleared successfully', [
                    'id' => $clearData['id']['id'] ?? $id,
                    'cleared' => $clearData['cleared'] ?? true,
                    'clearTs' => $clearData['clearTs'] ?? now()->timestamp,
                    'status' => $clearData['status'] ?? 'CLEARED'
                ]);
            }


            return jsonResponseWithErrorMessage('Failed to clear alarm: ' . $clearResponse->body(), $clearResponse->status());
        } catch (\Exception $e) {
            Log::error('Error clearing alarm: ' . $e->getMessage());
            return jsonResponseWithErrorMessage('An error occurred: ' . $e->getMessage(), 500);
        }
    }



    public function filterAlarm(Request $request)
    {
        try {
            // dd('alarm');
            $alarmData = $request->only([
                'severity',
                'pageSize',
                'page',
                'startTs',
                'endTs',
                'deviceId',
                'assetId',
                'assignId',
            ]);

            $apiResponse = $this->alarmService->filterAlarm($alarmData);

            return jsonResponseWithSuccessMessage('Alarm data retrieved successfully', ['api_response' => $apiResponse]);
        } catch (Exception $e) {
            Log::error("Error: " . $e->getMessage());

            $errorResponse = json_decode($e->getMessage(), true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return jsonResponseWithErrorMessage($errorResponse['message'] ?? 'Something went wrong', 400, $errorResponse);
            }

            return jsonResponseWithErrorMessage($e->getMessage(), 500);
        }
    }


    public function getDeviceAlarms(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'device_id' => 'required|string',
            'pageSize'  => 'nullable|integer',
            'page'      => 'nullable|integer',
        ]);

        // Handle validation failure
        if ($validator->fails()) {
            return response()->json(['error' => $validator->errors()->first()], 400);
        }

        // Get the device ID from the request
        $deviceId = $request->input('device_id');
        $pageSize = $request->input('pageSize', 1000);
        $page = $request->input('page', 0);

        // Fetch ThingsBoard token
        $token = $this->alarmService->getToken();

        if (!$token) {
            return response()->json(['error' => 'Failed to fetch ThingsBoard token'], 401);
        }

        $baseUrl = env('THINGSBOARD_URL');

        // Get timestamps for the past 24 hours
        $endTime = now()->timestamp * 1000;                         // Current time in ms
        $startTime = now()->subHours(24)->timestamp * 1000;         // 24 hours ago in ms

        // Fetch alarms from ThingsBoard API
        $response = Http::withHeaders([
            'Authorization' => "Bearer $token",
            'Accept'        => 'application/json',
        ])->get("{$baseUrl}api/v2/alarms", [
            'statusList'   => 'ACTIVE',
            'severityList' => 'CRITICAL,MAJOR,MINOR,WARNING',
            'pageSize'     => $pageSize,
            'page'         => $page,
            'startTime'    => $startTime,
            'endTime'      => $endTime,
            'sortProperty' => 'createdTime',
            'sortOrder'    => 'DESC'
        ]);

        // If the request fails, return an error
        if (!$response->successful()) {
            return response()->json(['error' => 'Failed to fetch alarms'], $response->status());
        }

        $alarms = $response->json()['data'] ?? [];

        // Get the token from the Authorization header
        $token = $request->header('Authorization');
        if ($token) {
            $token = str_replace('Bearer ', '', $token);

            // Decode the token
            try {
                $user = JWTAuth::toUser($token);
            } catch (\Exception $e) {
                return response()->json(['error' => 'Invalid token'], 401);
            }

            if (!$user) {
                return response()->json(['error' => 'User not found in the token'], 401);
            }

            // Retrieve the customer_id from the decoded user
            $customerId = $user->customer_id;
        } else {
            return response()->json(['error' => 'Token not provided'], 400);
        }

        // Alert initialization
        $alert = false;

        // Retrieve the device data to check if it belongs to the logged-in user's customer_id
        $device = Device::find($deviceId);
        if (!$device) {
            return response()->json(['error' => 'Device not found'], 404);
        }

        // Check if the device's customer_id matches the logged-in user's customer_id
        if ($device->customer_id !== $customerId) {
            return response()->json(['error' => 'Device does not belong to the logged-in user\'s customer'], 403);
        }

        // Get device display name
        $deviceDisplayName = $device->display_name;

        // Iterate through the alarms to check if any match the criteria
        foreach ($alarms as $alarm) {
            // Match the device ID with the alarm's originator
            $isDeviceMatch = isset($alarm['originator']['id']) && $alarm['originator']['id'] === $deviceId;

            // Match the assignee user ID with the logged-in user
            $isUserMatch = isset($alarm['assignee']['id']['id']) && $alarm['assignee']['id']['id'] === $user->id;

            // Match the alarm type with the device's display name
            $isTypeMatch = isset($alarm['type']) && $alarm['type'] === $deviceDisplayName;

            // Check if the device, user, and alarm type conditions are met
            if ($isDeviceMatch && $isUserMatch && $isTypeMatch) {
                $alert = true;
                break;
            }
        }

        return response()->json([
            'alert'   => $alert,
            'alarms'  => $alarms,
            'message' => $alert ? 'Alarm conditions met!' : 'No matching alarms found.'
        ]);
    }
}
