<?php
// header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

require_once 'config.php';
require_once 'Database.php';
include '../helper_functions/data_request.php';

class Auth {
    private $db;
    
    public function __construct() {
        $this->db = new Database();
    }
    
    public function login() {
        $data = json_decode(file_get_contents('php://input'), true);
    
        if (!isset($data['username']) || !isset($data['password'])) {
            http_response_code(400);
            echo json_encode(['error' => ['message' => 'Username and password are required']]);
            return;
        }
    
        $email = trim($data['username']);
        $password = $data['password'];
        $user = null;
        $userType = null;

        $user = fetchDataSingle('users', ['email' => $email]);
        if ($user) {
            $layerRaw = isset($user['layer']) ? strtolower(trim($user['layer'])) : '';

            $layerRaw = str_replace(['_', '-'], ' ', $layerRaw);

            $map = [
                'super admin'        => 'super_admin',
                'admin'              => 'admin',
                'dealer'             => 'dealer',
                'organization admin' => 'organization_admin',
                'sub dealer'         => 'sub_dealer',
                'property admin'     => 'property_admin',
                'user'               => 'user',
            ];

            $userType = $map[$layerRaw] ?? 'user';
        }

        if (!$user) {
            $sql = "
                SELECT id, email, password, has_2fa
                FROM dealer_admins
                WHERE email = :email
                AND status = 'registered'
                AND deleted_at IS NULL
                LIMIT 1
            ";
            $user = fetchSingleDataWithJoins($sql, [':email' => $email]);
            if ($user) {
                $userType = 'dealer_admin';
            }
        }

        if (!$user) {
            $sql = "
                SELECT id, email, password, has_2fa
                FROM property_users
                WHERE email = :email
                AND status = 'registered'
                AND deleted_at IS NULL
                LIMIT 1
            ";
            $user = fetchSingleDataWithJoins($sql, [':email' => $email]);
    
            if ($user) {
                $extra = fetchDataWithJoins("
                    SELECT property_id
                    FROM multi_prop_users
                    WHERE user_assoc = :id
                ", [':id' => $user['id']]);

                $userType = count($extra) > 0 ? 'multi_prop' : 'property_user';
            }
        }

        if (!$user || !password_verify($password, $user['password'])) {
            http_response_code(401);
            echo json_encode(['error' => ['message' => 'Invalid credentials']]);
            return;
        }

        deleteDataAdvanced('mobile_sessions', [
            'user_id' => $user['id'],
            'user_type' => $userType
        ]);

        $sessionId = bin2hex(random_bytes(32));
        $expiresAt = date('Y-m-d H:i:s', time() + TOKEN_EXPIRY);
    
        insertData('mobile_sessions', [
            'user_id'    => $user['id'],
            'user_type'  => $userType,
            'session_id' => $sessionId,
            'expires_at' => $expiresAt
        ]);

        $currentPropertyId = null;

        if ($userType === 'super_admin' || $userType === 'admin') {
            $allProps = fetchDataWithJoins("
                SELECT id, name
                FROM properties
                ORDER BY id ASC
            ", []);
            $currentPropertyId = $allProps[0]['id'] ?? null;

            updateTable('mobile_sessions', [
                'current_property_id' => $currentPropertyId
            ], 'session_id = :sid', [ 'sid' => $sessionId ]);

            $response = [
                'sessionId' => $sessionId,
                'user' => [
                    'id'     => $user['id'],
                    'email'  => $user['email'],
                    'type'   => $userType,
                    'has2FA' => (bool)$user['has_2fa']
                ],
                'currentPropertyId' => $currentPropertyId,
                'properties' => $allProps
            ];
            echo json_encode($response);
            return;
        }

        if ($userType === 'dealer') {
            $props = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM organizations o
                JOIN properties p ON p.organization_id = o.id
                WHERE o.dealer_id = :uid
                ORDER BY p.id ASC
            ", [':uid' => $user['id']]);

            $currentPropertyId = $props[0]['id'] ?? null;

            updateTable('mobile_sessions', ['current_property_id' => $currentPropertyId],
                'session_id = :sid', [ 'sid' => $sessionId ]);

            echo json_encode([
                'sessionId' => $sessionId,
                'user' => [
                    'id' => $user['id'],
                    'email' => $user['email'],
                    'type' => $userType,
                    'has2FA' => (bool)$user['has_2fa']
                ],
                'currentPropertyId' => $currentPropertyId,
                'properties' => $props
            ]);
            return;
        }

        if ($userType === 'dealer_admin') {

            $firstProp = fetchSingleDataWithJoins("
                SELECT property_id
                FROM dealer_admins_access
                WHERE dealer_admin_id = :id
                ORDER BY property_id ASC
                LIMIT 1
            ", [':id' => $user['id']]);

            $currentPropertyId = $firstProp['property_id'] ?? null;

            updateTable('mobile_sessions', [
                'current_property_id' => $currentPropertyId
            ], 'session_id = :sid', [ 'sid' => $sessionId ]);

            $props = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM dealer_admins_access daa
                JOIN properties p ON p.id = daa.property_id
                WHERE daa.dealer_admin_id = :id
            ", [':id' => $user['id']]);

            echo json_encode([
                'sessionId' => $sessionId,
                'user' => [
                    'id'     => $user['id'],
                    'email'  => $user['email'],
                    'type'   => $userType,
                    'has2FA' => (bool)$user['has_2fa']
                ],
                'currentPropertyId' => $currentPropertyId,
                'properties' => $props
            ]);
            return;
        }

        if ($userType === 'multi_prop') {
            $firstProp = fetchSingleDataWithJoins("
                SELECT property_id
                FROM property_users
                WHERE id = :id
                AND deleted_at IS NULL
                ORDER BY property_id ASC
                LIMIT 1
            ", [':id' => $user['id']]);

            $currentPropertyId = $firstProp['property_id'] ?? null;

            updateTable('mobile_sessions', [
                'current_property_id' => $currentPropertyId
            ], 'session_id = :sid', [ 'sid' => $sessionId ]);

            $primary = fetchSingleDataWithJoins("
                SELECT p.id, p.name
                FROM property_users pu
                JOIN properties p ON pu.property_id = p.id
                WHERE pu.id = :id
                AND pu.deleted_at IS NULL
                LIMIT 1
            ", [':id' => $user['id']]);

            $extra = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM multi_prop_users mp
                JOIN properties p ON mp.property_id = p.id
                WHERE mp.user_assoc = :id
                AND mp.deleted_at IS NULL
            ", [':id' => $user['id']]);

            echo json_encode([
                'sessionId' => $sessionId,
                'user' => [
                    'id'     => $user['id'],
                    'email'  => $user['email'],
                    'type'   => $userType,
                    'has2FA' => (bool)$user['has_2fa']
                ],
                'currentPropertyId' => $currentPropertyId,
                'properties' => array_merge([$primary], $extra)
            ]);
            return;
        }

        if ($userType === 'property_user') {
            $propRow = fetchSingleDataWithJoins("
                SELECT property_id
                FROM property_users
                WHERE id = :id
                AND deleted_at IS NULL
                LIMIT 1
            ", [':id' => $user['id']]);
            $currentPropertyId = $propRow['property_id'] ?? null;

            updateTable('mobile_sessions', [
                'current_property_id' => $currentPropertyId
            ], 'session_id = :sid', [ 'sid' => $sessionId ]);

            echo json_encode([
                'sessionId' => $sessionId,
                'user' => [
                    'id'     => $user['id'],
                    'email'  => $user['email'],
                    'type'   => $userType,
                    'has2FA' => (bool)$user['has_2fa']
                ]
            ]);
            return;
        }

        updateTable('mobile_sessions', [
            'current_property_id' => null
        ], 'session_id = :sid', [ 'sid' => $sessionId ]);

        echo json_encode([
            'sessionId' => $sessionId,
            'user' => [
                'id'     => $user['id'],
                'email'  => $user['email'],
                'type'   => $userType,
                'has2FA' => (bool)$user['has_2fa']
            ]

        ]);
        return;
    }
    
    public function verify() {
        $headers = getallheaders();
        $auth = isset($headers['Authorization']) ? $headers['Authorization'] : '';
    
        if (!preg_match('/Bearer\s+(.+)/', $auth, $matches)) {
            http_response_code(401);
            echo json_encode(['error' => ['message' => 'No token provided']]);
            return;
        }
    
        $sessionId = $matches[1];

        $session = fetchSingleDataWithJoins("
            SELECT user_id, user_type, current_property_id
            FROM mobile_sessions
            WHERE session_id = :sid
            AND expires_at > NOW()
            LIMIT 1
        ", [':sid' => $sessionId]);

        if (!$session) {
            http_response_code(401);
            echo json_encode(['error' => ['message' => 'Invalid or expired session']]);
            return;
        }

        $userType = $session['user_type'];
        $userId   = $session['user_id'];
        $currentPropertyId = $session['current_property_id'] ?? null;

        $mapToUsersTable = ['super_admin','admin','dealer','organization_admin','sub_dealer','property_admin','user'];
        if ($userType === 'multi_prop' || $userType === 'property_user') {
            $u = fetchDataSingle('property_users', ['id' => $userId]);
        } elseif ($userType === 'dealer_admin') {
            $u = fetchDataSingle('dealer_admins', ['id' => $userId]);
        } elseif (in_array($userType, $mapToUsersTable, true)) {
            $u = fetchDataSingle('users', ['id' => $userId]);
        } else {
            http_response_code(401);
            echo json_encode(['error' => ['message' => 'Invalid user type']]);
            return;
        }
        if (!$u) {
            http_response_code(401);
            echo json_encode(['error' => ['message' => 'User not found']]);
            return;
        }

        $props = null;
        if ($userType === 'super_admin' || $userType === 'admin') {
            $props = fetchDataWithJoins("
                SELECT id, name
                FROM properties
                ORDER BY id ASC
            ", []);
        } elseif ($userType === 'dealer') {
            $props = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM organizations o
                JOIN properties p ON p.organization_id = o.id
                WHERE o.dealer_id = :uid
                ORDER BY p.id ASC
            ", [':uid' => $userId]);
        } elseif ($userType === 'organization_admin' || $userType === 'sub_dealer') {
            $accessRows = fetchDataWithJoins("
                SELECT access_id
                FROM dealer_admins_access
                WHERE dealer_admin_id = :uid
                AND access_type = 'property'
                AND deleted_at IS NULL
            ", [':uid' => $userId]);
            if (!empty($accessRows)) {
                $ids = array_column($accessRows, 'access_id');
                $ph = []; $pa = [];
                foreach ($ids as $i => $pid) { $k=":p$i"; $ph[]=$k; $pa[$k]=$pid; }
                $props = fetchDataWithJoins("
                    SELECT id, name
                    FROM properties
                    WHERE deleted_at IS NULL
                    AND id IN (" . implode(',', $ph) . ")
                    ORDER BY id ASC
                ", $pa);
            } else {
                $props = [];
            }
        } elseif ($userType === 'dealer_admin') {
            $props = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM dealer_admins_access daa
                JOIN properties p ON p.id = daa.property_id
                WHERE daa.dealer_admin_id = :id
            ", [':id' => $userId]);
        } elseif ($userType === 'multi_prop') {
            $primary = fetchSingleDataWithJoins("
                SELECT p.id, p.name
                FROM property_users pu
                JOIN properties p ON pu.property_id = p.id
                WHERE pu.id = :id
                AND pu.deleted_at IS NULL
                LIMIT 1
            ", [':id' => $userId]);
            $extra = fetchDataWithJoins("
                SELECT p.id, p.name
                FROM multi_prop_users mp
                JOIN properties p ON mp.property_id = p.id
                WHERE mp.user_assoc = :id
                AND mp.deleted_at IS NULL
            ", [':id' => $userId]);
            $props = array_merge($primary ? [$primary] : [], $extra ?: []);
        }

        if (!$currentPropertyId && is_array($props) && count($props) > 0) {
            $currentPropertyId = $props[0]['id'];
            updateTable('mobile_sessions', [
                'current_property_id' => $currentPropertyId
            ], 'session_id = :sid', [ 'sid' => $sessionId ]);
        }

        $resp = [
            'valid' => true,
            'user' => [
                'id'     => $u['id'],
                'email'  => $u['email'],
                'type'   => $userType,
                'has2FA' => (bool)($u['has_2fa'] ?? 0)
            ],
            'currentPropertyId' => $currentPropertyId,
        ];
        if (is_array($props)) {
            $resp['properties'] = $props;
        }

        echo json_encode($resp);
    }
    
    public function logout() {
        $headers = getallheaders();
        $auth = isset($headers['Authorization']) ? $headers['Authorization'] : '';
    
        if (preg_match('/Bearer\s+(.+)/', $auth, $matches)) {
            $sessionId = $matches[1];

            $session = fetchSingleDataWithJoins("
                SELECT id FROM mobile_sessions WHERE session_id = :session_id LIMIT 1
            ", [':session_id' => $sessionId]);
    
            if ($session) {
                deleteData('mobile_sessions', 'session_id', $sessionId);
            }
        }

        echo json_encode(['success' => true]);
    }    
    
}

$auth = new Auth();
$method = $_SERVER['REQUEST_METHOD'];
$request = $_SERVER['REQUEST_URI'];
$prefix = '/include/api/auth/';

$endpoint = '';
if (strpos($request, $prefix) === 0) {
    $endpoint = substr($request, strlen($prefix));
}

if (($pos = strpos($endpoint, '?')) !== false) {
    $endpoint = substr($endpoint, 0, $pos);
}

$endpoint = rtrim($endpoint, '/');

if ($method === 'OPTIONS') {
    http_response_code(200);
    exit;
}

switch ($endpoint) {
    case 'login':
        if ($method === 'POST') {
            $auth->login();
        } else {
            http_response_code(405);
            echo json_encode(['error' => ['message' => 'Method not allowed']]);
        }
        break;
    case 'verify':
        if ($method === 'POST') {
            $auth->verify();
        } else {
            http_response_code(405);
            echo json_encode(['error' => ['message' => 'Method not allowed']]);
        }
        break;
    case 'logout':
        if ($method === 'POST') {
            $auth->logout();
        } else {
            http_response_code(405);
            echo json_encode(['error' => ['message' => 'Method not allowed']]);
        }
        break;
    default:
        http_response_code(404);
        echo json_encode(['error' => ['message' => 'Not found']]);
}