<?php

/**

 * SR_Accounting_Controller — تنظیمات سهم‌ها، صف صدور و گزارش بهای تمام‌شده (پورتال خدمات)

 */

if ( ! defined( 'ABSPATH' ) ) exit;



require_once ACC_PATH . 'includes/helpers/svc-accounting.php';



class SR_Accounting_Controller {



    public static function register_routes(): void {

        $ns  = 'acc/v1';

        $jwt = 'acc_jwt_check_permission';



        register_rest_route( $ns, '/service/accounting/config', [

            [ 'methods' => 'GET',  'callback' => [ __CLASS__, 'get_config' ],  'permission_callback' => $jwt ],

            [ 'methods' => 'PUT',  'callback' => [ __CLASS__, 'save_config' ], 'permission_callback' => $jwt ],

        ] );



        register_rest_route( $ns, '/service/accounting/portal', [

            [ 'methods' => 'GET', 'callback' => [ __CLASS__, 'get_portal' ], 'permission_callback' => $jwt ],

            [ 'methods' => 'PUT', 'callback' => [ __CLASS__, 'save_portal' ], 'permission_callback' => $jwt ],

        ] );



        register_rest_route( $ns, '/service/accounting/pending', [

            'methods' => 'GET', 'callback' => [ __CLASS__, 'pending_queue' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/config/by-type', [

            'methods' => 'GET', 'callback' => [ __CLASS__, 'list_configs' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/splits/(?P<report_id>\d+)', [

            'methods' => 'GET', 'callback' => [ __CLASS__, 'get_splits' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/cost-report', [

            'methods' => 'GET', 'callback' => [ __CLASS__, 'cost_report' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/preview/(?P<report_id>\d+)', [

            'methods' => 'GET', 'callback' => [ __CLASS__, 'preview_splits' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/post/(?P<report_id>\d+)', [

            'methods' => 'POST', 'callback' => [ __CLASS__, 'manual_post' ], 'permission_callback' => $jwt,

        ] );



        register_rest_route( $ns, '/service/accounting/post-event/(?P<event_id>\d+)', [

            'methods' => 'POST', 'callback' => [ __CLASS__, 'post_event' ], 'permission_callback' => $jwt,

        ] );

        register_rest_route( $ns, '/service/accounting/activities', [
            [ 'methods' => 'GET', 'callback' => [ __CLASS__, 'get_activities' ], 'permission_callback' => $jwt ],
            [ 'methods' => 'PUT', 'callback' => [ __CLASS__, 'save_activities' ], 'permission_callback' => $jwt ],
        ] );

        register_rest_route( $ns, '/service/accounting/crew/(?P<request_id>\d+)', [
            [ 'methods' => 'GET', 'callback' => [ __CLASS__, 'get_crew' ], 'permission_callback' => $jwt ],
            [ 'methods' => 'PUT', 'callback' => [ __CLASS__, 'save_crew' ], 'permission_callback' => $jwt ],
        ] );

        register_rest_route( $ns, '/service/accounting/activity-cost/(?P<report_id>\d+)', [
            'methods' => 'GET', 'callback' => [ __CLASS__, 'activity_cost' ], 'permission_callback' => $jwt,
        ] );

        register_rest_route( $ns, '/service/accounting/cost-graph', [
            'methods' => 'GET', 'callback' => [ __CLASS__, 'cost_graph' ], 'permission_callback' => $jwt,
        ] );

        register_rest_route( $ns, '/service/accounting/allocate/(?P<report_id>\d+)', [
            'methods' => 'POST', 'callback' => [ __CLASS__, 'reallocate' ], 'permission_callback' => $jwt,
        ] );

    }



    private static function can_view(): bool {

        $uid = (int) get_current_user_id();

        if ( $uid <= 0 ) return false;

        if ( function_exists( 'acl_user_is_super_admin' ) && acl_user_is_super_admin( $uid ) ) return true;

        foreach ( [ 'service.accounting', 'service.manage', 'acc.view', 'acc.post' ] as $pk ) {

            if ( function_exists( 'acl_user_can' ) && acl_user_can( $uid, $pk ) ) return true;

        }

        return false;

    }



    private static function can_post(): bool {

        $uid = (int) get_current_user_id();

        if ( $uid <= 0 ) return false;

        if ( function_exists( 'acl_user_is_super_admin' ) && acl_user_is_super_admin( $uid ) ) return true;

        foreach ( [ 'service.accounting.post', 'acc.post' ] as $pk ) {

            if ( function_exists( 'acl_user_can' ) && acl_user_can( $uid, $pk ) ) return true;

        }

        return false;

    }



    private static function can_manage_config(): bool {

        $uid = (int) get_current_user_id();

        if ( $uid <= 0 ) return false;

        if ( function_exists( 'acl_user_is_super_admin' ) && acl_user_is_super_admin( $uid ) ) return true;

        return function_exists( 'acl_user_can' ) && acl_user_can( $uid, 'service.manage' );

    }



    public static function get_config( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        $type = sanitize_text_field( $req->get_param( 'service_type' ) ?? '' );

        return new WP_REST_Response( [

            'success' => true,

            'data'    => [

                'config'        => Svc_Accounting::get_config( $type ?: null ),

                'defaults'      => Svc_Accounting::default_config(),

                'portal'        => Svc_Accounting::portal_settings(),

                'gl_accounts'   => Svc_Accounting::GL,

                'service_types' => self::_service_types(),

                'can_post'      => self::can_post(),

                'can_config'    => self::can_manage_config(),

            ],

        ] );

    }



    public static function get_portal( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        return new WP_REST_Response( [

            'success' => true,

            'data'    => Svc_Accounting::portal_settings(),

        ] );

    }



    public static function save_portal( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_manage_config() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'فقط مدیر می‌تواند هویت شعبه را تغییر دهد' ], 403 );

        }

        $body = $req->get_json_params() ?: [];

        $ok   = Svc_Accounting::save_portal_settings( $body );

        return new WP_REST_Response( [

            'success' => $ok,

            'data'    => Svc_Accounting::portal_settings(),

        ] );

    }



    public static function pending_queue( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        return new WP_REST_Response( [

            'success' => true,

            'data'    => Svc_Accounting::pending_queue(),

        ] );

    }



    public static function list_configs( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_manage_config() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        global $wpdb;

        $rows = $wpdb->get_results(

            "SELECT service_type, payload, updated_at FROM " . Svc_Accounting::config_table() . " ORDER BY service_type IS NULL DESC, service_type ASC",

            ARRAY_A

        ) ?: [];

        $out = [];

        foreach ( $rows as $r ) {

            $out[] = [

                'service_type' => $r['service_type'] ?: '_default',

                'config'       => json_decode( $r['payload'] ?? '{}', true ),

                'updated_at'   => $r['updated_at'],

            ];

        }

        return new WP_REST_Response( [ 'success' => true, 'data' => $out ] );

    }



    public static function save_config( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_manage_config() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        $body = $req->get_json_params() ?: [];

        $type = sanitize_text_field( $body['service_type'] ?? '' );

        $type = ( $type === '_default' || $type === '' ) ? null : $type;

        $cfg  = $body['config'] ?? $body;

        unset( $cfg['service_type'] );

        $ok = Svc_Accounting::save_config( $cfg, $type );

        return new WP_REST_Response( [

            'success' => $ok,

            'data'    => Svc_Accounting::get_config( $type ),

        ] );

    }



    public static function get_splits( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        global $wpdb;

        $rid = (int) $req['report_id'];

        $report = $wpdb->get_row( $wpdb->prepare(

            "SELECT * FROM {$wpdb->prefix}svc_reports WHERE id = %d", $rid

        ), ARRAY_A );

        if ( ! $report ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'یافت نشد' ], 404 );

        }

        $splits = json_decode( $report['acc_splits_json'] ?? '', true );

        if ( ! $splits ) {

            $splits = Svc_Accounting::calculate_splits( $report );

        }

        $state = '';

        if ( ! empty( $report['acc_revenue_event_id'] ) ) {

            $state = (string) $wpdb->get_var( $wpdb->prepare(

                "SELECT workflow_state FROM {$wpdb->prefix}ai_acc_events WHERE id = %d",

                (int) $report['acc_revenue_event_id']

            ) );

        }

        $entities = $wpdb->get_results( $wpdb->prepare(

            "SELECT * FROM " . Svc_Accounting::splits_table() . " WHERE report_id = %d", $rid

        ), ARRAY_A ) ?: [];

        return new WP_REST_Response( [

            'success' => true,

            'data'    => [

                'report'         => $report,

                'splits'         => $splits,

                'entities'       => $entities,

                'acc_event_id'   => (int) ( $report['acc_revenue_event_id'] ?? 0 ),

                'workflow_state' => $state,

                'portal'         => Svc_Accounting::portal_settings(),

            ],

        ] );

    }



    public static function preview_splits( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        global $wpdb;

        $rid = (int) $req['report_id'];

        $report = $wpdb->get_row( $wpdb->prepare(

            "SELECT * FROM {$wpdb->prefix}svc_reports WHERE id = %d", $rid

        ), ARRAY_A );

        if ( ! $report ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'یافت نشد' ], 404 );

        }

        $splits = Svc_Accounting::calculate_splits( $report );
        if ( file_exists( ACC_PATH . 'includes/helpers/svc-activity-cost.php' ) ) {
            require_once ACC_PATH . 'includes/helpers/svc-activity-cost.php';
            $abc = Svc_Activity_Cost::allocate( $report, $splits );
            $splits['activity_cost'] = [
                'pools'         => $abc['pools'],
                'person_shares' => $abc['person_shares'],
                'lines'         => $abc['lines'],
                'totals'        => $abc['totals'],
            ];
        }

        return new WP_REST_Response( [

            'success' => true,

            'data'    => $splits,

        ] );

    }



    public static function cost_report( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_view() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );

        }

        return new WP_REST_Response( [

            'success' => true,

            'data'    => Svc_Accounting::cost_report( [

                'date_from' => sanitize_text_field( $req->get_param( 'date_from' ) ?? '' ),

                'date_to'   => sanitize_text_field( $req->get_param( 'date_to' ) ?? '' ),

            ] ),

        ] );

    }



    public static function manual_post( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_post() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'فقط حسابدار مجاز به صدور سند است' ], 403 );

        }

        $rid = (int) $req['report_id'];

        $result = Svc_Accounting::post_report_by_accountant( $rid, (int) get_current_user_id() );

        return new WP_REST_Response( $result, $result['success'] ? 200 : 400 );

    }



    public static function post_event( WP_REST_Request $req ): WP_REST_Response {

        if ( ! self::can_post() ) {

            return new WP_REST_Response( [ 'success' => false, 'message' => 'فقط حسابدار مجاز به صدور سند است' ], 403 );

        }

        $event_id = (int) $req['event_id'];

        if ( ! class_exists( 'Acc_Event_Engine' ) ) {

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

        }

        $result = Acc_Event_Engine::post_event( $event_id );

        if ( $result['success'] ) {

            global $wpdb;

            $wpdb->update( Svc_Accounting::journal_table(), [

                'status'  => 'posted',

                'payload' => wp_json_encode( [ 'posted_by' => (int) get_current_user_id() ], JSON_UNESCAPED_UNICODE ),

            ], [ 'acc_event_id' => $event_id ] );

        }

        $http = (int) ( $result['http'] ?? ( $result['success'] ? 200 : 400 ) );

        unset( $result['http'] );

        return new WP_REST_Response( $result, $http );

    }



    private static function _abc(): void {
        require_once ACC_PATH . 'includes/helpers/svc-activity-cost.php';
    }

    public static function get_activities( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_view() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        $all = $req->get_param( 'all' );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Svc_Activity_Cost::list_activities( ! $all ),
            'roles'   => Svc_Activity_Cost::role_labels(),
        ] );
    }

    public static function save_activities( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_manage_config() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'فقط مدیر' ], 403 );
        }
        self::_abc();
        $body = $req->get_json_params() ?: [];
        $items = $body['activities'] ?? $body['data'] ?? $body;
        if ( ! is_array( $items ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'لیست فعالیت نامعتبر' ], 400 );
        }
        return new WP_REST_Response( Svc_Activity_Cost::save_activities( $items ) );
    }

    public static function get_crew( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_view() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        $rid = (int) $req['request_id'];
        $report_id = (int) ( $req->get_param( 'report_id' ) ?? 0 );
        return new WP_REST_Response( [
            'success' => true,
            'data'    => Svc_Activity_Cost::get_crew( $rid, $report_id ?: null ),
            'roles'   => Svc_Activity_Cost::role_labels(),
        ] );
    }

    public static function save_crew( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_post() && ! self::can_manage_config() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        $rid = (int) $req['request_id'];
        $body = $req->get_json_params() ?: [];
        $members = $body['crew'] ?? $body['members'] ?? $body['data'] ?? [];
        $report_id = (int) ( $body['report_id'] ?? 0 );
        if ( ! is_array( $members ) ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'خدمه نامعتبر' ], 400 );
        }
        return new WP_REST_Response( Svc_Activity_Cost::save_crew( $rid, $members, $report_id ?: null ) );
    }

    public static function activity_cost( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_view() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        global $wpdb;
        $rid = (int) $req['report_id'];
        $report = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}svc_reports WHERE id = %d", $rid
        ), ARRAY_A );
        if ( ! $report ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'گزارش یافت نشد' ], 404 );
        }
        $alloc = Svc_Activity_Cost::allocate( $report );
        return new WP_REST_Response( [ 'success' => true, 'data' => $alloc ] );
    }

    public static function cost_graph( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_view() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        $data = Svc_Activity_Cost::cost_graph( [
            'date_from' => $req->get_param( 'date_from' ) ?: date( 'Y-m-01' ),
            'date_to'   => $req->get_param( 'date_to' ) ?: date( 'Y-m-d' ),
            'report_id' => (int) ( $req->get_param( 'report_id' ) ?: 0 ),
        ] );
        return new WP_REST_Response( [ 'success' => true, 'data' => $data ] );
    }

    public static function reallocate( WP_REST_Request $req ): WP_REST_Response {
        if ( ! self::can_post() && ! self::can_manage_config() ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'دسترسی ندارید' ], 403 );
        }
        self::_abc();
        global $wpdb;
        $rid = (int) $req['report_id'];
        $report = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}svc_reports WHERE id = %d", $rid
        ), ARRAY_A );
        if ( ! $report ) {
            return new WP_REST_Response( [ 'success' => false, 'message' => 'گزارش یافت نشد' ], 404 );
        }
        $alloc = Svc_Activity_Cost::allocate( $report );
        Svc_Activity_Cost::persist_allocation( $rid, $alloc );
        $splits = json_decode( $report['acc_splits_json'] ?? '{}', true ) ?: [];
        if ( ! $splits && class_exists( 'Svc_Accounting' ) ) {
            $splits = Svc_Accounting::calculate_splits( $report );
        }
        $splits['activity_cost'] = [
            'pools' => $alloc['pools'],
            'person_shares' => $alloc['person_shares'],
            'lines' => $alloc['lines'],
            'totals' => $alloc['totals'],
        ];
        $wpdb->update( "{$wpdb->prefix}svc_reports", [
            'acc_splits_json' => wp_json_encode( $splits, JSON_UNESCAPED_UNICODE ),
        ], [ 'id' => $rid ] );
        return new WP_REST_Response( [
            'success' => true,
            'message' => 'تخصیص فعالیت و سهم نفرها ذخیره شد',
            'data'    => $alloc,
        ] );
    }

    private static function _service_types(): array {

        if ( class_exists( 'SR_Controller' ) ) {

            return SR_Controller::$SERVICE_TYPES;

        }

        return [];

    }

}

