<?php
require_once '../../config.php';
header('Content-Type: application/json');

$sessionRole = $_SESSION['role'] ?? ($_SESSION['user_role'] ?? '');
if (!isset($_SESSION['user_id']) || $sessionRole !== 'staff') {
    http_response_code(401);
    echo json_encode(['success' => false, 'message' => 'Unauthorized']);
    exit;
}

$data = json_decode(file_get_contents('php://input'), true);
$property_id = (int)($data['property_id'] ?? 0);
$broker_id = (int)($data['broker_id'] ?? 0);

if ($property_id <= 0) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Valid property_id is required']);
    exit;
}

function getPropertyBrokerReferenceTable(mysqli $mysqli): string
{
    $sql = "
        SELECT LOWER(REFERENCED_TABLE_NAME) AS ref_table
        FROM information_schema.KEY_COLUMN_USAGE
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = 'properties'
          AND COLUMN_NAME = 'broker_id'
          AND REFERENCED_TABLE_NAME IS NOT NULL
        LIMIT 1
    ";
    $res = $mysqli->query($sql);
    if ($res && ($row = $res->fetch_assoc())) {
        $ref = strtolower((string)($row['ref_table'] ?? ''));
        $res->free();
        if ($ref === 'brokers' || $ref === 'users') {
            return $ref;
        }
    }
    return 'users';
}

function resolveAssignableBroker(mysqli $mysqli, int $requestedBrokerId, string $refTable): array
{
    if ($requestedBrokerId <= 0) {
        return ['id' => null, 'name' => 'Unassigned'];
    }

    if ($refTable === 'brokers') {
        $b = $mysqli->prepare("SELECT id, name, email FROM brokers WHERE id = ? LIMIT 1");
        if ($b) {
            $b->bind_param('i', $requestedBrokerId);
            $b->execute();
            $row = $b->get_result()->fetch_assoc();
            $b->close();
            if ($row) {
                return ['id' => (int)$row['id'], 'name' => (string)($row['name'] ?? ('Broker #' . $row['id']))];
            }
        }

        // Mixed schema fallback: users.id -> brokers.id via email
        $u = $mysqli->prepare("SELECT email, full_name FROM users WHERE id = ? AND role = 'broker' LIMIT 1");
        if ($u) {
            $u->bind_param('i', $requestedBrokerId);
            $u->execute();
            $uRow = $u->get_result()->fetch_assoc();
            $u->close();
            if (!empty($uRow['email'])) {
                $m = $mysqli->prepare("SELECT id, name FROM brokers WHERE email = ? LIMIT 1");
                if ($m) {
                    $m->bind_param('s', $uRow['email']);
                    $m->execute();
                    $mRow = $m->get_result()->fetch_assoc();
                    $m->close();
                    if ($mRow) {
                        return ['id' => (int)$mRow['id'], 'name' => (string)($mRow['name'] ?? ($uRow['full_name'] ?? 'Broker'))];
                    }
                }
            }
        }
        return ['id' => null, 'name' => 'Unassigned'];
    }

    $u = $mysqli->prepare("SELECT id, full_name FROM users WHERE id = ? AND role = 'broker' LIMIT 1");
    if ($u) {
        $u->bind_param('i', $requestedBrokerId);
        $u->execute();
        $row = $u->get_result()->fetch_assoc();
        $u->close();
        if ($row) {
            return ['id' => (int)$row['id'], 'name' => (string)($row['full_name'] ?? ('Broker #' . $row['id']))];
        }
    }

    return ['id' => null, 'name' => 'Unassigned'];
}

function resolveAssignableBrokerRef(mysqli $mysqli, string $brokerRef, string $refTable): array
{
    $brokerRef = trim($brokerRef);
    if ($brokerRef === '' || $brokerRef === '0') {
        return ['id' => null, 'name' => 'Unassigned'];
    }

    if (preg_match('/^broker:(\d+)$/', $brokerRef, $m)) {
        $brokerId = (int)$m[1];
        if ($brokerId <= 0) {
            return ['id' => null, 'name' => 'Unassigned'];
        }
        if ($refTable === 'brokers') {
            $b = $mysqli->prepare("SELECT id, name FROM brokers WHERE id = ? LIMIT 1");
            if ($b) {
                $b->bind_param('i', $brokerId);
                $b->execute();
                $row = $b->get_result()->fetch_assoc();
                $b->close();
                if ($row) {
                    return ['id' => (int)$row['id'], 'name' => (string)$row['name']];
                }
            }
            return ['id' => null, 'name' => 'Unassigned'];
        }
        return resolveAssignableBroker($mysqli, $brokerId, $refTable);
    }

    if (preg_match('/^user:(\d+)$/', $brokerRef, $m)) {
        $userId = (int)$m[1];
        if ($refTable !== 'brokers') {
            return resolveAssignableBroker($mysqli, $userId, $refTable);
        }

        $u = $mysqli->prepare("
            SELECT id, full_name, email, phone
            FROM users
            WHERE id = ? AND role = 'broker'
            LIMIT 1
        ");
        if (!$u) {
            return ['id' => null, 'name' => 'Unassigned'];
        }
        $u->bind_param('i', $userId);
        $u->execute();
        $user = $u->get_result()->fetch_assoc();
        $u->close();
        if (!$user || empty($user['email'])) {
            return ['id' => null, 'name' => 'Unassigned'];
        }

        // Reuse existing broker by email if available.
        $find = $mysqli->prepare("SELECT id, name FROM brokers WHERE email = ? LIMIT 1");
        if ($find) {
            $find->bind_param('s', $user['email']);
            $find->execute();
            $broker = $find->get_result()->fetch_assoc();
            $find->close();
            if ($broker) {
                return ['id' => (int)$broker['id'], 'name' => (string)($broker['name'] ?? $user['full_name'])];
            }
        }

        // Auto-create broker row so FK properties.broker_id -> brokers.id can be satisfied.
        $randomPassword = password_hash(bin2hex(random_bytes(8)), PASSWORD_DEFAULT);
        $insert = $mysqli->prepare("
            INSERT INTO brokers (name, email, password, phone, role)
            VALUES (?, ?, ?, ?, 'broker')
        ");
        if (!$insert) {
            return ['id' => null, 'name' => 'Unassigned'];
        }
        $name = (string)($user['full_name'] ?? ('Broker #' . $userId));
        $email = (string)$user['email'];
        $phone = (string)($user['phone'] ?? '');
        $insert->bind_param('ssss', $name, $email, $randomPassword, $phone);
        if (!$insert->execute()) {
            $insert->close();
            return ['id' => null, 'name' => 'Unassigned'];
        }
        $newId = (int)$insert->insert_id;
        $insert->close();
        return ['id' => $newId, 'name' => $name];
    }

    if (ctype_digit($brokerRef)) {
        return resolveAssignableBroker($mysqli, (int)$brokerRef, $refTable);
    }

    return ['id' => null, 'name' => 'Unassigned'];
}

function ensureAssignmentWorkflowTable(mysqli $mysqli): void
{
    $mysqli->query("
        CREATE TABLE IF NOT EXISTS property_assignment_workflow (
            id INT AUTO_INCREMENT PRIMARY KEY,
            property_id INT NOT NULL UNIQUE,
            broker_id INT NULL,
            workflow_status VARCHAR(40) NOT NULL DEFAULT 'assigned',
            admin_review_status VARCHAR(20) NOT NULL DEFAULT 'pending',
            broker_confirmed_at DATETIME NULL,
            work_started_at DATETIME NULL,
            work_finished_at DATETIME NULL,
            admin_reviewed_by INT NULL,
            admin_reviewed_at DATETIME NULL,
            admin_notes VARCHAR(255) NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_broker_id (broker_id),
            INDEX idx_workflow_status (workflow_status),
            INDEX idx_admin_review_status (admin_review_status)
        )
    ");
}

try {
    ensureAssignmentWorkflowTable($mysqli);
    $refTable = getPropertyBrokerReferenceTable($mysqli);

    $property_check = $mysqli->prepare("SELECT id FROM properties WHERE id = ?");
    if (!$property_check) {
        throw new Exception($mysqli->error);
    }
    $property_check->bind_param('i', $property_id);
    $property_check->execute();
    $property_result = $property_check->get_result();
    if ($property_result->num_rows === 0) {
        http_response_code(404);
        echo json_encode(['success' => false, 'message' => 'Property not found']);
        $property_check->close();
        exit;
    }
    $property_check->close();

    $broker_ref = (string)($data['broker_ref'] ?? '');
    $resolvedBroker = $broker_ref !== ''
        ? resolveAssignableBrokerRef($mysqli, $broker_ref, $refTable)
        : resolveAssignableBroker($mysqli, $broker_id, $refTable);
    $resolvedBrokerId = isset($resolvedBroker['id']) ? (int)$resolvedBroker['id'] : 0;
    $broker_name = (string)($resolvedBroker['name'] ?? 'Unassigned');

    if ($broker_id > 0 && $resolvedBrokerId <= 0) {
        http_response_code(400);
        echo json_encode(['success' => false, 'message' => 'Broker not found for current schema']);
        exit;
    }

    if ($resolvedBrokerId > 0) {
        $update_stmt = $mysqli->prepare("UPDATE properties SET broker_id = ? WHERE id = ?");
        if (!$update_stmt) {
            throw new Exception($mysqli->error);
        }
        $update_stmt->bind_param('ii', $resolvedBrokerId, $property_id);
    } else {
        $update_stmt = $mysqli->prepare("UPDATE properties SET broker_id = NULL WHERE id = ?");
        if (!$update_stmt) {
            throw new Exception($mysqli->error);
        }
        $update_stmt->bind_param('i', $property_id);
    }

    if (!$update_stmt->execute()) {
        throw new Exception($update_stmt->error);
    }
    $update_stmt->close();

    if ($resolvedBrokerId > 0) {
        $workflowStmt = $mysqli->prepare("
            INSERT INTO property_assignment_workflow (
                property_id, broker_id, workflow_status, admin_review_status,
                broker_confirmed_at, work_started_at, work_finished_at,
                admin_reviewed_by, admin_reviewed_at, admin_notes
            )
            VALUES (?, ?, 'assigned', 'pending', NULL, NULL, NULL, NULL, NULL, NULL)
            ON DUPLICATE KEY UPDATE
                broker_id = VALUES(broker_id),
                workflow_status = 'assigned',
                admin_review_status = 'pending',
                broker_confirmed_at = NULL,
                work_started_at = NULL,
                work_finished_at = NULL,
                admin_reviewed_by = NULL,
                admin_reviewed_at = NULL,
                admin_notes = NULL
        ");
        if (!$workflowStmt) {
            throw new Exception($mysqli->error);
        }
        $workflowStmt->bind_param('ii', $property_id, $resolvedBrokerId);
        if (!$workflowStmt->execute()) {
            $workflowStmt->close();
            throw new Exception('Failed to initialize assignment workflow');
        }
        $workflowStmt->close();
    } else {
        $deleteWorkflowStmt = $mysqli->prepare("DELETE FROM property_assignment_workflow WHERE property_id = ?");
        if ($deleteWorkflowStmt) {
            $deleteWorkflowStmt->bind_param('i', $property_id);
            $deleteWorkflowStmt->execute();
            $deleteWorkflowStmt->close();
        }
    }

    echo json_encode([
        'success' => true,
        'message' => $resolvedBrokerId > 0 ? 'Property assigned successfully' : 'Property unassigned successfully',
        'property_id' => $property_id,
        'broker_id' => $resolvedBrokerId > 0 ? $resolvedBrokerId : null,
        'broker_name' => $broker_name
    ]);
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'success' => false,
        'message' => 'Failed to assign property: ' . $e->getMessage()
    ]);
}
