<?php

namespace App\Support;

use App\Models\ActivationRequest;
use App\Models\Course;
use App\Models\DailyEntry;
use App\Models\DailySheet;
use App\Models\DashboardProject;
use App\Models\DGService;
use App\Models\FbSubmission;
use App\Models\GmailSale;
use App\Models\InAccount;
use App\Models\Job;
use App\Models\JobSubmission;
use App\Models\LeadershipClaim;
use App\Models\LeadershipRank;
use App\Models\Offer;
use App\Models\Order;
use App\Models\PdCategory;
use App\Models\PdOrder;
use App\Models\Product;
use App\Models\Recharge;
use App\Models\Review;
use App\Models\TargetCampaign;
use App\Models\TargetClaim;
use App\Models\TypingJobSubmission;
use App\Models\User;
use App\Models\VendorOrder;
use App\Models\VendorProfile;
use App\Models\VoucherPayment;
use App\Models\VoucherTransaction;
use App\Models\WelcomeOfferClaim;
use App\Models\Withdraw;
use App\Models\WithdrawMethod;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use InvalidArgumentException;

class GraphqlReadOnlySchema
{
    /**
     * @return array<string, array<string, mixed>>
     */
    public static function definitions(): array
    {
        return [
            'siteInfo' => [
                'group' => 'knowledge',
                'lookup_name' => 'General Website Info',
                'use_case' => 'General website knowledge',
                'entity_label' => 'site',
                'variable_name' => null,
                'result_path' => 'data.siteInfo',
                'trigger_keywords' => 'about, contact, support, site info, company',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'siteName, siteDescription, supportGeneral, supportVerify, supportWithdraw, supportTechnical, socialLinks',
                'success_example' => 'Website info found.',
                'no_match_example' => 'Website info is not available.',
                'query' => <<<'GRAPHQL'
query SiteInfo {
  siteInfo {
    siteName
    siteDescription
    supportGeneral
    supportVerify
    supportWithdraw
    supportTechnical
    socialLinks
  }
}
GRAPHQL,
            ],
            'dashboardProjects' => [
                'group' => 'knowledge',
                'lookup_name' => 'Dashboard Project Summary',
                'use_case' => 'User dashboard modules and guides',
                'entity_label' => 'project',
                'variable_name' => null,
                'result_path' => 'data.dashboardProjects',
                'trigger_keywords' => 'dashboard, project, modules, features',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, link, isActive, allowedForInactive, sortOrder',
                'success_example' => 'Dashboard project list found.',
                'no_match_example' => 'No dashboard project found.',
                'query' => <<<'GRAPHQL'
query DashboardProjects {
  dashboardProjects {
    id
    title
    link
    isActive
    allowedForInactive
    sortOrder
  }
}
GRAPHQL,
            ],
            'publicProducts' => [
                'group' => 'knowledge',
                'lookup_name' => 'Product List',
                'use_case' => 'Product/service catalog knowledge',
                'entity_label' => 'product',
                'variable_name' => null,
                'result_path' => 'data.publicProducts',
                'trigger_keywords' => 'product, shop, item, price, delivery',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, slug, category, price, deliveryTime, stock, status',
                'success_example' => 'Product list found.',
                'no_match_example' => 'No product found.',
                'query' => <<<'GRAPHQL'
query PublicProducts {
  publicProducts {
    id
    title
    slug
    category
    price
    deliveryTime
    stock
    status
  }
}
GRAPHQL,
            ],
            'productBySlug' => [
                'group' => 'lookup',
                'lookup_name' => 'Product By Slug',
                'use_case' => 'Product detail lookup',
                'entity_label' => 'product',
                'variable_name' => 'slug',
                'result_path' => 'data.productBySlug',
                'trigger_keywords' => 'product details, product slug, item details',
                'customer_prompt' => 'পণ্যের slug দিন।',
                'sample_value' => 'sample-product-slug',
                'safe_fields' => 'id, title, slug, description, category, price, deliveryTime, stock, status',
                'success_example' => 'Product details found.',
                'no_match_example' => 'এই slug দিয়ে কোনো product পাওয়া যায়নি।',
                'query' => <<<'GRAPHQL'
query ProductBySlug($slug: String!) {
  productBySlug(slug: $slug) {
    id
    title
    slug
    description
    category
    price
    deliveryTime
    stock
    status
  }
}
GRAPHQL,
            ],
            'publicCourses' => [
                'group' => 'knowledge',
                'lookup_name' => 'Course List',
                'use_case' => 'Education/course knowledge',
                'entity_label' => 'course',
                'variable_name' => null,
                'result_path' => 'data.publicCourses',
                'trigger_keywords' => 'course, class, lesson, education',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, description, sessionCount',
                'success_example' => 'Course list found.',
                'no_match_example' => 'No course found.',
                'query' => <<<'GRAPHQL'
query PublicCourses {
  publicCourses {
    id
    title
    description
    sessionCount
  }
}
GRAPHQL,
            ],
            'digitalServices' => [
                'group' => 'knowledge',
                'lookup_name' => 'Digital Service List',
                'use_case' => 'Digital service catalog knowledge',
                'entity_label' => 'service',
                'variable_name' => null,
                'result_path' => 'data.digitalServices',
                'trigger_keywords' => 'digital service, service, cashback, validity',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, description, price, cashback, validity, status',
                'success_example' => 'Digital service list found.',
                'no_match_example' => 'No digital service found.',
                'query' => <<<'GRAPHQL'
query DigitalServices {
  digitalServices {
    id
    title
    description
    price
    cashback
    validity
    status
  }
}
GRAPHQL,
            ],
            'publicOffers' => [
                'group' => 'knowledge',
                'lookup_name' => 'Drive Offer List',
                'use_case' => 'Offer/package knowledge',
                'entity_label' => 'offer',
                'variable_name' => null,
                'result_path' => 'data.publicOffers',
                'trigger_keywords' => 'offer, package, drive, cashback',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, description, price, cashback, validity',
                'success_example' => 'Offer list found.',
                'no_match_example' => 'No offer found.',
                'query' => <<<'GRAPHQL'
query PublicOffers {
  publicOffers {
    id
    title
    description
    price
    cashback
    validity
  }
}
GRAPHQL,
            ],
            'leadershipRanks' => [
                'group' => 'knowledge',
                'lookup_name' => 'Leadership Rank List',
                'use_case' => 'Leadership rank requirements',
                'entity_label' => 'rank',
                'variable_name' => null,
                'result_path' => 'data.leadershipRanks',
                'trigger_keywords' => 'leadership, rank, reward, requirement',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'key, name, displayTitle, requirements, rewardAmount, isActive',
                'success_example' => 'Leadership rank list found.',
                'no_match_example' => 'No leadership rank found.',
                'query' => <<<'GRAPHQL'
query LeadershipRanks {
  leadershipRanks {
    key
    name
    displayTitle
    requirements
    rewardAmount
    isActive
  }
}
GRAPHQL,
            ],
            'targetCampaigns' => [
                'group' => 'knowledge',
                'lookup_name' => 'Target Campaign List',
                'use_case' => 'Target bonus campaign knowledge',
                'entity_label' => 'target',
                'variable_name' => null,
                'result_path' => 'data.targetCampaigns',
                'trigger_keywords' => 'target, campaign, bonus',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, title, projectType, requiredCount, bonusAmount, bonusWallet, startAt, endAt, isActive',
                'success_example' => 'Target campaign list found.',
                'no_match_example' => 'No target campaign found.',
                'query' => <<<'GRAPHQL'
query TargetCampaigns {
  targetCampaigns {
    id
    title
    projectType
    requiredCount
    bonusAmount
    bonusWallet
    startAt
    endAt
    isActive
  }
}
GRAPHQL,
            ],
            'publicReviews' => [
                'group' => 'knowledge',
                'lookup_name' => 'Review Summary',
                'use_case' => 'Public review/rating knowledge',
                'entity_label' => 'review',
                'variable_name' => null,
                'result_path' => 'data.publicReviews',
                'trigger_keywords' => 'review, rating, feedback',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, userName, rating, comment, createdAt',
                'success_example' => 'Review list found.',
                'no_match_example' => 'No review found.',
                'query' => <<<'GRAPHQL'
query PublicReviews {
  publicReviews {
    id
    userName
    rating
    comment
    createdAt
  }
}
GRAPHQL,
            ],
            'withdrawMethods' => [
                'group' => 'knowledge',
                'lookup_name' => 'Withdraw Method List',
                'use_case' => 'Withdraw method knowledge',
                'entity_label' => 'withdraw_method',
                'variable_name' => null,
                'result_path' => 'data.withdrawMethods',
                'trigger_keywords' => 'withdraw, cashout, payment method',
                'customer_prompt' => '',
                'sample_value' => '',
                'safe_fields' => 'id, name, status',
                'success_example' => 'Withdraw method list found.',
                'no_match_example' => 'No withdraw method found.',
                'query' => <<<'GRAPHQL'
query WithdrawMethods {
  withdrawMethods {
    id
    name
    status
  }
}
GRAPHQL,
            ],
            'lookupUser' => self::lookupDefinition(
                'User Profile Lookup',
                'User / reference / mobile lookup',
                'user',
                'userIdentifier',
                'user, member, referral, mobile',
                'ইউজারের referral code, mobile, email বা ID দিন।',
                '123456',
                'id, name, referralCode, activeStatus, bannedStatus, joinedAt, activatedAt',
                <<<'GRAPHQL'
query LookupUser($userIdentifier: String!) {
  lookupUser(userIdentifier: $userIdentifier) {
    id
    name
    referralCode
    activeStatus
    bannedStatus
    joinedAt
    activatedAt
  }
}
GRAPHQL
            ),
            'lookupActivationRequest' => self::lookupDefinition(
                'Activation Request Lookup',
                'Activation request status',
                'activation_request',
                'activationIdentifier',
                'activation, verify, verification, request',
                'Activation request ID, referral code, mobile বা transaction reference দিন।',
                '123456',
                'id, user, referralCode, mobileMasked, status, reviewedAt, createdAt',
                <<<'GRAPHQL'
query LookupActivationRequest($activationIdentifier: String!) {
  lookupActivationRequest(activationIdentifier: $activationIdentifier) {
    id
    user
    referralCode
    mobileMasked
    status
    reviewedAt
    createdAt
  }
}
GRAPHQL
            ),
            'lookupWithdraw' => self::lookupDefinition(
                'Withdraw Lookup',
                'Withdraw request status',
                'withdraw',
                'withdrawIdentifier',
                'withdraw, cashout, payment, transaction',
                'Withdraw ID, transaction ID, mobile/account number বা user reference দিন।',
                'WD-1001',
                'id, user, method, type, numberMasked, amount, charge, total, transactionId, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupWithdraw($withdrawIdentifier: String!) {
  lookupWithdraw(withdrawIdentifier: $withdrawIdentifier) {
    id
    user
    method
    type
    numberMasked
    amount
    charge
    total
    transactionId
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupRecharge' => self::lookupDefinition(
                'Recharge Lookup',
                'Mobile recharge status',
                'recharge',
                'rechargeIdentifier',
                'recharge, topup, mobile recharge',
                'Recharge transaction ID, mobile number, user reference বা ID দিন।',
                'TRX-1001',
                'id, user, transactionId, numberMasked, operator, type, amount, cashback, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupRecharge($rechargeIdentifier: String!) {
  lookupRecharge(rechargeIdentifier: $rechargeIdentifier) {
    id
    user
    transactionId
    numberMasked
    operator
    type
    amount
    cashback
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupGmailSale' => self::lookupDefinition(
                'Gmail Sale Lookup',
                'Gmail sell submission status',
                'gmail_sale',
                'gmailIdentifier',
                'gmail, gmail sale, email sale',
                'Gmail sale ID, gmail address বা user reference দিন।',
                'GMAIL-1001',
                'id, user, gmailMasked, rate, adminPrice, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupGmailSale($gmailIdentifier: String!) {
  lookupGmailSale(gmailIdentifier: $gmailIdentifier) {
    id
    user
    gmailMasked
    rate
    adminPrice
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupFacebookSubmission' => self::lookupDefinition(
                'Facebook Submission Lookup',
                'Facebook submission status',
                'facebook_submission',
                'facebookIdentifier',
                'facebook, fb, facebook submission',
                'Facebook submission ID, UID, email বা user reference দিন।',
                'FB-1001',
                'id, user, fbUidMasked, fbEmailMasked, status, createdAt',
                <<<'GRAPHQL'
query LookupFacebookSubmission($facebookIdentifier: String!) {
  lookupFacebookSubmission(facebookIdentifier: $facebookIdentifier) {
    id
    user
    fbUidMasked
    fbEmailMasked
    status
    createdAt
  }
}
GRAPHQL
            ),
            'lookupInstagramAccount' => self::lookupDefinition(
                'Instagram Account Lookup',
                'Instagram account submission status',
                'instagram_account',
                'instagramIdentifier',
                'instagram, in account, username',
                'Instagram submission ID, username বা user reference দিন।',
                'insta_user',
                'id, user, username, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupInstagramAccount($instagramIdentifier: String!) {
  lookupInstagramAccount(instagramIdentifier: $instagramIdentifier) {
    id
    user
    username
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupDriveOrder' => self::lookupDefinition(
                'Drive Offer Order Lookup',
                'Drive offer order status',
                'drive_order',
                'driveOrderIdentifier',
                'drive order, offer order, order',
                'Drive order ID, mobile number বা user reference দিন।',
                '1001',
                'id, user, offerTitle, mobileMasked, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupDriveOrder($driveOrderIdentifier: String!) {
  lookupDriveOrder(driveOrderIdentifier: $driveOrderIdentifier) {
    id
    user
    offerTitle
    mobileMasked
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupProductOrder' => self::lookupDefinition(
                'Product Order Lookup',
                'Product delivery/order status',
                'product_order',
                'productOrderIdentifier',
                'product order, pd order, delivery, tracking',
                'Product order ID, customer phone, tracking URL বা user reference দিন।',
                '1001',
                'id, user, productTitle, qty, size, color, amount, customerName, customerPhoneMasked, addressSummary, status, trackingUrl, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupProductOrder($productOrderIdentifier: String!) {
  lookupProductOrder(productOrderIdentifier: $productOrderIdentifier) {
    id
    user
    productTitle
    qty
    amount
    customerName
    customerPhoneMasked
    status
    trackingUrl
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupVoucherPayment' => self::lookupDefinition(
                'Voucher Payment Lookup',
                'Voucher payment status',
                'voucher_payment',
                'paymentIdentifier',
                'voucher payment, payment, add money',
                'Payment transaction ID, trx ID, payment ID বা user reference দিন।',
                'PAY-1001',
                'id, user, transactionId, trxId, amount, currency, paymentMethod, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupVoucherPayment($paymentIdentifier: String!) {
  lookupVoucherPayment(paymentIdentifier: $paymentIdentifier) {
    id
    user
    transactionId
    trxId
    amount
    currency
    paymentMethod
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupVoucherTransaction' => self::lookupDefinition(
                'Voucher Transaction Lookup',
                'Wallet/voucher transaction status',
                'voucher_transaction',
                'transactionIdentifier',
                'voucher transaction, wallet transaction, statement',
                'Transaction ID, reference ID বা user reference দিন।',
                'TXN-1001',
                'id, txnId, user, wallet, direction, amount, source, referenceType, referenceId, description, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupVoucherTransaction($transactionIdentifier: String!) {
  lookupVoucherTransaction(transactionIdentifier: $transactionIdentifier) {
    id
    txnId
    user
    wallet
    direction
    amount
    source
    referenceType
    referenceId
    description
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupJob' => self::lookupDefinition(
                'Micro Job Lookup',
                'Micro job details/status',
                'micro_job',
                'jobIdentifier',
                'micro job, job, task',
                'Job ID বা title দিন।',
                '1001',
                'id, title, amount, limit, completedCount, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupJob($jobIdentifier: String!) {
  lookupJob(jobIdentifier: $jobIdentifier) {
    id
    title
    amount
    limit
    completedCount
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupJobSubmission' => self::lookupDefinition(
                'Job Submission Lookup',
                'Micro job submission status',
                'job_submission',
                'jobSubmissionIdentifier',
                'job submission, task submission, proof',
                'Job submission ID, job ID বা user reference দিন।',
                '1001',
                'id, user, jobTitle, status, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupJobSubmission($jobSubmissionIdentifier: String!) {
  lookupJobSubmission(jobSubmissionIdentifier: $jobSubmissionIdentifier) {
    id
    user
    jobTitle
    status
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupVendorOrder' => self::lookupDefinition(
                'Vendor Order Lookup',
                'Vendor shipment/order status',
                'vendor_order',
                'vendorOrderIdentifier',
                'vendor order, shipping, tracking',
                'Vendor order no, order ID, tracking link বা user reference দিন।',
                'VO-1001',
                'id, orderNo, user, vendorName, productTitle, totalAmount, trackingLink, status, orderedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupVendorOrder($vendorOrderIdentifier: String!) {
  lookupVendorOrder(vendorOrderIdentifier: $vendorOrderIdentifier) {
    id
    orderNo
    user
    vendorName
    productTitle
    totalAmount
    trackingLink
    status
    orderedAt
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupVendorProfile' => self::lookupDefinition(
                'Vendor Profile Lookup',
                'Vendor profile/application status',
                'vendor_profile',
                'vendorIdentifier',
                'vendor, vendor profile, vendor application',
                'Vendor ID, vendor name, service charge transaction ID বা user reference দিন।',
                '1001',
                'id, user, vendorName, address, status, serviceChargeAmount, serviceChargeTxnId, reviewedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupVendorProfile($vendorIdentifier: String!) {
  lookupVendorProfile(vendorIdentifier: $vendorIdentifier) {
    id
    user
    vendorName
    address
    status
    serviceChargeAmount
    serviceChargeTxnId
    reviewedAt
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupLeadershipClaim' => self::lookupDefinition(
                'Leadership Claim Lookup',
                'Leadership reward claim status',
                'leadership_claim',
                'leadershipClaimIdentifier',
                'leadership claim, rank claim, reward',
                'Leadership claim ID, rank ID বা user reference দিন।',
                '1001',
                'id, user, rankName, rewardAmount, claimedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupLeadershipClaim($leadershipClaimIdentifier: String!) {
  lookupLeadershipClaim(leadershipClaimIdentifier: $leadershipClaimIdentifier) {
    id
    user
    rankName
    rewardAmount
    claimedAt
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupTargetClaim' => self::lookupDefinition(
                'Target Claim Lookup',
                'Target bonus claim status',
                'target_claim',
                'targetClaimIdentifier',
                'target claim, bonus claim',
                'Target claim ID, campaign ID বা user reference দিন।',
                '1001',
                'id, user, campaignTitle, amount, claimedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupTargetClaim($targetClaimIdentifier: String!) {
  lookupTargetClaim(targetClaimIdentifier: $targetClaimIdentifier) {
    id
    user
    campaignTitle
    amount
    claimedAt
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupTypingJobSubmission' => self::lookupDefinition(
                'Typing Job Submission Lookup',
                'Typing job submission status/history',
                'typing_job_submission',
                'typingIdentifier',
                'typing job, typing submission',
                'Typing job submission ID, user answer বা user reference দিন।',
                '1001',
                'id, user, expression, userAnswer, correctAnswer, rewardAmount, submittedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupTypingJobSubmission($typingIdentifier: String!) {
  lookupTypingJobSubmission(typingIdentifier: $typingIdentifier) {
    id
    user
    expression
    userAnswer
    correctAnswer
    rewardAmount
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupWelcomeOfferClaim' => self::lookupDefinition(
                'Welcome Offer Claim Lookup',
                'Welcome offer claim status',
                'welcome_offer_claim',
                'welcomeIdentifier',
                'welcome offer, offer claim, bonus',
                'Welcome offer claim ID বা user reference দিন।',
                '1001',
                'id, user, amount, claimSource, claimedAt, createdAt, updatedAt',
                <<<'GRAPHQL'
query LookupWelcomeOfferClaim($welcomeIdentifier: String!) {
  lookupWelcomeOfferClaim(welcomeIdentifier: $welcomeIdentifier) {
    id
    user
    amount
    claimSource
    claimedAt
    createdAt
    updatedAt
  }
}
GRAPHQL
            ),
            'lookupFinanceDailySheet' => self::lookupDefinition(
                'Finance Daily Sheet Lookup',
                'Internal daily finance read-only summary',
                'finance_daily_sheet',
                'sheetDate',
                'finance, daily sheet, accounting',
                'Finance sheet date দিন, যেমন 2026-04-19।',
                '2026-04-19',
                'id, sheetDate, counts, totalIn, totalOut, net, notes, entries',
                <<<'GRAPHQL'
query LookupFinanceDailySheet($sheetDate: String!) {
  lookupFinanceDailySheet(sheetDate: $sheetDate) {
    id
    sheetDate
    counts
    totalIn
    totalOut
    net
    notes
    entries
  }
}
GRAPHQL
            ),
        ];
    }

    /**
     * @return array<string, mixed>
     */
    public static function execute(string $query, array $variables = []): array
    {
        self::guardReadOnlyQuery($query);

        $operation = self::extractRootField($query);
        $definitions = self::definitions();

        if (!isset($definitions[$operation])) {
            throw new InvalidArgumentException("Query '{$operation}' is not allowed on this read-only endpoint.");
        }

        $definition = $definitions[$operation];
        $value = null;
        $variableName = $definition['variable_name'] ?? null;

        if (is_string($variableName) && $variableName !== '') {
            $value = trim((string) ($variables[$variableName] ?? $variables['identifier'] ?? ''));
            if ($value === '') {
                throw new InvalidArgumentException("Variable '{$variableName}' is required.");
            }
        }

        return [
            'data' => [
                $operation => self::resolve($operation, $value),
            ],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    private static function lookupDefinition(
        string $lookupName,
        string $useCase,
        string $entityLabel,
        string $variableName,
        string $triggerKeywords,
        string $customerPrompt,
        string $sampleValue,
        string $safeFields,
        string $query
    ): array {
        return [
            'group' => 'lookup',
            'lookup_name' => $lookupName,
            'use_case' => $useCase,
            'entity_label' => $entityLabel,
            'variable_name' => $variableName,
            'result_path' => 'data.' . self::operationNameFromQuery($query),
            'trigger_keywords' => $triggerKeywords,
            'customer_prompt' => $customerPrompt,
            'sample_value' => $sampleValue,
            'safe_fields' => $safeFields,
            'success_example' => $lookupName . ' found.',
            'no_match_example' => 'No matching record found.',
            'query' => $query,
        ];
    }

    private static function operationNameFromQuery(string $query): string
    {
        if (preg_match('/\{\s*([_A-Za-z][_0-9A-Za-z]*)/s', $query, $m)) {
            return $m[1];
        }

        return '';
    }

    private static function guardReadOnlyQuery(string $query): void
    {
        if (trim($query) === '') {
            throw new InvalidArgumentException('GraphQL query is required.');
        }

        if (preg_match('/\b(mutation|subscription)\b/i', $query)) {
            throw new InvalidArgumentException('Only read-only query operations are allowed.');
        }

        if (Str::contains($query, ['__schema', '__type'])) {
            throw new InvalidArgumentException('GraphQL introspection is disabled on this endpoint.');
        }
    }

    private static function extractRootField(string $query): string
    {
        $clean = preg_replace('/#.*/', '', $query) ?? $query;
        $pos = strpos($clean, '{');
        if ($pos === false) {
            throw new InvalidArgumentException('GraphQL query body is invalid.');
        }

        $body = substr($clean, $pos + 1);
        if (!preg_match('/^\s*([_A-Za-z][_0-9A-Za-z]*)\s*(?:\(|\{|\s)/s', $body, $m)) {
            throw new InvalidArgumentException('Could not detect GraphQL root field.');
        }

        return $m[1];
    }

    private static function resolve(string $operation, ?string $value): mixed
    {
        return match ($operation) {
            'siteInfo' => self::siteInfo(),
            'dashboardProjects' => self::dashboardProjects(),
            'publicProducts' => self::publicProducts(),
            'productBySlug' => self::productBySlug((string) $value),
            'publicCourses' => self::publicCourses(),
            'digitalServices' => self::digitalServices(),
            'publicOffers' => self::publicOffers(),
            'leadershipRanks' => self::leadershipRanks(),
            'targetCampaigns' => self::targetCampaigns(),
            'publicReviews' => self::publicReviews(),
            'withdrawMethods' => self::withdrawMethods(),
            'lookupUser' => self::lookupUser((string) $value),
            'lookupActivationRequest' => self::lookupActivationRequest((string) $value),
            'lookupWithdraw' => self::lookupWithdraw((string) $value),
            'lookupRecharge' => self::lookupRecharge((string) $value),
            'lookupGmailSale' => self::lookupGmailSale((string) $value),
            'lookupFacebookSubmission' => self::lookupFacebookSubmission((string) $value),
            'lookupInstagramAccount' => self::lookupInstagramAccount((string) $value),
            'lookupDriveOrder' => self::lookupDriveOrder((string) $value),
            'lookupProductOrder' => self::lookupProductOrder((string) $value),
            'lookupVoucherPayment' => self::lookupVoucherPayment((string) $value),
            'lookupVoucherTransaction' => self::lookupVoucherTransaction((string) $value),
            'lookupJob' => self::lookupJob((string) $value),
            'lookupJobSubmission' => self::lookupJobSubmission((string) $value),
            'lookupVendorOrder' => self::lookupVendorOrder((string) $value),
            'lookupVendorProfile' => self::lookupVendorProfile((string) $value),
            'lookupLeadershipClaim' => self::lookupLeadershipClaim((string) $value),
            'lookupTargetClaim' => self::lookupTargetClaim((string) $value),
            'lookupTypingJobSubmission' => self::lookupTypingJobSubmission((string) $value),
            'lookupWelcomeOfferClaim' => self::lookupWelcomeOfferClaim((string) $value),
            'lookupFinanceDailySheet' => self::lookupFinanceDailySheet((string) $value),
            default => null,
        };
    }

    private static function siteInfo(): ?array
    {
        $settings = self::firstModel(\App\Models\GeneralSetting::class);
        if (!$settings) {
            return null;
        }

        return [
            'siteName' => self::attr($settings, 'site_name'),
            'siteDescription' => self::attr($settings, 'site_description'),
            'supportGeneral' => self::attr($settings, 'support_general'),
            'supportVerify' => self::attr($settings, 'support_verify'),
            'supportWithdraw' => self::attr($settings, 'support_withdraw'),
            'supportTechnical' => self::attr($settings, 'support_technical'),
            'socialLinks' => [
                'facebook' => self::attr($settings, 'facebook_link'),
                'youtube' => self::attr($settings, 'youtube_link'),
                'whatsapp' => self::attr($settings, 'whatsapp_link'),
                'telegram' => self::attr($settings, 'telegram_link'),
            ],
            'updatedAt' => self::date($settings->getAttribute('updated_at')),
        ];
    }

    private static function dashboardProjects(): array
    {
        return self::limitedRows(DashboardProject::class, 50, function (Builder $query): void {
            if (self::hasColumn(DashboardProject::class, 'sort_order')) {
                $query->orderBy('sort_order');
            }
            $query->orderBy('id');
        })->map(fn (DashboardProject $project): array => [
            'id' => (int) $project->id,
            'title' => self::attr($project, 'title'),
            'link' => self::attr($project, 'link'),
            'isActive' => self::boolLabel($project->getAttribute('is_active')),
            'allowedForInactive' => self::boolLabel($project->getAttribute('allowed_for_inactive')),
            'sortOrder' => self::intOrNull($project->getAttribute('sort_order')),
        ])->all();
    }

    private static function publicProducts(): array
    {
        return self::limitedRows(Product::class, 50, function (Builder $query): void {
            if (self::hasColumn(Product::class, 'status')) {
                $query->where('status', 1);
            }
            $query->latest('id');
        })->map(fn (Product $product): array => self::productPayload($product))->all();
    }

    private static function productBySlug(string $slug): ?array
    {
        $product = self::query(Product::class)
            ?->where('slug', $slug)
            ->first();

        return $product ? self::productPayload($product) : null;
    }

    private static function productPayload(Product $product): array
    {
        return [
            'id' => (int) $product->id,
            'title' => self::attr($product, 'title'),
            'slug' => self::attr($product, 'slug'),
            'description' => self::plainText(self::attr($product, 'description')),
            'category' => self::relatedValue(PdCategory::class, $product->getAttribute('category_id'), 'name'),
            'price' => self::money($product->getAttribute('reseller_price')),
            'deliveryTime' => self::attr($product, 'delivery_time'),
            'stock' => self::intOrNull($product->getAttribute('stock')),
            'status' => self::boolLabel($product->getAttribute('status')),
        ];
    }

    private static function publicCourses(): array
    {
        return self::limitedRows(Course::class, 50, fn (Builder $query) => $query->latest('id'))
            ->map(fn (Course $course): array => [
                'id' => (int) $course->id,
                'title' => self::attr($course, 'title'),
                'description' => self::plainText(self::attr($course, 'description')),
                'sessionCount' => self::relationCount($course, 'sessions'),
            ])->all();
    }

    private static function digitalServices(): array
    {
        return self::limitedRows(DGService::class, 50, function (Builder $query): void {
            if (self::hasColumn(DGService::class, 'status')) {
                $query->where('status', 1);
            }
            $query->latest('id');
        })->map(fn (DGService $service): array => [
            'id' => (int) $service->id,
            'title' => self::attr($service, 'title'),
            'description' => self::plainText(self::attr($service, 'description')),
            'price' => self::money($service->getAttribute('price')),
            'cashback' => self::money($service->getAttribute('cashback')),
            'validity' => self::attr($service, 'validity'),
            'status' => self::boolLabel($service->getAttribute('status')),
        ])->all();
    }

    private static function publicOffers(): array
    {
        return self::limitedRows(Offer::class, 50, fn (Builder $query) => $query->latest('id'))
            ->map(fn (Offer $offer): array => [
                'id' => (int) $offer->id,
                'title' => self::attr($offer, 'title'),
                'description' => self::plainText(self::attr($offer, 'description')),
                'price' => self::money($offer->getAttribute('price')),
                'cashback' => self::money($offer->getAttribute('cashback')),
                'validity' => self::attr($offer, 'validity'),
            ])->all();
    }

    private static function leadershipRanks(): array
    {
        return self::limitedRows(LeadershipRank::class, 50, function (Builder $query): void {
            if (self::hasColumn(LeadershipRank::class, 'sort_order')) {
                $query->orderBy('sort_order');
            }
            $query->orderBy('id');
        })->map(fn (LeadershipRank $rank): array => [
            'key' => self::attr($rank, 'key'),
            'name' => self::attr($rank, 'name'),
            'displayTitle' => self::attr($rank, 'display_title'),
            'requirements' => [
                'verifiedMembers' => self::intOrNull($rank->getAttribute('need_verified_members')),
                'level2Members' => self::intOrNull($rank->getAttribute('need_level2_members')),
                'gmailCompleted' => self::intOrNull($rank->getAttribute('need_gmail_completed')),
                'facebookApproved' => self::intOrNull($rank->getAttribute('need_fb_approved')),
            ],
            'rewardAmount' => self::money($rank->getAttribute('reward_amount')),
            'isActive' => self::boolLabel($rank->getAttribute('is_active')),
        ])->all();
    }

    private static function targetCampaigns(): array
    {
        return self::limitedRows(TargetCampaign::class, 50, fn (Builder $query) => $query->latest('id'))
            ->map(fn (TargetCampaign $target): array => [
                'id' => (int) $target->id,
                'title' => self::attr($target, 'title'),
                'projectType' => self::attr($target, 'project_type'),
                'requiredCount' => self::intOrNull($target->getAttribute('required_count')),
                'bonusAmount' => self::money($target->getAttribute('bonus_amount')),
                'bonusWallet' => self::attr($target, 'bonus_wallet'),
                'startAt' => self::date($target->getAttribute('start_at')),
                'endAt' => self::date($target->getAttribute('end_at')),
                'isActive' => self::boolLabel($target->getAttribute('is_active')),
            ])->all();
    }

    private static function publicReviews(): array
    {
        return self::limitedRows(Review::class, 30, fn (Builder $query) => $query->latest('id'))
            ->map(fn (Review $review): array => [
                'id' => (int) $review->id,
                'userName' => self::userSummary($review->getAttribute('user_id'))['name'] ?? null,
                'rating' => self::intOrNull($review->getAttribute('rating')),
                'comment' => self::plainText(self::attr($review, 'comment')),
                'createdAt' => self::date($review->getAttribute('created_at')),
            ])->all();
    }

    private static function withdrawMethods(): array
    {
        return self::limitedRows(WithdrawMethod::class, 50, fn (Builder $query) => $query->orderBy('id'))
            ->map(fn (WithdrawMethod $method): array => [
                'id' => (int) $method->id,
                'name' => self::attr($method, 'name') ?: self::attr($method, 'method_name'),
                'status' => self::hasColumn(WithdrawMethod::class, 'status') ? self::boolLabel($method->getAttribute('status')) : null,
            ])->all();
    }

    private static function lookupUser(string $identifier): ?array
    {
        $user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier);
        if (!$user) {
            return null;
        }

        return self::userSummary($user->id) + [
            'joinedAt' => self::date($user->getAttribute('created_at')),
            'activatedAt' => self::date($user->getAttribute('activated_at')),
        ];
    }

    private static function lookupActivationRequest(string $identifier): ?array
    {
        $record = self::findRecord(ActivationRequest::class, ['id', 'mobile', 'referral_code', 'transaction_reference'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(ActivationRequest::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'referralCode' => self::attr($record, 'referral_code'),
            'mobileMasked' => self::maskPhone(self::attr($record, 'mobile')),
            'status' => self::attr($record, 'status'),
            'reviewedAt' => self::date($record->getAttribute('reviewed_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
        ];
    }

    private static function lookupWithdraw(string $identifier): ?array
    {
        $record = self::findRecord(Withdraw::class, ['id', 'transaction_id', 'number'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(Withdraw::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'method' => self::relatedValue(WithdrawMethod::class, $record->getAttribute('method_id'), 'name'),
            'type' => self::relatedValue(\App\Models\WithdrawType::class, $record->getAttribute('type_id'), 'name'),
            'numberMasked' => self::maskPhone(self::attr($record, 'number')),
            'amount' => self::money($record->getAttribute('amount')),
            'charge' => self::money($record->getAttribute('charge')),
            'total' => self::money($record->getAttribute('total')),
            'transactionId' => self::attr($record, 'transaction_id'),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupRecharge(string $identifier): ?array
    {
        $record = self::findRecord(Recharge::class, ['id', 'tran_id', 'number', 'operator'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(Recharge::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'transactionId' => self::attr($record, 'tran_id'),
            'numberMasked' => self::maskPhone(self::attr($record, 'number')),
            'operator' => self::attr($record, 'operator'),
            'type' => self::attr($record, 'type'),
            'amount' => self::money($record->getAttribute('amount')),
            'cashback' => self::money($record->getAttribute('cashback')),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupGmailSale(string $identifier): ?array
    {
        $record = self::findRecord(GmailSale::class, ['id', 'gmail'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(GmailSale::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'gmailMasked' => self::maskEmail(self::attr($record, 'gmail')),
            'rate' => self::money($record->getAttribute('rate')),
            'adminPrice' => self::money($record->getAttribute('admin_price')),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupFacebookSubmission(string $identifier): ?array
    {
        $record = self::findRecord(FbSubmission::class, ['id', 'fb_uid', 'fb_email'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(FbSubmission::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'fbUidMasked' => self::maskPlain(self::attr($record, 'fb_uid')),
            'fbEmailMasked' => self::maskEmail(self::attr($record, 'fb_email')),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
        ];
    }

    private static function lookupInstagramAccount(string $identifier): ?array
    {
        $record = self::findRecord(InAccount::class, ['id', 'username'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(InAccount::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'username' => self::attr($record, 'username'),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupDriveOrder(string $identifier): ?array
    {
        $record = self::findRecord(Order::class, ['id', 'mobile_number'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(Order::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'offerTitle' => self::relatedValue(Offer::class, $record->getAttribute('offer_id'), 'title'),
            'mobileMasked' => self::maskPhone(self::attr($record, 'mobile_number')),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupProductOrder(string $identifier): ?array
    {
        $record = self::findRecord(PdOrder::class, ['id', 'customer_phone', 'alt_phone', 'tracking_url'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(PdOrder::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'productTitle' => self::relatedValue(Product::class, $record->getAttribute('product_id'), 'title'),
            'qty' => self::intOrNull($record->getAttribute('qty')),
            'size' => self::attr($record, 'size'),
            'color' => self::attr($record, 'color'),
            'amount' => self::money($record->getAttribute('grand_total')),
            'customerName' => self::attr($record, 'customer_name'),
            'customerPhoneMasked' => self::maskPhone(self::attr($record, 'customer_phone')),
            'addressSummary' => self::addressSummary($record),
            'status' => self::attr($record, 'status'),
            'trackingUrl' => self::attr($record, 'tracking_url'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupVoucherPayment(string $identifier): ?array
    {
        $record = self::findRecord(VoucherPayment::class, ['id', 'transaction_id', 'trx_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(VoucherPayment::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'transactionId' => self::attr($record, 'transaction_id'),
            'trxId' => self::attr($record, 'trx_id'),
            'amount' => self::money($record->getAttribute('amount')),
            'currency' => self::attr($record, 'currency'),
            'paymentMethod' => self::attr($record, 'payment_method'),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupVoucherTransaction(string $identifier): ?array
    {
        $record = self::findRecord(VoucherTransaction::class, ['id', 'txn_id', 'reference_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(VoucherTransaction::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'txnId' => self::attr($record, 'txn_id'),
            'user' => self::userSummary($record->getAttribute('user_id')),
            'wallet' => self::attr($record, 'wallet'),
            'direction' => self::attr($record, 'direction'),
            'amount' => self::money($record->getAttribute('amount')),
            'source' => self::attr($record, 'source'),
            'referenceType' => self::attr($record, 'reference_type'),
            'referenceId' => self::attr($record, 'reference_id'),
            'description' => self::plainText(self::attr($record, 'description')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupJob(string $identifier): ?array
    {
        $record = self::findRecord(Job::class, ['id', 'title'], $identifier);
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'title' => self::attr($record, 'title'),
            'amount' => self::money($record->getAttribute('amount')),
            'limit' => self::intOrNull($record->getAttribute('limit')),
            'completedCount' => self::intOrNull($record->getAttribute('completed_count')),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupJobSubmission(string $identifier): ?array
    {
        $record = self::findRecord(JobSubmission::class, ['id', 'job_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(JobSubmission::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'jobTitle' => self::relatedValue(Job::class, $record->getAttribute('job_id'), 'title'),
            'status' => self::attr($record, 'status'),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupVendorOrder(string $identifier): ?array
    {
        $record = self::findRecord(VendorOrder::class, ['id', 'order_no', 'tracking_link'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(VendorOrder::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'orderNo' => self::attr($record, 'order_no'),
            'user' => self::userSummary($record->getAttribute('user_id')),
            'vendorName' => self::relatedValue(VendorProfile::class, $record->getAttribute('vendor_profile_id'), 'vendor_name'),
            'productTitle' => self::relatedValue(Product::class, $record->getAttribute('product_id'), 'title'),
            'totalAmount' => self::money($record->getAttribute('total_amount')),
            'trackingLink' => self::attr($record, 'tracking_link'),
            'status' => self::attr($record, 'status'),
            'orderedAt' => self::date($record->getAttribute('ordered_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupVendorProfile(string $identifier): ?array
    {
        $record = self::findRecord(VendorProfile::class, ['id', 'vendor_name', 'service_charge_txn_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(VendorProfile::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'vendorName' => self::attr($record, 'vendor_name'),
            'address' => self::plainText(self::attr($record, 'address')),
            'status' => self::attr($record, 'status'),
            'serviceChargeAmount' => self::money($record->getAttribute('service_charge_amount')),
            'serviceChargeTxnId' => self::attr($record, 'service_charge_txn_id'),
            'reviewedAt' => self::date($record->getAttribute('reviewed_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupLeadershipClaim(string $identifier): ?array
    {
        $record = self::findRecord(LeadershipClaim::class, ['id', 'rank_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(LeadershipClaim::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'rankName' => self::relatedValue(LeadershipRank::class, $record->getAttribute('rank_id'), 'name'),
            'rewardAmount' => self::money($record->getAttribute('reward_amount')),
            'claimedAt' => self::date($record->getAttribute('claimed_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupTargetClaim(string $identifier): ?array
    {
        $record = self::findRecord(TargetClaim::class, ['id', 'campaign_id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(TargetClaim::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'campaignTitle' => self::relatedValue(TargetCampaign::class, $record->getAttribute('campaign_id'), 'title'),
            'amount' => self::money($record->getAttribute('amount')),
            'claimedAt' => self::date($record->getAttribute('claimed_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupTypingJobSubmission(string $identifier): ?array
    {
        $record = self::findRecord(TypingJobSubmission::class, ['id', 'user_answer', 'correct_answer'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(TypingJobSubmission::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'expression' => self::attr($record, 'expression'),
            'userAnswer' => self::attr($record, 'user_answer'),
            'correctAnswer' => self::attr($record, 'correct_answer'),
            'rewardAmount' => self::money($record->getAttribute('reward_amount')),
            'submittedAt' => self::date($record->getAttribute('submitted_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupWelcomeOfferClaim(string $identifier): ?array
    {
        $record = self::findRecord(WelcomeOfferClaim::class, ['id'], $identifier);
        if (!$record && ($user = self::findRecord(User::class, ['id', 'email', 'mobile', 'referral_code'], $identifier))) {
            $record = self::query(WelcomeOfferClaim::class)?->where('user_id', $user->id)->latest('id')->first();
        }
        if (!$record) {
            return null;
        }

        return [
            'id' => (int) $record->id,
            'user' => self::userSummary($record->getAttribute('user_id')),
            'amount' => self::money($record->getAttribute('reward_amount') ?? $record->getAttribute('amount')),
            'claimSource' => self::attr($record, 'claim_source'),
            'claimedAt' => self::date($record->getAttribute('claimed_at')),
            'createdAt' => self::date($record->getAttribute('created_at')),
            'updatedAt' => self::date($record->getAttribute('updated_at')),
        ];
    }

    private static function lookupFinanceDailySheet(string $date): ?array
    {
        $record = self::query(DailySheet::class)?->whereDate('sheet_date', $date)->first();
        if (!$record) {
            return null;
        }

        $entries = self::tableAvailable(DailyEntry::class)
            ? DailyEntry::query()->where('sheet_id', $record->id)->orderBy('id')->get()
            : collect();

        $totalIn = round((float) $entries->where('type', 'in')->sum('amount'), 2);
        $totalOut = round((float) $entries->where('type', 'out')->sum('amount'), 2);

        return [
            'id' => (int) $record->id,
            'sheetDate' => self::date($record->getAttribute('sheet_date')),
            'counts' => [
                'i' => self::intOrNull($record->getAttribute('count_i')),
                'b' => self::intOrNull($record->getAttribute('count_b')),
                'lab' => self::intOrNull($record->getAttribute('count_lab')),
                'loc' => self::intOrNull($record->getAttribute('count_loc')),
            ],
            'totalIn' => self::money($totalIn),
            'totalOut' => self::money($totalOut),
            'net' => self::money($totalIn - $totalOut),
            'notes' => self::plainText(self::attr($record, 'notes')),
            'entries' => $entries->map(fn (DailyEntry $entry): array => [
                'khat' => self::attr($entry, 'khat'),
                'type' => self::attr($entry, 'type'),
                'amount' => self::money($entry->getAttribute('amount')),
                'remark' => self::plainText(self::attr($entry, 'remark')),
            ])->all(),
        ];
    }

    /**
     * @template TModel of Model
     * @param class-string<TModel> $modelClass
     */
    private static function findRecord(string $modelClass, array $columns, string $identifier): ?Model
    {
        $query = self::query($modelClass);
        if (!$query) {
            return null;
        }

        $columns = array_values(array_filter($columns, function ($column) use ($modelClass, $identifier): bool {
            $column = (string) $column;
            if ($column === 'id' && !ctype_digit($identifier)) {
                return false;
            }

            return self::hasColumn($modelClass, $column);
        }));
        if ($columns === []) {
            return null;
        }

        $query->where(function (Builder $inner) use ($columns, $identifier): void {
            foreach ($columns as $column) {
                $inner->orWhere($column, $identifier);
            }
        });

        if ($modelClass === User::class && self::hasColumn(User::class, 'is_hidden')) {
            $query->where(function (Builder $inner): void {
                $inner->whereNull('is_hidden')->orWhere('is_hidden', 0);
            });
        }

        return $query->latest('id')->first();
    }

    /**
     * @template TModel of Model
     * @param class-string<TModel> $modelClass
     */
    private static function query(string $modelClass): ?Builder
    {
        if (!self::tableAvailable($modelClass)) {
            return null;
        }

        return $modelClass::query();
    }

    /**
     * @template TModel of Model
     * @param class-string<TModel> $modelClass
     */
    private static function firstModel(string $modelClass): ?Model
    {
        return self::query($modelClass)?->first();
    }

    /**
     * @template TModel of Model
     * @param class-string<TModel> $modelClass
     */
    private static function limitedRows(string $modelClass, int $limit, callable $scope)
    {
        $query = self::query($modelClass);
        if (!$query) {
            return collect();
        }

        $scope($query);

        return $query->limit($limit)->get();
    }

    private static function userSummary($userId): ?array
    {
        if (!$userId || !self::tableAvailable(User::class)) {
            return null;
        }

        $query = User::query()->where('id', $userId);
        if (self::hasColumn(User::class, 'is_hidden')) {
            $query->where(function (Builder $inner): void {
                $inner->whereNull('is_hidden')->orWhere('is_hidden', 0);
            });
        }

        $user = $query->first();
        if (!$user) {
            return null;
        }

        return [
            'id' => (int) $user->id,
            'name' => self::attr($user, 'name'),
            'referralCode' => self::attr($user, 'referral_code'),
            'activeStatus' => ((int) $user->getAttribute('is_active') === 1) ? 'active' : 'inactive',
            'bannedStatus' => ((int) $user->getAttribute('is_banned') === 1) ? 'banned' : 'clear',
        ];
    }

    private static function relatedValue(string $modelClass, $id, string $field): ?string
    {
        if (!$id || !self::tableAvailable($modelClass) || !self::hasColumn($modelClass, $field)) {
            return null;
        }

        $record = $modelClass::query()->where('id', $id)->first();

        return $record ? self::attr($record, $field) : null;
    }

    private static function relationCount(Model $model, string $relation): int
    {
        try {
            if (!method_exists($model, $relation)) {
                return 0;
            }

            return (int) $model->{$relation}()->count();
        } catch (\Throwable) {
            return 0;
        }
    }

    private static function tableAvailable(string $modelClass): bool
    {
        static $cache = [];

        if (array_key_exists($modelClass, $cache)) {
            return $cache[$modelClass];
        }

        try {
            $table = (new $modelClass())->getTable();
            $cache[$modelClass] = Schema::hasTable($table);
        } catch (\Throwable) {
            $cache[$modelClass] = false;
        }

        return $cache[$modelClass];
    }

    private static function hasColumn(string $modelClass, string $column): bool
    {
        static $cache = [];
        $key = $modelClass . ':' . $column;

        if (array_key_exists($key, $cache)) {
            return $cache[$key];
        }

        try {
            $table = (new $modelClass())->getTable();
            $cache[$key] = Schema::hasColumn($table, $column);
        } catch (\Throwable) {
            $cache[$key] = false;
        }

        return $cache[$key];
    }

    private static function attr(Model $model, string $field): ?string
    {
        $value = $model->getAttribute($field);
        if ($value === null || $value === '') {
            return null;
        }

        return (string) $value;
    }

    private static function date($value): ?string
    {
        if (!$value) {
            return null;
        }

        try {
            if ($value instanceof \DateTimeInterface) {
                return $value->format(DATE_ATOM);
            }

            return \Illuminate\Support\Carbon::parse($value)->format(DATE_ATOM);
        } catch (\Throwable) {
            return (string) $value;
        }
    }

    private static function money($value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }

        return number_format((float) $value, 2, '.', '');
    }

    private static function intOrNull($value): ?int
    {
        if ($value === null || $value === '') {
            return null;
        }

        return (int) $value;
    }

    private static function boolLabel($value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }

        return ((int) $value === 1) ? 'yes' : 'no';
    }

    private static function plainText(?string $value): ?string
    {
        if ($value === null) {
            return null;
        }

        $value = trim(strip_tags($value));
        $value = preg_replace('/\s+/', ' ', $value) ?? $value;

        return $value !== '' ? $value : null;
    }

    private static function maskPhone(?string $value): ?string
    {
        $value = preg_replace('/\D+/', '', (string) $value) ?? '';
        if ($value === '') {
            return null;
        }

        if (strlen($value) <= 5) {
            return str_repeat('*', strlen($value));
        }

        return substr($value, 0, 3) . str_repeat('*', max(strlen($value) - 5, 0)) . substr($value, -2);
    }

    private static function maskEmail(?string $value): ?string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return null;
        }

        if (!str_contains($value, '@')) {
            return self::maskPlain($value);
        }

        [$local, $domain] = explode('@', $value, 2);
        $visible = substr($local, 0, 2);

        return $visible . str_repeat('*', max(strlen($local) - 2, 3)) . '@' . $domain;
    }

    private static function maskPlain(?string $value): ?string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return null;
        }

        if (strlen($value) <= 4) {
            return str_repeat('*', strlen($value));
        }

        return substr($value, 0, 2) . str_repeat('*', max(strlen($value) - 4, 0)) . substr($value, -2);
    }

    private static function addressSummary(PdOrder $order): ?string
    {
        $parts = array_filter([
            self::attr($order, 'district'),
            self::attr($order, 'thana'),
            self::attr($order, 'union_name'),
            self::attr($order, 'village'),
        ]);

        return $parts ? implode(', ', $parts) : null;
    }
}
