<?php
/**
 * PasskeyChallengesTable - short-lived WebAuthn challenge nonces.
 *
 * @package UltraguardPro\modules\authenticator\db
 */

namespace UltraguardPro\modules\authenticator\db;

use UltraguardPro\db\BaseTable;

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

class PasskeyChallengesTable extends BaseTable {

    protected $table_name  = 'ultraguard_passkey_challenges';
    protected $cache_group = 'ultraguard_passkey_challenges';

    public function get_defaults(): array {
        return [
            'id'         => 0,
            'user_id'    => 0,
            'challenge'  => '',
            'type'       => 'authentication',
            'expires_at' => '',
            'created_at' => '',
        ];
    }

    protected function validate_data( $data ) {
        if ( empty( $data['user_id'] ) || empty( $data['challenge'] ) || empty( $data['type'] ) ) {
            return false;
        }

        if ( ! in_array( $data['type'], [ 'registration', 'authentication' ], true ) ) {
            return false;
        }

        return $data;
    }

    protected function sanitize_data( $data ): array {
        $out = [];

        foreach ( $data as $k => $v ) {
            switch ( $k ) {
                case 'user_id':
                    $out[ $k ] = absint( $v );
                    break;

                case 'type':
                    $out[ $k ] = sanitize_key( (string) $v );
                    break;

                case 'challenge':
                    $out[ $k ] = sanitize_text_field( (string) $v );
                    break;

                default:
                    $out[ $k ] = is_string( $v ) ? sanitize_text_field( $v ) : $v;
                    break;
            }
        }

        return $out;
    }

    public function store( int $user_id, string $challenge, string $type ) {
        $this->delete_where( [ 'user_id' => $user_id, 'type' => $type ] );

        return $this->insert( [
            'user_id'    => $user_id,
            'challenge'  => $challenge,
            'type'       => $type,
            'expires_at' => gmdate( 'Y-m-d H:i:s', time() + 5 * MINUTE_IN_SECONDS ),
        ] );
    }

    public function consume( int $user_id, string $type ): ?string {
        $rows = $this->get_by( [ 'user_id' => $user_id, 'type' => $type ], 1 );

        if ( empty( $rows ) ) {
            return null;
        }

        $row = $rows[0];

        if ( strtotime( $row['expires_at'] ) < time() ) {
            $this->delete( (int) $row['id'] );
            return null;
        }

        $this->delete( (int) $row['id'] );

        return $row['challenge'];
    }

    public function purge_expired(): void {
        $this->delete_where( [ 'expires_at <' => gmdate( 'Y-m-d H:i:s' ) ] );
    }

    protected function invalidate_caches_after_insert() {
        $this->clear_all_caches();
    }

    protected function invalidate_caches_after_update( $id ) {
        $this->clear_all_caches();
    }

    protected function invalidate_caches_after_bulk() {
        $this->clear_all_caches();
    }
}
