<?php
/**
 * Permits_Controller.php — مجوزها و شهرداری
 * پروانه ساخت | مراحل | عوارض | پایان کار
 */

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

class Permits_Controller {

    /* مراحل استاندارد فرآیند پروانه */
    const STEPS = [
        'document_prep'   => ['label'=>'تهیه مدارک',          'icon'=>'📄', 'order'=>1],
        'submit'          => ['label'=>'ارائه درخواست',        'icon'=>'📮', 'order'=>2],
        'municipality'    => ['label'=>'بررسی شهرداری',        'icon'=>'🏛️', 'order'=>3],
        'fee_calc'        => ['label'=>'محاسبه عوارض',         'icon'=>'🧮', 'order'=>4],
        'fee_payment'     => ['label'=>'پرداخت عوارض',         'icon'=>'💳', 'order'=>5],
        'permit_issued'   => ['label'=>'صدور پروانه',          'icon'=>'📋', 'order'=>6],
        'foundation'      => ['label'=>'بازدید فونداسیون',     'icon'=>'🔍', 'order'=>7],
        'structure'       => ['label'=>'بازدید اسکلت',         'icon'=>'🏗️', 'order'=>8],
        'final_inspect'   => ['label'=>'بازدید نهایی',         'icon'=>'✅', 'order'=>9],
        'completion_cert' => ['label'=>'پایان کار',            'icon'=>'🏆', 'order'=>10],
        'title_deed'      => ['label'=>'صدور سند',             'icon'=>'📜', 'order'=>11],
    ];

    public static function register_routes(): void {
        $ns = 'acc/v1';
        $p  = 'acc_jwt_check_permission';

        // پروانه‌ها
        register_rest_route($ns, '/permits', [
            ['methods'=>'GET',  'callback'=>[self::class,'get_permits'],   'permission_callback'=>$p],
            ['methods'=>'POST', 'callback'=>[self::class,'create_permit'], 'permission_callback'=>$p],
        ]);
        register_rest_route($ns, '/permits/(?P<id>\d+)', [
            ['methods'=>'GET',    'callback'=>[self::class,'get_permit'],    'permission_callback'=>$p],
            ['methods'=>'PUT',    'callback'=>[self::class,'update_permit'], 'permission_callback'=>$p],
            ['methods'=>'DELETE', 'callback'=>[self::class,'delete_permit'], 'permission_callback'=>$p],
        ]);

        // مراحل
        register_rest_route($ns, '/permits/(?P<id>\d+)/steps', [
            ['methods'=>'GET',  'callback'=>[self::class,'get_steps'],   'permission_callback'=>$p],
            ['methods'=>'POST', 'callback'=>[self::class,'update_step'], 'permission_callback'=>$p],
        ]);

        // عوارض
        register_rest_route($ns, '/permits/(?P<id>\d+)/fees', [
            ['methods'=>'GET',  'callback'=>[self::class,'get_fees'],   'permission_callback'=>$p],
            ['methods'=>'POST', 'callback'=>[self::class,'create_fee'], 'permission_callback'=>$p],
        ]);
        register_rest_route($ns, '/permits/(?P<id>\d+)/fees/(?P<fee_id>\d+)', [
            ['methods'=>'PUT',    'callback'=>[self::class,'update_fee'], 'permission_callback'=>$p],
            ['methods'=>'DELETE', 'callback'=>[self::class,'delete_fee'], 'permission_callback'=>$p],
        ]);
        register_rest_route($ns, '/permits/(?P<id>\d+)/fees/(?P<fee_id>\d+)/pay', [
            'methods'=>'POST', 'callback'=>[self::class,'pay_fee'], 'permission_callback'=>$p,
        ]);

        // متادیتا
        register_rest_route($ns, '/permits/steps/definitions', [
            'methods'=>'GET', 'callback'=>[self::class,'get_step_defs'], 'permission_callback'=>$p,
        ]);
        register_rest_route($ns, '/permits/dashboard', [
            'methods'=>'GET', 'callback'=>[self::class,'get_dashboard'], 'permission_callback'=>$p,
        ]);
    }

    /* ══════════════════════════════════════════════════════════
       پروانه‌ها
    ══════════════════════════════════════════════════════════ */
    public static function get_permits( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre    = $wpdb->prefix;
        $wheres = ['1=1'];
        $args   = [];

        if ($v=$req->get_param('status'))     { $wheres[]='pm.status=%s';     $args[]=sanitize_text_field($v); }
        if ($v=$req->get_param('type'))       { $wheres[]='pm.type=%s';       $args[]=sanitize_text_field($v); }
        if ($v=$req->get_param('parcel_id'))  { $wheres[]='pm.parcel_id=%d';  $args[]=(int)$v; }
        if ($v=$req->get_param('project_id')) { $wheres[]='pm.project_id=%d'; $args[]=(int)$v; }
        $uid = acl_current_user_id();
        if ( ! acl_append_scope_where( $uid, 'project', 'pm.project_id', $wheres, $args ) ) {
            return new WP_REST_Response( [ 'data' => [], 'total' => 0 ] );
        }

        $where = 'WHERE '.implode(' AND ',$wheres);
        $sql   = "SELECT pm.*,
                    p.name AS project_name,
                    gp.code AS parcel_code, gp.address AS parcel_address,
                    (SELECT COUNT(*) FROM {$pre}permit_steps s WHERE s.permit_id=pm.id AND s.status='done') AS done_steps,
                    (SELECT COUNT(*) FROM {$pre}permit_fees f WHERE f.permit_id=pm.id AND f.status='pending') AS pending_fees,
                    DATEDIFF(pm.expiry_date, CURDATE()) AS days_to_expiry
                  FROM {$pre}permits pm
                  LEFT JOIN {$pre}pc_projects p  ON p.id=pm.project_id
                  LEFT JOIN {$pre}gis_parcels gp ON gp.id=pm.parcel_id
                  {$where}
                  ORDER BY pm.updated_at DESC";

        $rows = $args
            ? $wpdb->get_results($wpdb->prepare($sql,...$args), ARRAY_A)
            : $wpdb->get_results($sql, ARRAY_A);

        return new WP_REST_Response(['data'=>$rows??[], 'total'=>count($rows??[])]);
    }

    public static function get_permit( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;
        $id  = (int)$req->get_param('id');

        $pm = $wpdb->get_row($wpdb->prepare(
            "SELECT pm.*, p.name AS project_name, gp.code AS parcel_code, gp.address AS parcel_address
             FROM {$pre}permits pm
             LEFT JOIN {$pre}pc_projects p ON p.id=pm.project_id
             LEFT JOIN {$pre}gis_parcels gp ON gp.id=pm.parcel_id
             WHERE pm.id=%d", $id
        ), ARRAY_A);

        if (!$pm) return new WP_REST_Response(['message'=>'پروانه یافت نشد'],404);

        $deny = acl_deny_scope( acl_current_user_id(), 'project', $pm['project_id'] ? (int) $pm['project_id'] : null, '' );
        if ( $deny ) return $deny;

        // مراحل (همه steps با وضعیت)
        $done_steps = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}permit_steps WHERE permit_id=%d", $id
        ), ARRAY_A);
        $steps_map = [];
        foreach ($done_steps as $s) $steps_map[$s['step_key']] = $s;

        $pm['steps'] = [];
        foreach (self::STEPS as $key => $def) {
            $pm['steps'][] = [
                'key'       => $key,
                'label'     => $def['label'],
                'icon'      => $def['icon'],
                'order'     => $def['order'],
                'status'    => $steps_map[$key]['status']  ?? 'pending',
                'done_date' => $steps_map[$key]['done_date'] ?? null,
                'reference' => $steps_map[$key]['reference'] ?? null,
                'notes'     => $steps_map[$key]['notes']    ?? null,
                'step_db_id'=> $steps_map[$key]['id']       ?? null,
            ];
        }

        $pm['fees'] = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$pre}permit_fees WHERE permit_id=%d ORDER BY due_date, id", $id
        ), ARRAY_A);

        // آمار مالی
        $pm['fee_summary'] = [
            'total'   => array_sum(array_column($pm['fees'],'amount')),
            'paid'    => array_sum(array_filter(array_column($pm['fees'],'amount'), function($i) use ($pm) {
                return $pm['fees'][$i]['status'] === 'paid';
            })),
        ];
        $paid_sum = 0;
        foreach ($pm['fees'] as $f) {
            if ($f['status'] === 'paid') $paid_sum += (float)$f['amount'];
        }
        $pm['fee_summary'] = [
            'total'     => array_sum(array_column($pm['fees'],'amount')),
            'paid'      => $paid_sum,
            'remaining' => array_sum(array_column($pm['fees'],'amount')) - $paid_sum,
        ];

        // پیشرفت
        $total_steps = count(self::STEPS);
        $done_count  = count(array_filter($pm['steps'], fn($s)=>$s['status']==='done'));
        $pm['progress_pct'] = $total_steps > 0 ? round($done_count/$total_steps*100) : 0;
        $pm['done_steps']   = $done_count;
        $pm['total_steps']  = $total_steps;

        // اعلام انقضا
        $pm['days_to_expiry'] = $pm['expiry_date']
            ? (int)round((strtotime($pm['expiry_date']) - time()) / 86400)
            : null;

        return new WP_REST_Response(['data'=>$pm]);
    }

    public static function create_permit( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $data = self::_extract_permit_data($req);
        if (!$data) return new WP_REST_Response(['message'=>'اطلاعات ناقص است'],400);
        $deny = acl_deny_scope( acl_current_user_id(), 'project', ! empty( $data['project_id'] ) ? (int) $data['project_id'] : null );
        if ( $deny ) return $deny;
        $wpdb->insert($wpdb->prefix.'permits', $data);
        return new WP_REST_Response(['id'=>$wpdb->insert_id,'success'=>true],201);
    }

    public static function update_permit( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id   = (int)$req->get_param('id');
        $deny = acl_deny_entity_project( acl_current_user_id(), 'permits', $id );
        if ( $deny ) return $deny;
        $data = self::_extract_permit_data($req, false);
        if ( isset( $data['project_id'] ) ) {
            $deny = acl_deny_scope( acl_current_user_id(), 'project', $data['project_id'] ?: null );
            if ( $deny ) return $deny;
        }
        if ($data) $wpdb->update($wpdb->prefix.'permits', $data, ['id'=>$id]);
        // همگام‌سازی paid_fee از جدول عوارض
        self::_sync_paid_fee($id);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_permit( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id = (int)$req->get_param('id');
        $deny = acl_deny_entity_project( acl_current_user_id(), 'permits', $id );
        if ( $deny ) return $deny;
        $wpdb->delete($wpdb->prefix.'permit_steps', ['permit_id'=>$id]);
        $wpdb->delete($wpdb->prefix.'permit_fees',  ['permit_id'=>$id]);
        $wpdb->delete($wpdb->prefix.'permits',      ['id'=>$id]);
        return new WP_REST_Response(['success'=>true]);
    }

    private static function _extract_permit_data( WP_REST_Request $req, bool $require_type=true ): array|null {
        $type = sanitize_text_field($req->get_param('type')?:'build');
        $data = [
            'type'             => $type,
            'status'           => sanitize_text_field($req->get_param('status') ?: 'draft'),
            'permit_number'    => sanitize_text_field($req->get_param('permit_number') ?: ''),
            'application_ref'  => sanitize_text_field($req->get_param('application_ref') ?: ''),
            'application_date' => sanitize_text_field($req->get_param('application_date') ?: ''),
            'approval_date'    => sanitize_text_field($req->get_param('approval_date') ?: ''),
            'expiry_date'      => sanitize_text_field($req->get_param('expiry_date') ?: ''),
            'completion_date'  => sanitize_text_field($req->get_param('completion_date') ?: ''),
            'allowed_floors'   => $req->get_param('allowed_floors')   ? (int)$req->get_param('allowed_floors')   : null,
            'allowed_area_sqm' => $req->get_param('allowed_area_sqm') ? (float)$req->get_param('allowed_area_sqm') : null,
            'allowed_use'      => sanitize_text_field($req->get_param('allowed_use') ?: ''),
            'density_pct'      => $req->get_param('density_pct') ? (float)$req->get_param('density_pct') : null,
            'municipality'     => sanitize_text_field($req->get_param('municipality') ?: ''),
            'engineer_name'    => sanitize_text_field($req->get_param('engineer_name') ?: ''),
            'engineer_code'    => sanitize_text_field($req->get_param('engineer_code') ?: ''),
            'total_fee'        => $req->get_param('total_fee') ? (float)$req->get_param('total_fee') : null,
            'parcel_id'        => $req->get_param('parcel_id')  ? (int)$req->get_param('parcel_id')  : null,
            'project_id'       => $req->get_param('project_id') ? (int)$req->get_param('project_id') : null,
            'notes'            => sanitize_textarea_field($req->get_param('notes') ?: ''),
        ];
        // حذف مقادیر خالی
        foreach ($data as $k=>$v) {
            if ($v==='' || $v===null) unset($data[$k]);
        }
        return $data;
    }

    /* ══════════════════════════════════════════════════════════
       مراحل
    ══════════════════════════════════════════════════════════ */
    public static function get_steps( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id   = (int)$req->get_param('id');
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}permit_steps WHERE permit_id=%d ORDER BY step_key", $id
        ), ARRAY_A);
        return new WP_REST_Response(['data'=>$rows??[], 'definitions'=>self::STEPS]);
    }

    public static function update_step( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre  = $wpdb->prefix;
        $id   = (int)$req->get_param('id');
        $key  = sanitize_text_field($req->get_param('step_key') ?: '');
        if (!isset(self::STEPS[$key])) return new WP_REST_Response(['message'=>'مرحله نامعتبر'],400);

        $data = [
            'permit_id' => $id,
            'step_key'  => $key,
            'status'    => sanitize_text_field($req->get_param('status') ?: 'done'),
            'done_date' => sanitize_text_field($req->get_param('done_date') ?: date('Y-m-d')),
            'reference' => sanitize_text_field($req->get_param('reference') ?: ''),
            'notes'     => sanitize_textarea_field($req->get_param('notes') ?: ''),
        ];
        foreach ($data as $k=>$v) { if ($v==='' && !in_array($k,['permit_id','step_key','status'])) unset($data[$k]); }

        $wpdb->query($wpdb->prepare(
            "INSERT INTO {$pre}permit_steps (permit_id,step_key,status,done_date,reference,notes)
             VALUES (%d,%s,%s,%s,%s,%s)
             ON DUPLICATE KEY UPDATE status=VALUES(status), done_date=VALUES(done_date),
             reference=VALUES(reference), notes=VALUES(notes)",
            $data['permit_id'], $data['step_key'], $data['status'],
            $data['done_date'] ?? date('Y-m-d'),
            $data['reference'] ?? '',
            $data['notes']     ?? ''
        ));

        // به‌روزرسانی وضعیت پروانه بر اساس مراحل
        self::_auto_update_status($id);

        return new WP_REST_Response(['success'=>true]);
    }

    private static function _auto_update_status( int $permit_id ): void {
        global $wpdb;
        $pre  = $wpdb->prefix;
        $done = $wpdb->get_col($wpdb->prepare(
            "SELECT step_key FROM {$pre}permit_steps WHERE permit_id=%d AND status='done'", $permit_id
        ));
        // قوانین ارتقای خودکار وضعیت
        if (in_array('completion_cert', $done)) {
            $wpdb->update("{$pre}permits", ['status'=>'completed'], ['id'=>$permit_id]);
        } elseif (in_array('permit_issued', $done)) {
            $wpdb->update("{$pre}permits", ['status'=>'active'], ['id'=>$permit_id]);
        } elseif (in_array('submit', $done)) {
            $wpdb->update("{$pre}permits", ['status'=>'under_review'], ['id'=>$permit_id]);
        }
    }

    /* ══════════════════════════════════════════════════════════
       عوارض
    ══════════════════════════════════════════════════════════ */
    public static function get_fees( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}permit_fees WHERE permit_id=%d ORDER BY due_date, id",
            (int)$req->get_param('id')
        ), ARRAY_A);
        // به‌روزرسانی خودکار سررسیدگذشته
        $today = date('Y-m-d');
        foreach ($rows as &$r) {
            if ($r['status']==='pending' && $r['due_date'] && $r['due_date'] < $today) {
                $r['status'] = 'overdue';
                $wpdb->update($wpdb->prefix.'permit_fees',['status'=>'overdue'],['id'=>$r['id']]);
            }
        }
        return new WP_REST_Response(['data'=>$rows??[]]);
    }

    public static function create_fee( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $data = [
            'permit_id'   => (int)$req->get_param('id'),
            'category'    => sanitize_text_field($req->get_param('category')    ?: 'permit_fee'),
            'description' => sanitize_text_field($req->get_param('description') ?: ''),
            'amount'      => (float)($req->get_param('amount') ?: 0),
            'due_date'    => sanitize_text_field($req->get_param('due_date') ?: ''),
            'status'      => 'pending',
            'notes'       => sanitize_textarea_field($req->get_param('notes') ?: ''),
        ];
        if (!$data['description']) return new WP_REST_Response(['message'=>'شرح الزامی است'],400);
        if (!$data['amount'])      return new WP_REST_Response(['message'=>'مبلغ الزامی است'],400);
        if (empty($data['due_date'])) unset($data['due_date']);
        $wpdb->insert($wpdb->prefix.'permit_fees', $data);
        self::_sync_paid_fee($data['permit_id']);
        return new WP_REST_Response(['id'=>$wpdb->insert_id,'success'=>true],201);
    }

    public static function update_fee( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $id  = (int)$req->get_param('fee_id');
        $pid = (int)$req->get_param('id');
        $data = [];
        foreach (['category','description','due_date','status','notes','receipt_number'] as $k) {
            $v=$req->get_param($k); if($v!==null) $data[$k]=sanitize_textarea_field((string)$v);
        }
        if ($req->get_param('amount')!==null) $data['amount']=(float)$req->get_param('amount');
        $wpdb->update($wpdb->prefix.'permit_fees', $data, ['id'=>$id,'permit_id'=>$pid]);
        self::_sync_paid_fee($pid);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function delete_fee( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pid = (int)$req->get_param('id');
        $wpdb->delete($wpdb->prefix.'permit_fees',['id'=>(int)$req->get_param('fee_id'),'permit_id'=>$pid]);
        self::_sync_paid_fee($pid);
        return new WP_REST_Response(['success'=>true]);
    }

    public static function pay_fee( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre    = $wpdb->prefix;
        $pid    = (int)$req->get_param('id');
        $fee_id = (int)$req->get_param('fee_id');
        $wpdb->update("{$pre}permit_fees",[
            'status'         => 'paid',
            'paid_date'      => sanitize_text_field($req->get_param('paid_date') ?: date('Y-m-d')),
            'receipt_number' => sanitize_text_field($req->get_param('receipt_number') ?: ''),
        ],['id'=>$fee_id,'permit_id'=>$pid]);
        self::_sync_paid_fee($pid);
        return new WP_REST_Response(['success'=>true]);
    }

    private static function _sync_paid_fee( int $permit_id ): void {
        global $wpdb;
        $paid = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(amount),0) FROM {$wpdb->prefix}permit_fees WHERE permit_id=%d AND status='paid'",
            $permit_id
        ));
        $total = (float)$wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(amount),0) FROM {$wpdb->prefix}permit_fees WHERE permit_id=%d AND status!='cancelled'",
            $permit_id
        ));
        $wpdb->update($wpdb->prefix.'permits',['paid_fee'=>$paid,'total_fee'=>$total],['id'=>$permit_id]);
    }

    /* ══════════════════════════════════════════════════════════
       متادیتا و داشبورد
    ══════════════════════════════════════════════════════════ */
    public static function get_step_defs(): WP_REST_Response {
        return new WP_REST_Response(['data'=>self::STEPS]);
    }

    public static function get_dashboard( WP_REST_Request $req ): WP_REST_Response {
        global $wpdb;
        $pre = $wpdb->prefix;

        $by_status = $wpdb->get_results(
            "SELECT status, COUNT(*) AS cnt FROM {$pre}permits GROUP BY status", ARRAY_A
        );
        $expiring = $wpdb->get_results(
            "SELECT id, permit_number, type, expiry_date, parcel_id,
                    DATEDIFF(expiry_date, CURDATE()) AS days_left
             FROM {$pre}permits
             WHERE status IN ('approved','active') AND expiry_date IS NOT NULL
               AND DATEDIFF(expiry_date, CURDATE()) BETWEEN 0 AND 60
             ORDER BY expiry_date",
            ARRAY_A
        );
        $pending_fees = $wpdb->get_results(
            "SELECT pf.*, pm.permit_number, pm.type AS permit_type
             FROM {$pre}permit_fees pf
             JOIN {$pre}permits pm ON pm.id=pf.permit_id
             WHERE pf.status IN ('pending','overdue')
             ORDER BY pf.due_date
             LIMIT 10",
            ARRAY_A
        );

        return new WP_REST_Response([
            'by_status'    => $by_status,
            'expiring'     => $expiring,
            'pending_fees' => $pending_fees,
        ]);
    }
}
