<?php
/**
 * RecoveryCodesTable - stores single-use recovery code hashes.
 *
 * @package UltraguardPro\modules\authenticator\db
 */

namespace UltraguardPro\modules\authenticator\db;

use UltraguardPro\db\BaseTable;

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

class RecoveryCodesTable extends BaseTable {

    protected $table_name  = 'ultraguard_recovery_codes';
    protected $cache_group = 'ultraguard_recovery_codes';

    public function get_defaults(): array {
        return [
            'id'         => 0,
            'user_id'    => 0,
            'code_hash'  => '',
            'used_at'    => null,
            'created_at' => '',
        ];
    }

    protected function validate_data( $data ) {
        if ( empty( $data['user_id'] ) || empty( $data['code_hash'] ) ) {
            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 'used_at':
                    $out[ $k ] = null === $v ? null : sanitize_text_field( (string) $v );
                    break;

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

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

        return $out;
    }

    public function replace_for_user( int $user_id, array $hashes ): void {
        $this->delete_where( [ 'user_id' => $user_id ] );

        $rows = array_map( function ( $hash ) use ( $user_id ) {
            return [
                'user_id'   => $user_id,
                'code_hash' => $hash,
            ];
        }, $hashes );

        $this->bulk_insert( $rows );
    }

    public function get_unused( int $user_id ): array {
        $all = $this->get_by( [ 'user_id' => $user_id ], 20 );

        return array_values( array_filter( $all, function ( $row ) {
            return null === $row['used_at'];
        } ) );
    }

    public function mark_used( int $id ): bool {
        return $this->update( $id, [ 'used_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();
    }
}
