<?php
/**
 * Edu_Cost_Accounting — بهای تمام‌شده جلسات آموزشی
 * حق‌الزحمه · ایاب‌ذهاب · سربار · مواد · اجاره فضا · کارمزد پلتفرم
 * اتصال به Acc_Event_Engine + Acc_Portal_Accounting (education)
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class Edu_Cost_Accounting {

    public const GL = [
        'bank'              => 4113,
        'ar'                => 4121,
        'revenue_academic'  => 4141,
        'revenue_skill'     => 4142,
        'mentor_expense'    => 4151,
        'transport_expense' => 4152,
        'materials_expense' => 4153,
        'overhead_expense'  => 4154,
        'venue_expense'     => 4155,
        'mentor_payable'    => 4161,
        'org_payable'       => 4162,
        'transport_payable' => 4163,
        'platform_revenue'  => 4164,
    ];

    public static function config_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'edu_acc_config';
    }

    public static function splits_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'edu_acc_splits';
    }

    public static function journal_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'edu_acc_journal';
    }

    public static function default_config(): array {
        return [
            'mentor_pct'           => 62.0,
            'org_venue_pct'        => 12.0,
            'transport_base'       => 150000,
            'transport_per_km'     => 25000,
            'materials_standard'   => 45000,
            'materials_intensive'  => 95000,
            'overhead_pct'         => 4.5,
            'platform_pct'         => 8.0,
            'paper_per_session'    => 15000,
            'auto_post'            => false,
        ];
    }

    public static function get_config(): array {
        global $wpdb;
        $t = self::config_table();
        if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t ) ) !== $t ) {
            return self::default_config();
        }
        $row = $wpdb->get_var( "SELECT payload FROM {$t} ORDER BY id ASC LIMIT 1" );
        return $row ? array_merge( self::default_config(), json_decode( $row, true ) ?: [] ) : self::default_config();
    }

    public static function save_config( array $data ): bool {
        global $wpdb;
        $t = self::config_table();
        $cfg = array_merge( self::default_config(), $data );
        $json = wp_json_encode( $cfg, JSON_UNESCAPED_UNICODE );
        $id = (int) $wpdb->get_var( "SELECT id FROM {$t} ORDER BY id ASC LIMIT 1" );
        if ( $id ) {
            return (bool) $wpdb->update( $t, [ 'payload' => $json ], [ 'id' => $id ] );
        }
        return (bool) $wpdb->insert( $t, [ 'payload' => $json ] );
    }

    /** پیش‌فاکتور شفاف قبل از رزرو */
    public static function quote_session( array $p ): array {
        $cfg = self::get_config();
        $duration_h = max( 0.5, ( (int) ( $p['duration_min'] ?? 90 ) ) / 60 );
        $mentor_base = (float) ( $p['mentor_hourly'] ?? 800000 ) * $duration_h;
        if ( ! empty( $p['educator_id'] ) ) {
            global $wpdb;
            $rate = (float) $wpdb->get_var( $wpdb->prepare(
                "SELECT hourly_rate FROM " . $wpdb->prefix . "edu_educators WHERE id = %d", (int) $p['educator_id']
            ) );
            if ( $rate > 0 ) {
                $mentor_base = $rate * $duration_h;
            }
        }
        $mentor = round( $mentor_base * (float) $cfg['mentor_pct'] / 100 );
        if ( $mentor <= 0 ) {
            $mentor = round( $mentor_base * 0.62 );
        }

        $venue = 0.0;
        if ( in_array( $p['venue_type'] ?? '', [ 'school', 'institute' ], true ) && ! empty( $p['org_id'] ) ) {
            global $wpdb;
            $res_price = null;
            if ( ! empty( $p['resource_id'] ) ) {
                $res_price = $wpdb->get_var( $wpdb->prepare(
                    "SELECT price_per_hour FROM " . $wpdb->prefix . "edu_org_resources WHERE id = %d", (int) $p['resource_id']
                ) );
            }
            $venue = $res_price ? (float) $res_price * $duration_h : round( $mentor_base * (float) $cfg['org_venue_pct'] / 100 );
        }

        $transport = 0.0;
        if ( ( $p['delivery_mode'] ?? '' ) === 'in_person' && ( $p['venue_type'] ?? '' ) === 'home' ) {
            $km = max( 0, (float) ( $p['distance_km'] ?? 0 ) );
            $transport = (float) $cfg['transport_base'] + $km * (float) $cfg['transport_per_km'];
        }

        $materials = ( $p['materials_level'] ?? 'standard' ) === 'intensive'
            ? (float) $cfg['materials_intensive']
            : (float) $cfg['materials_standard'];
        $materials += (float) $cfg['paper_per_session'];

        $direct = $mentor + $venue + $transport + $materials;
        $overhead = round( $direct * (float) $cfg['overhead_pct'] / 100 );
        $subtotal = $direct + $overhead;
        $platform = round( $subtotal * (float) $cfg['platform_pct'] / ( 100 - (float) $cfg['platform_pct'] ) );
        $total = round( $subtotal + $platform );

        return [
            'lines' => [
                [ 'key' => 'mentor_fee', 'label' => 'حق‌الزحمه مربی/معلم', 'amount' => $mentor ],
                [ 'key' => 'venue_fee', 'label' => 'اجاره فضا (مدرسه/مؤسسه)', 'amount' => $venue ],
                [ 'key' => 'transport', 'label' => 'ایاب‌ذهاب', 'amount' => $transport ],
                [ 'key' => 'materials', 'label' => 'مواد + کاغذ/لوازم', 'amount' => $materials ],
                [ 'key' => 'overhead', 'label' => 'سربار (اداری)', 'amount' => $overhead ],
                [ 'key' => 'platform', 'label' => 'سرویس پلتفرم ACC Edu', 'amount' => $platform ],
            ],
            'direct_cost' => $direct,
            'overhead'    => $overhead,
            'platform'    => $platform,
            'total'       => $total,
            'gross_margin'=> $platform,
        ];
    }

    public static function calculate_costs( array $session ): array {
        $quote = json_decode( $session['quote_json'] ?? '{}', true );
        if ( empty( $quote['lines'] ) ) {
            $quote = self::quote_session( [
                'delivery_mode'  => $session['delivery_mode'] ?? 'virtual',
                'venue_type'     => $session['venue_type'] ?? 'online',
                'org_id'         => (int) ( $session['org_id'] ?? 0 ),
                'resource_id'    => (int) ( $session['resource_id'] ?? 0 ),
                'distance_km'    => (float) ( $session['distance_km'] ?? 0 ),
                'duration_min'   => (int) ( $session['duration_min'] ?? 90 ),
                'educator_id'    => (int) ( $session['educator_id'] ?? 0 ),
            ] );
        }
        $costs = [
            'mentor_fee'  => 0.0,
            'venue_fee'   => 0.0,
            'transport'   => 0.0,
            'materials'   => 0.0,
            'overhead'    => 0.0,
            'platform'    => 0.0,
            'total'       => (float) ( $session['amount_total'] ?? $quote['total'] ?? 0 ),
        ];
        foreach ( $quote['lines'] ?? [] as $line ) {
            $k = $line['key'] ?? '';
            if ( isset( $costs[ $k ] ) ) {
                $costs[ $k ] = (float) $line['amount'];
            }
        }
        $costs['direct'] = $costs['mentor_fee'] + $costs['venue_fee'] + $costs['transport'] + $costs['materials'];
        $costs['total_cost'] = $costs['direct'] + $costs['overhead'];
        $costs['revenue'] = $costs['total'];
        $costs['gross_margin'] = $costs['revenue'] - $costs['total_cost'] - $costs['platform'];
        return $costs;
    }

    public static function on_session_completed( array $session, array $report = [] ): array {
        global $wpdb;
        $costs = self::calculate_costs( $session );
        $sid = (int) $session['id'];
        $revenue_gl = ( $session['session_type'] ?? '' ) === 'skill' ? self::GL['revenue_skill'] : self::GL['revenue_academic'];

        require_once ACC_PATH . 'includes/helpers/acc-event-engine.php';
        require_once ACC_PATH . 'includes/helpers/acc-portal-accounting.php';

        $portal = Acc_Portal_Accounting::portal_settings( 'education' );
        $tag = '[' . ( $portal['ledger_tag'] ?? 'EDU' ) . ']';

        $pairs = [];
        $G = self::GL;
        $total = (float) $costs['total'];
        if ( $total <= 0 ) {
            return [ 'success' => false, 'message' => 'مبلغ جلسه نامعتبر' ];
        }

        $pairs[] = [ 'dr_gl_id' => $G['ar'], 'cr_gl_id' => $revenue_gl, 'source_field' => 'revenue', 'desc' => $tag . ' درآمد جلسه #' . $sid, 'amount' => $total - $costs['platform'] ];
        if ( $costs['platform'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['ar'], 'cr_gl_id' => $G['platform_revenue'], 'source_field' => 'platform', 'desc' => $tag . ' کارمزد پلتفرم', 'amount' => $costs['platform'] ];
        }
        if ( $costs['mentor_fee'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['mentor_expense'], 'cr_gl_id' => $G['mentor_payable'], 'source_field' => 'mentor_fee', 'desc' => $tag . ' حق‌الزحمه مربی', 'amount' => $costs['mentor_fee'] ];
        }
        if ( $costs['venue_fee'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['venue_expense'], 'cr_gl_id' => $G['org_payable'], 'source_field' => 'venue_fee', 'desc' => $tag . ' اجاره فضا', 'amount' => $costs['venue_fee'] ];
        }
        if ( $costs['transport'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['transport_expense'], 'cr_gl_id' => $G['transport_payable'], 'source_field' => 'transport', 'desc' => $tag . ' ایاب‌ذهاب', 'amount' => $costs['transport'] ];
        }
        if ( $costs['materials'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['materials_expense'], 'cr_gl_id' => $G['bank'], 'source_field' => 'materials', 'desc' => $tag . ' مواد و کاغذ', 'amount' => $costs['materials'] ];
        }
        if ( $costs['overhead'] > 0 ) {
            $pairs[] = [ 'dr_gl_id' => $G['overhead_expense'], 'cr_gl_id' => $G['bank'], 'source_field' => 'overhead', 'desc' => $tag . ' سربار', 'amount' => $costs['overhead'] ];
        }

        $payload = [
            'revenue'     => $total,
            'platform'    => $costs['platform'],
            'mentor_fee'  => $costs['mentor_fee'],
            'venue_fee'   => $costs['venue_fee'],
            'transport'   => $costs['transport'],
            'materials'   => $costs['materials'],
            'overhead'    => $costs['overhead'],
            'costs'       => $costs,
            'source_module' => 'education',
            'manual_entries' => [ 'pairs' => array_map( function ( $p ) {
                if ( ! isset( $p['amount'] ) && isset( $p['source_field'] ) ) {
                    return $p;
                }
                return $p;
            }, $pairs ) ],
        ];

        foreach ( $pairs as &$p ) {
            if ( ! isset( $p['amount'] ) ) {
                $p['amount'] = (float) ( $payload[ $p['source_field'] ] ?? 0 );
            }
        }
        unset( $p );
        $payload['manual_entries']['pairs'] = $pairs;

        $result = Acc_Event_Engine::create_event( [
            'event_type'      => 'EDU_SESSION_INVOICE',
            'amount'          => $total,
            'payload'         => $payload,
            'reference_type'  => 'edu_session',
            'reference_id'    => $sid,
            'idempotency_key' => 'EDU_SESS_' . $sid,
            'source_module'   => 'education',
            'description'     => $tag . ' سند جلسه آموزشی #' . $sid,
        ] );

        if ( empty( $result['success'] ) ) {
            return $result;
        }
        $event_id = (int) ( $result['event_id'] ?? 0 );
        self::_persist_splits( $sid, $costs, $session );
        self::_journal_log( $sid, $event_id, 'EDU_SESSION_INVOICE', $total, 'pending' );

        $wpdb->update( Education_Platform::tbl( 'sessions' ), [
            'acc_event_id' => $event_id,
            'cost_json'    => wp_json_encode( $costs, JSON_UNESCAPED_UNICODE ),
        ], [ 'id' => $sid ] );

        $cfg = self::get_config();
        if ( ! empty( $cfg['auto_post'] ) ) {
            return self::post_session( $sid, 0 );
        }
        return [ 'success' => true, 'event_id' => $event_id, 'pending' => true, 'costs' => $costs ];
    }

    public static function post_session( int $session_id, int $user_id = 0 ): array {
        global $wpdb;
        $s = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . Education_Platform::tbl( 'sessions' ) . " WHERE id = %d", $session_id
        ), ARRAY_A );
        if ( ! $s || empty( $s['acc_event_id'] ) ) {
            return [ 'success' => false, 'message' => 'سند یافت نشد' ];
        }
        require_once ACC_PATH . 'includes/helpers/acc-event-engine.php';
        $post = Acc_Event_Engine::post_event( (int) $s['acc_event_id'] );
        if ( empty( $post['success'] ) ) {
            return $post;
        }
        require_once ACC_PATH . 'includes/helpers/acc-portal-accounting.php';
        Acc_Portal_Accounting::confirm_event( 'education', (int) $s['acc_event_id'] );
        self::_journal_log( $session_id, (int) $s['acc_event_id'], 'EDU_SESSION_INVOICE', (float) $s['amount_total'], 'posted' );
        return [ 'success' => true, 'event_id' => (int) $s['acc_event_id'], 'message' => 'سند قطعی شد' ];
    }

    private static function _persist_splits( int $session_id, array $costs, array $session ): void {
        global $wpdb;
        $t = self::splits_table();
        $rows = [
            [ 'entity_type' => 'mentor', 'entity_id' => (int) ( $session['educator_id'] ?? 0 ), 'fee' => $costs['mentor_fee'] ],
            [ 'entity_type' => 'org', 'entity_id' => (int) ( $session['org_id'] ?? 0 ), 'fee' => $costs['venue_fee'] ],
            [ 'entity_type' => 'transport', 'entity_id' => 0, 'fee' => $costs['transport'] ],
            [ 'entity_type' => 'platform', 'entity_id' => 0, 'fee' => $costs['platform'] ],
        ];
        foreach ( $rows as $r ) {
            if ( $r['fee'] <= 0 ) {
                continue;
            }
            $wpdb->insert( $t, [
                'session_id'  => $session_id,
                'entity_type' => $r['entity_type'],
                'entity_id'   => $r['entity_id'],
                'amount'      => $r['fee'],
                'created_at'  => current_time( 'mysql' ),
            ] );
        }
    }

    private static function _journal_log( int $session_id, int $event_id, string $etype, float $amount, string $status ): void {
        global $wpdb;
        $t = self::journal_table();
        if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t ) ) !== $t ) {
            return;
        }
        $ex = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$t} WHERE session_id = %d AND event_type = %s", $session_id, $etype
        ) );
        $row = [
            'session_id'   => $session_id,
            'event_type'   => $etype,
            'acc_event_id' => $event_id,
            'amount'       => $amount,
            'status'       => $status,
        ];
        if ( $ex ) {
            $wpdb->update( $t, $row, [ 'id' => $ex ] );
        } else {
            $row['created_at'] = current_time( 'mysql' );
            $wpdb->insert( $t, $row );
        }
    }

    public static function pending_queue(): array {
        global $wpdb;
        $st = Education_Platform::tbl( 'sessions' );
        $rows = $wpdb->get_results(
            "SELECT s.* FROM {$st} s
             WHERE s.status = 'completed' AND s.acc_event_id IS NOT NULL
             AND EXISTS (
                SELECT 1 FROM {$wpdb->prefix}ai_acc_events e
                WHERE e.id = s.acc_event_id AND e.workflow_state = 'pending'
             )
             ORDER BY s.id DESC LIMIT 50",
            ARRAY_A
        ) ?: [];
        return [ 'sessions' => $rows, 'count' => count( $rows ) ];
    }

    public static function cost_report( ?string $from = null, ?string $to = null ): array {
        global $wpdb;
        $st = Education_Platform::tbl( 'sessions' );
        $conds = [ "status = 'completed'" ];
        $args = [];
        if ( $from ) {
            $conds[] = 'completed_at >= %s';
            $args[] = $from . ' 00:00:00';
        }
        if ( $to ) {
            $conds[] = 'completed_at <= %s';
            $args[] = $to . ' 23:59:59';
        }
        $sql = "SELECT id, amount_total, cost_json, session_type, delivery_mode, venue_type FROM {$st} WHERE " . implode( ' AND ', $conds );
        $rows = $args ? $wpdb->get_results( $wpdb->prepare( $sql, ...$args ), ARRAY_A ) : $wpdb->get_results( $sql, ARRAY_A );
        $tot = [ 'revenue' => 0, 'mentor' => 0, 'venue' => 0, 'transport' => 0, 'materials' => 0, 'overhead' => 0, 'platform' => 0, 'sessions' => 0 ];
        foreach ( $rows ?: [] as $r ) {
            $c = json_decode( $r['cost_json'] ?? '{}', true ) ?: [];
            $tot['sessions']++;
            $tot['revenue']   += (float) ( $r['amount_total'] ?? 0 );
            $tot['mentor']    += (float) ( $c['mentor_fee'] ?? 0 );
            $tot['venue']     += (float) ( $c['venue_fee'] ?? 0 );
            $tot['transport'] += (float) ( $c['transport'] ?? 0 );
            $tot['materials'] += (float) ( $c['materials'] ?? 0 );
            $tot['overhead']  += (float) ( $c['overhead'] ?? 0 );
            $tot['platform']  += (float) ( $c['platform'] ?? 0 );
        }
        $tot['direct_cost'] = $tot['mentor'] + $tot['venue'] + $tot['transport'] + $tot['materials'];
        $tot['total_cost']  = $tot['direct_cost'] + $tot['overhead'];
        return $tot;
    }
}
