<?php
/**
 * C3P Capital — ledger + state for MT5 live reserve (manual broker wd/dep).
 */
declare(strict_types=1);

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

class C3P_Capital {

    public const MODULE = 'c3p_capital';

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

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

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

    public static function api_key(): string {
        return defined('C3P_CAPITAL_API_KEY') ? (string) C3P_CAPITAL_API_KEY : '';
    }

    public static function check_api_key(WP_REST_Request $req): bool {
        $expected = self::api_key();
        if ($expected === '') {
            return false;
        }
        $headers = $req->get_headers();
        $got = '';
        if (isset($headers['x_c3p_api_key'])) {
            $got = is_array($headers['x_c3p_api_key']) ? (string) ($headers['x_c3p_api_key'][0] ?? '') : (string) $headers['x_c3p_api_key'];
        }
        if ($got === '' && isset($_SERVER['HTTP_X_C3P_API_KEY'])) {
            $got = (string) $_SERVER['HTTP_X_C3P_API_KEY'];
        }
        return $got !== '' && hash_equals($expected, $got);
    }

    /** @return array<string,mixed>|null */
    public static function get_state(int $login): ?array {
        global $wpdb;
        $row = $wpdb->get_row(
            $wpdb->prepare('SELECT * FROM ' . self::state_table() . ' WHERE account_login = %d', $login),
            ARRAY_A
        );
        return is_array($row) ? $row : null;
    }

    /** @param array<string,mixed> $data */
    public static function upsert_state(int $login, array $data): array {
        global $wpdb;
        $t = self::state_table();
        $now = current_time('mysql');

        $payload = [
            'account_login'          => $login,
            'saved_reserve'          => (float) ($data['saved_reserve'] ?? 0),
            'cycle_anchor'           => (float) ($data['cycle_anchor'] ?? 0),
            'cycle_phase'            => (int) ($data['cycle_phase'] ?? 0),
            'lot_scale_equity'       => (float) ($data['lot_scale_equity'] ?? 0),
            'reserve_total_injected' => (float) ($data['reserve_total_injected'] ?? 0),
            'broker_name'            => sanitize_text_field((string) ($data['broker_name'] ?? '')),
            'updated_at'             => $now,
        ];

        $exists = self::get_state($login);
        if ($exists) {
            $wpdb->update($t, $payload, ['account_login' => $login]);
        } else {
            $payload['created_at'] = $now;
            $wpdb->insert($t, $payload);
        }

        return ['success' => true, 'state' => self::get_state($login)];
    }

    /** @param array<string,mixed> $entry */
    public static function append_ledger(int $login, array $entry): array {
        global $wpdb;
        $t = self::ledger_table();

        $row = [
            'account_login' => $login,
            'event_time'    => !empty($entry['event_time'])
                ? gmdate('Y-m-d H:i:s', (int) $entry['event_time'])
                : current_time('mysql'),
            'entry_type'    => sanitize_text_field((string) ($entry['entry_type'] ?? 'UNKNOWN')),
            'amount'        => (float) ($entry['amount'] ?? 0),
            'saved_after'   => (float) ($entry['saved_after'] ?? 0),
            'balance_after' => (float) ($entry['balance_after'] ?? 0),
            'margin_level'  => (float) ($entry['margin_level'] ?? 0),
            'symbol'        => sanitize_text_field((string) ($entry['symbol'] ?? '')),
            'cluster_tag'   => sanitize_text_field((string) ($entry['cluster_tag'] ?? '')),
            'reason'        => sanitize_text_field((string) ($entry['reason'] ?? '')),
            'deal_ticket'   => (int) ($entry['deal_ticket'] ?? 0),
            'status'        => sanitize_text_field((string) ($entry['status'] ?? 'confirmed')),
            'meta_json'     => wp_json_encode($entry['meta'] ?? [], JSON_UNESCAPED_UNICODE),
            'created_at'    => current_time('mysql'),
        ];

        $ok = $wpdb->insert($t, $row);
        if (!$ok) {
            return ['success' => false, 'message' => 'ledger insert failed'];
        }

        return ['success' => true, 'id' => (int) $wpdb->insert_id, 'entry' => $row];
    }

    /** @return array<int,array<string,mixed>> */
    public static function ledger(int $login, int $limit = 200, ?string $from = null, ?string $to = null): array {
        global $wpdb;
        $t = self::ledger_table();
        $where = 'account_login = %d';
        $args  = [$login];

        if ($from) {
            $where .= ' AND event_time >= %s';
            $args[] = $from . ' 00:00:00';
        }
        if ($to) {
            $where .= ' AND event_time <= %s';
            $args[] = $to . ' 23:59:59';
        }

        $sql = $wpdb->prepare(
            "SELECT * FROM {$t} WHERE {$where} ORDER BY id DESC LIMIT %d",
            ...array_merge($args, [max(1, min(1000, $limit))])
        );

        $rows = $wpdb->get_results($sql, ARRAY_A);
        return is_array($rows) ? $rows : [];
    }

    /** @param array<string,mixed> $data */
    public static function create_pending(int $login, array $data): array {
        global $wpdb;
        $t = self::pending_table();

        $type = strtoupper(sanitize_text_field((string) ($data['pending_type'] ?? '')));
        if (!in_array($type, ['WITHDRAW', 'DEPOSIT', 'RECALL'], true)) {
            return ['success' => false, 'message' => 'invalid pending_type'];
        }

        $amount = (float) ($data['amount'] ?? 0);
        if ($amount <= 0) {
            return ['success' => false, 'message' => 'amount must be positive'];
        }

        $row = [
            'account_login' => $login,
            'pending_type'  => $type,
            'amount'        => $amount,
            'reason'        => sanitize_text_field((string) ($data['reason'] ?? '')),
            'cluster_tag'   => sanitize_text_field((string) ($data['cluster_tag'] ?? '')),
            'status'        => 'pending',
            'created_at'    => current_time('mysql'),
            'expires_at'    => gmdate('Y-m-d H:i:s', time() + (int) ($data['ttl_sec'] ?? 86400 * 3)),
        ];

        $wpdb->insert($t, $row);

        return ['success' => true, 'id' => (int) $wpdb->insert_id, 'pending' => $row];
    }

    /** @return array<int,array<string,mixed>> */
    public static function pending_list(int $login, string $status = 'pending'): array {
        global $wpdb;
        $t = self::pending_table();
        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$t} WHERE account_login = %d AND status = %s ORDER BY id DESC LIMIT 50",
                $login,
                $status
            ),
            ARRAY_A
        );
        return is_array($rows) ? $rows : [];
    }

    public static function confirm_pending(int $id, int $login, int $deal_ticket = 0): array {
        global $wpdb;
        $t = self::pending_table();
        $row = $wpdb->get_row(
            $wpdb->prepare("SELECT * FROM {$t} WHERE id = %d AND account_login = %d", $id, $login),
            ARRAY_A
        );
        if (!$row) {
            return ['success' => false, 'message' => 'pending not found', 'http' => 404];
        }
        if ($row['status'] !== 'pending') {
            return ['success' => true, 'already' => true, 'pending' => $row];
        }

        $wpdb->update(
            $t,
            [
                'status'            => 'matched',
                'matched_deal_ticket' => $deal_ticket,
                'matched_at'        => current_time('mysql'),
            ],
            ['id' => $id]
        );

        $row['status'] = 'matched';
        $row['matched_deal_ticket'] = $deal_ticket;

        return ['success' => true, 'pending' => $row];
    }
}
