<?php
/**
 * Education_Platform — EduBrain + پروفایل + جلسات + org + dispatch
 */
if ( ! defined( 'ABSPATH' ) ) exit;

require_once ACC_PATH . 'includes/helpers/education-cost-accounting.php';

class Education_Platform {

    public const REQUEST_STATUSES = [
        'submitted'          => 'ثبت‌شده — در انتظار آزمون',
        'placement_pending'  => 'آماده آزمون آنلاین',
        'placement_done'     => 'تعیین سطح انجام شد',
        'active'             => 'فعال — آماده رزرو',
        'cancelled'          => 'لغو شده',
    ];

    public const VERSION = '1.0';

    public const DELIVERY_MODES = [ 'virtual' => 'مجازی', 'in_person' => 'حضوری' ];
    public const VENUE_TYPES    = [
        'online'    => 'آنلاین',
        'school'    => 'مدرسه',
        'institute' => 'مؤسسه آموزشی',
        'home'      => 'منزل',
    ];
    public const SESSION_TYPES  = [ 'academic' => 'تحصیلی', 'skill' => 'مهارتی' ];
    public const TRACKS         = [
        'general'     => 'عمومی',
        'konkur'      => 'کنکور',
        'tizhooshan'  => 'تیزهوشان / سمپاد',
        'skill'       => 'مهارت',
    ];

    public static function skill_domains(): array {
        return [
            'math'       => 'ریاضی',
            'physics'    => 'فیزیک',
            'chemistry'  => 'شیمی',
            'biology'    => 'زیست',
            'persian'    => 'ادبیات فارسی',
            'english'    => 'زبان انگلیسی',
            'language'   => 'زبان خارجی',
            'music'      => 'موسیقی',
            'programming'=> 'برنامه‌نویسی',
            'art'        => 'هنر',
            'sport'      => 'ورزش',
        ];
    }

    public static function tbl( string $name ): string {
        global $wpdb;
        return $wpdb->prefix . 'edu_' . $name;
    }

    /* ── Meta ── */

    public static function public_meta(): array {
        require_once ACC_PATH . 'includes/helpers/education-assessment-bank.php';
        require_once ACC_PATH . 'includes/helpers/education-lifepath.php';
        return [
            'version'        => self::VERSION,
            'delivery_modes' => self::DELIVERY_MODES,
            'venue_types'    => self::VENUE_TYPES,
            'session_types'  => self::SESSION_TYPES,
            'tracks'         => self::TRACKS,
            'skill_domains'  => self::skill_domains(),
            'grade_levels'   => Edu_Assessment_Bank::grade_levels(),
            'learning_goals' => Edu_Assessment_Bank::learning_goals(),
            'request_schema' => Edu_Assessment_Bank::request_schema(),
            'request_statuses' => self::REQUEST_STATUSES,
            'budget_tiers'   => Edu_LifePath::BUDGET_TIERS,
            'career_catalog' => Edu_LifePath::CAREER_CATALOG,
            'facility_types' => Edu_LifePath::FACILITY_TYPES,
            'portal_label'   => 'ACC EduBrain',
        ];
    }

    public static function ensure_request_table(): void {
        global $wpdb;
        $t = self::tbl( 'service_requests' );
        $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t ) );
        if ( $exists === $t ) {
            return;
        }
        $charset = $wpdb->get_charset_collate();
        $wpdb->query( "CREATE TABLE IF NOT EXISTS {$t} (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
            learner_id BIGINT UNSIGNED NOT NULL,
            ref_code VARCHAR(24) NOT NULL DEFAULT '',
            session_type VARCHAR(20) NOT NULL DEFAULT 'academic',
            track VARCHAR(30) NOT NULL DEFAULT 'general',
            domain VARCHAR(40) NOT NULL DEFAULT 'math',
            grade_level VARCHAR(40) NOT NULL DEFAULT '',
            status VARCHAR(30) NOT NULL DEFAULT 'submitted',
            request_json JSON NULL,
            assessment_id BIGINT UNSIGNED NULL,
            created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME NULL,
            PRIMARY KEY (id),
            UNIQUE KEY ref_code (ref_code),
            KEY learner_status (learner_id, status)
        ) {$charset}" );
    }

    /* ── Learner profile ── */

    public static function get_or_create_learner( int $user_id ): array {
        global $wpdb;
        $t = self::tbl( 'learners' );
        $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$t} WHERE user_id = %d", $user_id ), ARRAY_A );
        if ( $row ) {
            $row['profile'] = json_decode( $row['profile_json'] ?? '{}', true ) ?: [];
            return $row;
        }
        require_once ACC_PATH . 'includes/helpers/education-lifepath.php';
        $wpdb->insert( $t, [
            'user_id'      => $user_id,
            'grade_level'  => '',
            'track'        => 'general',
            'profile_json' => wp_json_encode( Edu_LifePath::default_profile(), JSON_UNESCAPED_UNICODE ),
            'created_at'   => current_time( 'mysql' ),
        ] );
        return self::get_or_create_learner( $user_id );
    }

    public static function update_learner( int $user_id, array $data ): array {
        global $wpdb;
        $t   = self::tbl( 'learners' );
        $row = self::get_or_create_learner( $user_id );
        require_once ACC_PATH . 'includes/helpers/education-lifepath.php';
        $profile = Edu_LifePath::merge_profile( $row['profile'] ?? [], $data['profile'] ?? [] );
        if ( isset( $data['profile'] ) && is_array( $data['profile'] ) ) {
            // merge_profile handles structured sections
        } elseif ( isset( $data['identity'] ) || isset( $data['academic_history'] ) || isset( $data['career'] ) || isset( $data['family'] ) ) {
            $profile = Edu_LifePath::merge_profile( $profile, $data );
        }
        if ( isset( $data['goals'] ) && is_array( $data['goals'] ) ) {
            $profile['goals'] = array_values( $data['goals'] );
        }
        $upd = [
            'profile_json' => wp_json_encode( $profile, JSON_UNESCAPED_UNICODE ),
            'updated_at'   => current_time( 'mysql' ),
        ];
        if ( isset( $data['grade_level'] ) ) {
            $upd['grade_level'] = sanitize_text_field( $data['grade_level'] );
        }
        if ( isset( $data['track'] ) && isset( self::TRACKS[ $data['track'] ] ) ) {
            $upd['track'] = sanitize_key( $data['track'] );
        }
        if ( isset( $data['school_org_id'] ) ) {
            $upd['school_org_id'] = (int) $data['school_org_id'] ?: null;
        }
        $wpdb->update( $t, $upd, [ 'user_id' => $user_id ] );
        return self::get_or_create_learner( $user_id );
    }

    public static function add_learner_log( int $user_id, string $log_type, string $category, array $payload ): int {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        $table   = $log_type === 'skill' ? self::tbl( 'learner_skill_log' ) : self::tbl( 'learner_academic_log' );
        $wpdb->insert( $table, [
            'learner_id'  => (int) $learner['id'],
            'category'    => sanitize_key( $category ),
            'title'       => sanitize_text_field( $payload['title'] ?? '' ),
            'payload_json'=> wp_json_encode( $payload, JSON_UNESCAPED_UNICODE ),
            'entry_date'  => sanitize_text_field( $payload['entry_date'] ?? current_time( 'Y-m-d' ) ),
            'created_at'  => current_time( 'mysql' ),
        ] );
        return (int) $wpdb->insert_id;
    }

    public static function learner_timeline( int $user_id ): array {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        $lid = (int) $learner['id'];
        $academic = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'learner_academic_log' ) . " WHERE learner_id=%d ORDER BY entry_date DESC, id DESC LIMIT 100", $lid
        ), ARRAY_A ) ?: [];
        $skill = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'learner_skill_log' ) . " WHERE learner_id=%d ORDER BY entry_date DESC, id DESC LIMIT 100", $lid
        ), ARRAY_A ) ?: [];
        return [ 'learner' => $learner, 'academic' => $academic, 'skill' => $skill ];
    }

    /* ── Educator profile ── */

    public static function get_or_create_educator( int $user_id ): array {
        global $wpdb;
        $t = self::tbl( 'educators' );
        $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$t} WHERE user_id = %d", $user_id ), ARRAY_A );
        if ( $row ) {
            $row['profile'] = json_decode( $row['profile_json'] ?? '{}', true ) ?: [];
            $row['delivery_modes'] = json_decode( $row['delivery_modes_json'] ?? '[]', true ) ?: [];
            $row['venue_types'] = json_decode( $row['venue_types_json'] ?? '[]', true ) ?: [];
            return $row;
        }
        $wpdb->insert( $t, [
            'user_id'             => $user_id,
            'educator_type'       => 'mentor',
            'verified_status'     => 'pending',
            'profile_json'        => wp_json_encode( [ 'academic_cv' => [], 'skill_cv' => [] ], JSON_UNESCAPED_UNICODE ),
            'delivery_modes_json' => wp_json_encode( [ 'virtual', 'in_person' ] ),
            'venue_types_json'    => wp_json_encode( [ 'school', 'institute', 'home' ] ),
            'created_at'          => current_time( 'mysql' ),
        ] );
        return self::get_or_create_educator( $user_id );
    }

    public static function update_educator( int $user_id, array $data ): array {
        global $wpdb;
        $t = self::tbl( 'educators' );
        self::get_or_create_educator( $user_id );
        $current = self::get_or_create_educator( $user_id );
        $upd = [ 'updated_at' => current_time( 'mysql' ) ];
        if ( isset( $data['profile'] ) && is_array( $data['profile'] ) ) {
            $upd['profile_json'] = wp_json_encode(
                array_merge( $current['profile'] ?? [], $data['profile'] ),
                JSON_UNESCAPED_UNICODE
            );
        }
        if ( isset( $data['educator_type'] ) ) {
            $upd['educator_type'] = in_array( $data['educator_type'], [ 'teacher', 'mentor' ], true ) ? $data['educator_type'] : 'mentor';
        }
        if ( isset( $data['delivery_modes'] ) ) {
            $upd['delivery_modes_json'] = wp_json_encode( array_values( $data['delivery_modes'] ), JSON_UNESCAPED_UNICODE );
        }
        if ( isset( $data['venue_types'] ) ) {
            $upd['venue_types_json'] = wp_json_encode( array_values( $data['venue_types'] ), JSON_UNESCAPED_UNICODE );
        }
        if ( isset( $data['hourly_rate'] ) ) {
            $upd['hourly_rate'] = max( 0, (float) $data['hourly_rate'] );
        }
        $wpdb->update( $t, $upd, [ 'user_id' => $user_id ] );
        return self::get_or_create_educator( $user_id );
    }

    public static function list_educators( array $filters = [] ): array {
        global $wpdb;
        $t = self::tbl( 'educators' );
        $u = $wpdb->users;
        $where = [ '1=1' ];
        if ( ! empty( $filters['verified'] ) ) {
            $where[] = "e.verified_status = 'verified'";
        }
        $sql = "SELECT e.*, u.display_name FROM {$t} e INNER JOIN {$u} u ON u.ID = e.user_id WHERE " . implode( ' AND ', $where ) . " ORDER BY e.rating_avg DESC, e.id DESC LIMIT 50";
        $rows = $wpdb->get_results( $sql, ARRAY_A ) ?: [];
        foreach ( $rows as &$r ) {
            $r['profile'] = json_decode( $r['profile_json'] ?? '{}', true ) ?: [];
        }
        return $rows;
    }

    /* ── Organizations ── */

    public static function list_orgs( ?string $type = null ): array {
        global $wpdb;
        $t = self::tbl( 'organizations' );
        $rows = $type
            ? $wpdb->get_results( $wpdb->prepare(
                "SELECT * FROM {$t} WHERE org_type = %s AND is_active = 1 ORDER BY name", $type
            ), ARRAY_A )
            : $wpdb->get_results( "SELECT * FROM {$t} WHERE is_active = 1 ORDER BY org_type, name", ARRAY_A );
        foreach ( $rows ?: [] as &$r ) {
            $r['profile'] = json_decode( $r['profile_json'] ?? '{}', true ) ?: [];
        }
        unset( $r );
        return $rows ?: [];
    }

    public static function get_org( int $id ): ?array {
        global $wpdb;
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'organizations' ) . " WHERE id = %d", $id
        ), ARRAY_A );
        if ( ! $row ) {
            return null;
        }
        $row['profile'] = json_decode( $row['profile_json'] ?? '{}', true ) ?: [];
        return $row;
    }

    public static function update_org( int $org_id, array $data ): ?array {
        global $wpdb;
        $t = self::tbl( 'organizations' );
        $row = self::get_org( $org_id );
        if ( ! $row ) {
            return null;
        }
        $profile = $row['profile'] ?? [];
        if ( isset( $data['profile'] ) && is_array( $data['profile'] ) ) {
            $profile = array_merge( $profile, $data['profile'] );
        }
        if ( isset( $data['facilities'] ) ) {
            $profile['facilities'] = array_values( array_map( 'sanitize_key', (array) $data['facilities'] ) );
        }
        if ( isset( $data['facility_details'] ) ) {
            $profile['facility_details'] = $data['facility_details'];
        }
        if ( isset( $data['programs'] ) ) {
            $profile['programs'] = array_values( array_map( 'sanitize_text_field', (array) $data['programs'] ) );
        }
        $upd = [
            'profile_json' => wp_json_encode( $profile, JSON_UNESCAPED_UNICODE ),
        ];
        if ( isset( $data['name'] ) ) {
            $upd['name'] = sanitize_text_field( $data['name'] );
        }
        if ( isset( $data['city'] ) ) {
            $upd['city'] = sanitize_text_field( $data['city'] );
        }
        if ( isset( $data['address_text'] ) ) {
            $upd['address_text'] = sanitize_textarea_field( $data['address_text'] );
        }
        $wpdb->update( $t, $upd, [ 'id' => $org_id ] );
        return self::get_org( $org_id );
    }

    public static function org_for_user( int $user_id ): ?array {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        if ( ! empty( $learner['school_org_id'] ) ) {
            return self::get_org( (int) $learner['school_org_id'] );
        }
        $orgs = self::list_orgs();
        return $orgs[0] ?? null;
    }

    public static function org_resources( int $org_id ): array {
        global $wpdb;
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'org_resources' ) . " WHERE org_id = %d AND is_active = 1 ORDER BY name", $org_id
        ), ARRAY_A ) ?: [];
    }

    public static function org_schedule( int $org_id, ?string $from = null, ?string $to = null ): array {
        global $wpdb;
        $t = self::tbl( 'org_schedule' );
        $conds = [ 'org_id = %d' ];
        $args  = [ $org_id ];
        if ( $from ) {
            $conds[] = 'slot_date >= %s';
            $args[]  = $from;
        }
        if ( $to ) {
            $conds[] = 'slot_date <= %s';
            $args[]  = $to;
        }
        return $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM {$t} WHERE " . implode( ' AND ', $conds ) . " ORDER BY slot_date, start_time LIMIT 200",
            ...$args
        ), ARRAY_A ) ?: [];
    }

    public static function save_org_schedule_slot( int $org_id, array $data ): array {
        global $wpdb;
        $t = self::tbl( 'org_schedule' );
        $wpdb->insert( $t, [
            'org_id'      => $org_id,
            'resource_id' => (int) ( $data['resource_id'] ?? 0 ) ?: null,
            'slot_date'   => sanitize_text_field( $data['slot_date'] ?? current_time( 'Y-m-d' ) ),
            'start_time'  => sanitize_text_field( $data['start_time'] ?? '09:00' ),
            'end_time'    => sanitize_text_field( $data['end_time'] ?? '11:00' ),
            'status'      => 'available',
            'price_override' => isset( $data['price'] ) ? (float) $data['price'] : null,
            'created_at'  => current_time( 'mysql' ),
        ] );
        return [ 'success' => true, 'id' => (int) $wpdb->insert_id ];
    }

    /* ── Sessions (Snapp-like) ── */

    public static function create_session_request( int $learner_user_id, array $data ): array {
        global $wpdb;
        $learner = self::get_or_create_learner( $learner_user_id );
        $delivery = sanitize_key( $data['delivery_mode'] ?? 'virtual' );
        $venue    = sanitize_key( $data['venue_type'] ?? ( $delivery === 'virtual' ? 'online' : 'home' ) );
        $stype    = sanitize_key( $data['session_type'] ?? 'academic' );
        $domain   = sanitize_key( $data['domain'] ?? 'math' );
        $duration = max( 30, min( 180, (int) ( $data['duration_min'] ?? 90 ) ) );
        $distance_km = (float) ( $data['distance_km'] ?? 0 );

        if ( $distance_km <= 0 && $venue === 'home' ) {
            require_once ACC_PATH . 'includes/helpers/education-gis.php';
            $distance_km = Edu_GIS::distance_for_session( $learner['profile'] ?? [], (int) ( $data['org_id'] ?? 0 ) );
            if ( $distance_km <= 0 && ! empty( $data['org_id'] ) ) {
                $org = $wpdb->get_row( $wpdb->prepare(
                    "SELECT lat, lng FROM " . self::tbl( 'organizations' ) . " WHERE id = %d",
                    (int) $data['org_id']
                ), ARRAY_A );
                $hlat = (float) ( $learner['profile']['home_lat'] ?? 0 );
                $hlng = (float) ( $learner['profile']['home_lng'] ?? 0 );
                if ( $org && $hlat && $org['lat'] ) {
                    $distance_km = Edu_GIS::haversine_km( $hlat, $hlng, (float) $org['lat'], (float) $org['lng'] );
                }
            }
            $data['distance_km'] = $distance_km;
        }

        $quote = Edu_Cost_Accounting::quote_session( [
            'delivery_mode'  => $delivery,
            'venue_type'     => $venue,
            'org_id'         => (int) ( $data['org_id'] ?? 0 ),
            'resource_id'    => (int) ( $data['resource_id'] ?? 0 ),
            'distance_km'    => (float) ( $data['distance_km'] ?? 0 ),
            'duration_min'   => $duration,
            'materials_level'=> sanitize_key( $data['materials_level'] ?? 'standard' ),
            'educator_id'    => (int) ( $data['educator_id'] ?? 0 ),
        ] );

        $wpdb->insert( self::tbl( 'sessions' ), [
            'learner_id'       => (int) $learner['id'],
            'session_type'     => $stype,
            'track'            => sanitize_key( $data['track'] ?? $learner['track'] ?? 'general' ),
            'domain'           => $domain,
            'delivery_mode'    => $delivery,
            'venue_type'       => $venue,
            'org_id'           => (int) ( $data['org_id'] ?? 0 ) ?: null,
            'resource_id'      => (int) ( $data['resource_id'] ?? 0 ) ?: null,
            'address_text'     => sanitize_textarea_field( $data['address_text'] ?? '' ),
            'distance_km'      => (float) ( $data['distance_km'] ?? 0 ),
            'learner_lat'      => isset( $learner['profile']['home_lat'] ) ? (float) $learner['profile']['home_lat'] : null,
            'learner_lng'      => isset( $learner['profile']['home_lng'] ) ? (float) $learner['profile']['home_lng'] : null,
            'scheduled_at'     => sanitize_text_field( $data['scheduled_at'] ?? '' ) ?: null,
            'duration_min'     => $duration,
            'status'           => 'submitted',
            'notes'            => sanitize_textarea_field( $data['notes'] ?? '' ),
            'quote_json'       => wp_json_encode( $quote, JSON_UNESCAPED_UNICODE ),
            'amount_total'     => (float) ( $quote['total'] ?? 0 ),
            'created_at'       => current_time( 'mysql' ),
        ] );
        $sid = (int) $wpdb->insert_id;
        return [ 'success' => true, 'session_id' => $sid, 'quote' => $quote ];
    }

    public static function dispatch_queue( ?int $educator_user_id = null ): array {
        global $wpdb;
        $t = self::tbl( 'sessions' );
        if ( $educator_user_id ) {
            $ed = self::get_or_create_educator( $educator_user_id );
            return $wpdb->get_results( $wpdb->prepare(
                "SELECT s.*, l.user_id AS learner_user_id FROM {$t} s
                 INNER JOIN " . self::tbl( 'learners' ) . " l ON l.id = s.learner_id
                 WHERE s.educator_id = %d AND s.status IN ('assigned','confirmed','in_progress')
                 ORDER BY s.scheduled_at", (int) $ed['id']
            ), ARRAY_A ) ?: [];
        }
        return $wpdb->get_results(
            "SELECT s.*, l.user_id AS learner_user_id FROM {$t} s
             INNER JOIN " . self::tbl( 'learners' ) . " l ON l.id = s.learner_id
             WHERE s.status IN ('submitted','matching') ORDER BY s.id DESC LIMIT 50",
            ARRAY_A
        ) ?: [];
    }

    public static function assign_session( int $session_id, int $educator_user_id ): array {
        global $wpdb;
        $ed = self::get_or_create_educator( $educator_user_id );
        $wpdb->update( self::tbl( 'sessions' ), [
            'educator_id' => (int) $ed['id'],
            'status'      => 'assigned',
            'updated_at'  => current_time( 'mysql' ),
        ], [ 'id' => $session_id, 'status' => 'submitted' ] );
        if ( ! $wpdb->rows_affected ) {
            return [ 'success' => false, 'message' => 'جلسه قابل تخصیص نیست' ];
        }
        return [ 'success' => true, 'session_id' => $session_id ];
    }

    public static function complete_session( int $session_id, int $actor_user_id, array $report = [] ): array {
        global $wpdb;
        $s = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM " . self::tbl( 'sessions' ) . " WHERE id = %d", $session_id ), ARRAY_A );
        if ( ! $s ) {
            return [ 'success' => false, 'message' => 'جلسه یافت نشد' ];
        }
        $wpdb->update( self::tbl( 'sessions' ), [
            'status'       => 'completed',
            'report_json'  => wp_json_encode( $report, JSON_UNESCAPED_UNICODE ),
            'completed_at' => current_time( 'mysql' ),
        ], [ 'id' => $session_id ] );

        require_once ACC_PATH . 'includes/helpers/education-cost-accounting.php';
        $acc = Edu_Cost_Accounting::on_session_completed( $s, $report );

        $learner = $wpdb->get_row( $wpdb->prepare( "SELECT user_id FROM " . self::tbl( 'learners' ) . " WHERE id = %d", (int) $s['learner_id'] ), ARRAY_A );
        if ( $learner ) {
            $log_type = ( $s['session_type'] ?? '' ) === 'skill' ? 'skill' : 'academic';
            self::add_learner_log( (int) $learner['user_id'], $log_type, $s['domain'] ?? 'general', [
                'title'      => 'جلسه تکمیل‌شده #' . $session_id,
                'session_id' => $session_id,
                'report'     => $report,
            ] );
        }
        return [ 'success' => true, 'session_id' => $session_id, 'accounting' => $acc ];
    }

    /* ── Service requests (Enrollment → Placement) ── */

    public static function next_request_ref(): string {
        global $wpdb;
        self::ensure_request_table();
        $n = (int) $wpdb->get_var( "SELECT COUNT(*) FROM " . self::tbl( 'service_requests' ) ) + 1;
        return 'REQ-' . gmdate( 'Y' ) . '-' . str_pad( (string) $n, 5, '0', STR_PAD_LEFT );
    }

    public static function create_service_request( int $user_id, array $data ): array {
        global $wpdb;
        self::ensure_request_table();
        require_once ACC_PATH . 'includes/helpers/education-assessment-bank.php';

        $learner = self::get_or_create_learner( $user_id );
        $stype   = sanitize_key( $data['session_type'] ?? 'academic' );
        if ( ! isset( self::SESSION_TYPES[ $stype ] ) ) {
            $stype = 'academic';
        }
        $track = sanitize_key( $data['track'] ?? 'general' );
        if ( ! isset( self::TRACKS[ $track ] ) ) {
            $track = $stype === 'skill' ? 'skill' : 'konkur';
        }
        $domain = sanitize_key( $data['domain'] ?? 'math' );
        $grade  = sanitize_text_field( $data['grade_level'] ?? '' );

        $payload = [
            'learner'  => [
                'full_name'   => sanitize_text_field( $data['full_name'] ?? '' ),
                'grade_level' => $grade,
                'school_name' => sanitize_text_field( $data['school_name'] ?? '' ),
            ],
            'program'  => [
                'session_type' => $stype,
                'track'        => $track,
                'domain'       => $domain,
                'goals'        => array_values( array_map( 'sanitize_key', (array) ( $data['goals'] ?? [] ) ) ),
            ],
            'delivery' => [
                'delivery_mode' => sanitize_key( $data['delivery_mode'] ?? 'virtual' ),
                'venue_type'    => sanitize_key( $data['venue_type'] ?? 'online' ),
                'weekly_hours'  => sanitize_text_field( $data['weekly_hours'] ?? '' ),
                'notes'         => sanitize_textarea_field( $data['notes'] ?? '' ),
            ],
            'consent'  => [ 'privacy' => ! empty( $data['consent_privacy'] ) ],
        ];

        self::update_learner( $user_id, [
            'grade_level' => $grade,
            'track'       => $track,
            'profile'     => [
                'goals'       => array_map( fn( $g ) => Edu_Assessment_Bank::learning_goals()[ $g ] ?? $g, $payload['program']['goals'] ),
                'school_name' => $payload['learner']['school_name'],
            ],
        ] );

        $ref = self::next_request_ref();
        $wpdb->insert( self::tbl( 'service_requests' ), [
            'learner_id'   => (int) $learner['id'],
            'ref_code'     => $ref,
            'session_type' => $stype,
            'track'        => $track,
            'domain'       => $domain,
            'grade_level'  => $grade,
            'status'       => 'placement_pending',
            'request_json' => wp_json_encode( $payload, JSON_UNESCAPED_UNICODE ),
            'created_at'   => current_time( 'mysql' ),
        ] );
        $rid = (int) $wpdb->insert_id;

        return [
            'success'    => true,
            'request_id' => $rid,
            'ref_code'   => $ref,
            'status'     => 'placement_pending',
            'next_step'  => 'online_test',
        ];
    }

    public static function get_service_request( int $request_id, int $user_id ): ?array {
        global $wpdb;
        self::ensure_request_table();
        $learner = self::get_or_create_learner( $user_id );
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'service_requests' ) . " WHERE id = %d AND learner_id = %d",
            $request_id, (int) $learner['id']
        ), ARRAY_A );
        if ( ! $row ) {
            return null;
        }
        $row['request'] = json_decode( $row['request_json'] ?? '{}', true ) ?: [];
        return $row;
    }

    public static function list_service_requests( int $user_id, int $limit = 20 ): array {
        global $wpdb;
        self::ensure_request_table();
        $learner = self::get_or_create_learner( $user_id );
        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'service_requests' ) . " WHERE learner_id = %d ORDER BY id DESC LIMIT %d",
            (int) $learner['id'], $limit
        ), ARRAY_A ) ?: [];
        foreach ( $rows as &$r ) {
            $r['request'] = json_decode( $r['request_json'] ?? '{}', true ) ?: [];
        }
        unset( $r );
        return $rows;
    }

    public static function get_assessment_test( int $request_id, int $user_id ): array {
        $req = self::get_service_request( $request_id, $user_id );
        if ( ! $req ) {
            return [ 'success' => false, 'message' => 'درخواست یافت نشد' ];
        }
        if ( $req['status'] === 'placement_done' || $req['status'] === 'active' ) {
            return [ 'success' => false, 'message' => 'آزمون قبلاً انجام شده', 'status' => $req['status'] ];
        }
        require_once ACC_PATH . 'includes/helpers/education-assessment-bank.php';
        $test = Edu_Assessment_Bank::build_test( $req['session_type'], $req['domain'], $req['track'] );
        return [
            'success'      => true,
            'request_id'   => $request_id,
            'ref_code'     => $req['ref_code'],
            'session_type' => $req['session_type'],
            'track'        => $req['track'],
            'domain'       => $req['domain'],
            'domain_label' => self::skill_domains()[ $req['domain'] ] ?? $req['domain'],
            'phases'       => $test['phases'],
        ];
    }

    public static function submit_assessment( int $request_id, int $user_id, array $answers ): array {
        global $wpdb;
        $req = self::get_service_request( $request_id, $user_id );
        if ( ! $req ) {
            return [ 'success' => false, 'message' => 'درخواست یافت نشد' ];
        }
        require_once ACC_PATH . 'includes/helpers/education-assessment-bank.php';

        $domain = $req['domain'];
        $stype  = $req['session_type'];
        $track  = $req['track'];
        $test   = Edu_Assessment_Bank::build_test( $stype, $domain, $track );
        $results = [ 'request_id' => $request_id, 'phases' => [] ];
        $mastery = [];
        $weak    = [];

        foreach ( $test['phases'] as $phase ) {
            $type = $phase['type'];
            $qs   = $phase['questions'];
            if ( $type === Edu_Assessment_Bank::TYPE_ACADEMIC_PLACEMENT ) {
                $sc = Edu_Assessment_Bank::score_academic( $qs, $answers );
                $sc['mastery'] = [ $domain => round( $sc['score_pct'] / 100, 2 ) ];
                $mastery[ $domain ] = $sc['mastery'][ $domain ];
                if ( $sc['score_pct'] < 60 ) {
                    $weak[] = [
                        'domain'  => $domain,
                        'label'   => self::skill_domains()[ $domain ] ?? $domain,
                        'mastery' => $mastery[ $domain ],
                    ];
                }
                $results['phases'][] = array_merge( $sc, [ 'type' => $type ] );
            } elseif ( $type === Edu_Assessment_Bank::TYPE_SKILL_TALENT ) {
                $results['phases'][] = array_merge(
                    Edu_Assessment_Bank::score_talent( $qs, $answers ),
                    [ 'type' => $type ]
                );
            } elseif ( $type === Edu_Assessment_Bank::TYPE_SKILL_LEVEL ) {
                $sl = Edu_Assessment_Bank::score_skill_level( $qs, $answers );
                $mastery[ $domain ] = round( $sl['level_pct'] / 100, 2 );
                $results['phases'][] = array_merge( $sl, [ 'type' => $type ] );
            }
        }

        $assess_type = $stype === 'skill' ? 'skill_placement' : 'academic_placement';
        $wpdb->insert( self::tbl( 'assessments' ), [
            'learner_id'   => (int) $req['learner_id'],
            'assess_type'  => $assess_type,
            'track'        => $track,
            'results_json' => wp_json_encode( array_merge( $results, [
                'mastery'    => $mastery,
                'weaknesses' => $weak,
                'domain'     => $domain,
            ] ), JSON_UNESCAPED_UNICODE ),
            'created_at'   => current_time( 'mysql' ),
        ] );
        $aid = (int) $wpdb->insert_id;

        $learner = self::get_or_create_learner( $user_id );
        if ( ! empty( $mastery ) ) {
            $plan = self::build_learning_plan( $learner, $mastery, $weak );
            $wpdb->insert( self::tbl( 'learning_plans' ), [
                'learner_id' => (int) $learner['id'],
                'track'      => $track,
                'plan_json'  => wp_json_encode( $plan, JSON_UNESCAPED_UNICODE ),
                'is_active'  => 1,
                'created_at' => current_time( 'mysql' ),
            ] );
            $results['plan'] = $plan;
        }

        $wpdb->update( self::tbl( 'service_requests' ), [
            'status'        => 'placement_done',
            'assessment_id' => $aid,
            'updated_at'    => current_time( 'mysql' ),
        ], [ 'id' => $request_id ] );

        self::add_learner_log( $user_id, $stype === 'skill' ? 'skill' : 'academic', $domain, [
            'title'      => 'تعیین سطح — ' . ( self::skill_domains()[ $domain ] ?? $domain ),
            'ref_code'   => $req['ref_code'],
            'assessment' => $results,
        ] );

        return [
            'success'       => true,
            'assessment_id' => $aid,
            'results'       => $results,
            'mastery'       => $mastery,
            'weaknesses'    => $weak,
            'status'        => 'placement_done',
        ];
    }

    /* ── EduBrain lite: placement + plan ── */

    public static function run_placement( int $user_id, array $answers ): array {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        $domains = self::skill_domains();
        $mastery = [];
        $weak    = [];
        foreach ( $answers as $domain => $score ) {
            $pct = max( 0, min( 100, (int) $score ) );
            $mastery[ $domain ] = round( $pct / 100, 2 );
            if ( $pct < 60 ) {
                $weak[] = [ 'domain' => $domain, 'label' => $domains[ $domain ] ?? $domain, 'mastery' => $mastery[ $domain ] ];
            }
        }
        usort( $weak, fn( $a, $b ) => $a['mastery'] <=> $b['mastery'] );
        $wpdb->insert( self::tbl( 'assessments' ), [
            'learner_id'   => (int) $learner['id'],
            'assess_type'  => 'placement',
            'track'        => $learner['track'] ?? 'general',
            'results_json' => wp_json_encode( [ 'mastery' => $mastery, 'weaknesses' => $weak ], JSON_UNESCAPED_UNICODE ),
            'created_at'   => current_time( 'mysql' ),
        ] );
        $plan = self::build_learning_plan( $learner, $mastery, $weak );
        $wpdb->insert( self::tbl( 'learning_plans' ), [
            'learner_id' => (int) $learner['id'],
            'track'      => $learner['track'] ?? 'general',
            'plan_json'  => wp_json_encode( $plan, JSON_UNESCAPED_UNICODE ),
            'is_active'  => 1,
            'created_at' => current_time( 'mysql' ),
        ] );
        return [
            'mastery'    => $mastery,
            'weaknesses' => array_slice( $weak, 0, 5 ),
            'plan'       => $plan,
        ];
    }

    public static function build_learning_plan( array $learner, array $mastery, array $weak ): array {
        $track = $learner['track'] ?? 'general';
        $weeks = [];
        $focus = array_slice( $weak, 0, 3 );
        foreach ( $focus as $i => $w ) {
            $weeks[] = [
                'week'     => $i + 1,
                'domain'   => $w['domain'],
                'label'    => $w['label'],
                'goal'     => 'رساندن تسلط به ۷۰٪',
                'tasks'    => [
                    '۲ جلسه remedial ' . ( $w['label'] ?? '' ),
                    '۱ Mock موضوعی',
                    'تمرین هدفمند ۳۰ سؤال',
                ],
            ];
        }
        if ( $track === 'konkur' ) {
            $weeks[] = [ 'week' => count( $weeks ) + 1, 'label' => 'Mock کنکور', 'goal' => 'آزمون جامع', 'tasks' => [ 'Mock ۴ درس', 'تحلیل CDM' ] ];
        }
        if ( $track === 'tizhooshan' ) {
            $weeks[] = [ 'week' => count( $weeks ) + 1, 'label' => 'استدلال و الگو', 'goal' => 'تیزهوشان', 'tasks' => [ 'آزمون استدلال', 'مسائل Olympiad-style' ] ];
        }
        return [
            'track'       => $track,
            'weeks'       => $weeks,
            'generated_at'=> current_time( 'mysql' ),
            'ai_note'     => 'برنامه بر اساس placement و بین‌المللی EduLoop/CDM',
        ];
    }

    public static function active_plan( int $user_id ): ?array {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'learning_plans' ) . " WHERE learner_id = %d AND is_active = 1 ORDER BY id DESC LIMIT 1",
            (int) $learner['id']
        ), ARRAY_A );
        if ( ! $row ) {
            return null;
        }
        $row['plan'] = json_decode( $row['plan_json'] ?? '{}', true ) ?: [];
        return $row;
    }

    public static function list_assessments( int $user_id, int $limit = 20 ): array {
        global $wpdb;
        $learner = self::get_or_create_learner( $user_id );
        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'assessments' ) . " WHERE learner_id = %d ORDER BY id DESC LIMIT %d",
            (int) $learner['id'], $limit
        ), ARRAY_A ) ?: [];
        foreach ( $rows as &$r ) {
            $r['results'] = json_decode( $r['results_json'] ?? '{}', true ) ?: [];
        }
        unset( $r );
        return $rows;
    }

    public static function get_session( int $session_id ): ?array {
        global $wpdb;
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . self::tbl( 'sessions' ) . " WHERE id = %d", $session_id
        ), ARRAY_A );
        if ( ! $row ) {
            return null;
        }
        $row['quote'] = json_decode( $row['quote_json'] ?? '{}', true ) ?: [];
        $row['costs'] = json_decode( $row['cost_json'] ?? '{}', true ) ?: [];
        $row['report'] = json_decode( $row['report_json'] ?? '{}', true ) ?: [];
        return $row;
    }

    /** وضعیت EduBrain برای UI — CDM · برنامه · تاریخچه */
    public static function brain_state( int $user_id ): array {
        $learner = self::get_or_create_learner( $user_id );
        $assessments = self::list_assessments( $user_id, 5 );
        $plan = self::active_plan( $user_id );
        $mastery = [];
        $weaknesses = [];
        if ( ! empty( $assessments[0]['results']['mastery'] ) ) {
            $mastery = $assessments[0]['results']['mastery'];
            $weaknesses = $assessments[0]['results']['weaknesses'] ?? [];
        }
        return [
            'learner'     => $learner,
            'mastery'     => $mastery,
            'weaknesses'  => $weaknesses,
            'assessments' => $assessments,
            'plan'        => $plan,
            'frameworks'  => [
                'cdm'       => 'Cognitive Diagnostic Model — تشخیص ضعف موضوعی',
                'gdina'     => 'G-DINA — تعامل مهارت‌ها (نمایش ماتریس)',
                'aleks'     => 'ALEKS/KST — مسیر یادگیری knowledge space',
                'eduloop'   => 'EduLoop — چرخه Placement → Plan → Session → Assess',
            ],
        ];
    }

    public static function dashboard( int $user_id, string $role ): array {
        $out = [ 'meta' => self::public_meta(), 'role' => $role ];
        if ( $role === 'learner' ) {
            $out['learner']  = self::get_or_create_learner( $user_id );
            $out['timeline'] = self::learner_timeline( $user_id );
            $out['plan']     = self::active_plan( $user_id );
            self::ensure_request_table();
            $out['requests'] = self::list_service_requests( $user_id, 10 );
            global $wpdb;
            $lid = (int) $out['learner']['id'];
            $out['sessions'] = $wpdb->get_results( $wpdb->prepare(
                "SELECT * FROM " . self::tbl( 'sessions' ) . " WHERE learner_id = %d ORDER BY id DESC LIMIT 20", $lid
            ), ARRAY_A ) ?: [];
        } elseif ( in_array( $role, [ 'mentor', 'teacher' ], true ) ) {
            $out['educator'] = self::get_or_create_educator( $user_id );
            $out['queue']     = self::dispatch_queue( $user_id );
            $out['pending']    = self::dispatch_queue();
        } elseif ( $role === 'org_admin' ) {
            $out['organizations'] = self::list_orgs();
        } elseif ( $role === 'accountant' ) {
            require_once ACC_PATH . 'includes/helpers/education-cost-accounting.php';
            $out['accounting'] = Edu_Cost_Accounting::pending_queue();
        } elseif ( $role === 'parent' ) {
            require_once ACC_PATH . 'includes/helpers/education-companion-extras.php';
            $out['parent'] = Edu_Companion_Extras::parent_dashboard( $user_id );
        }
        return $out;
    }
}
