<?php

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

class Niwa_AI_Model_Router {
    private $model_catalog;

    public function __construct( $model_catalog = null ) {
        $this->model_catalog = $model_catalog;
    }

    public function route_for_agent() {
        $mode = $this->read_auth_mode();
        $configured = $this->read_model_from_settings( 'model' );
        if ( $this->is_valid_for_mode( $mode, $configured ) ) {
            return $configured;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'get_default_chat_model' ) ) {
            return (string) $this->model_catalog->get_default_chat_model( $mode );
        }
        return 'gpt-5.4-mini';
    }

    public function route_for_founder_agent() {
        $mode = $this->read_auth_mode( 'founder' );
        $configured = $this->read_first_valid_founder_model( $mode, array( 'founder_agent_model' ) );
        if ( '' !== $configured ) {
            return $configured;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'get_default_founder_model' ) ) {
            return (string) $this->model_catalog->get_default_founder_model( $mode );
        }

        return ( 'oauth' === $mode ) ? 'gpt-5.4' : 'gpt-5.4-mini';
    }

    public function route_for_founder_subagent() {
        $mode = $this->read_auth_mode( 'founder' );
        $configured = $this->read_first_valid_founder_model( $mode, array( 'founder_subagent_model', 'founder_agent_model' ) );
        if ( '' !== $configured ) {
            return $configured;
        }

        return $this->route_for_founder_agent();
    }

    public function get_founder_runtime_model_status() {
        return array(
            'configured_founder_agent_model'    => $this->read_configured_founder_model( 'founder_agent_model' ),
            'configured_founder_subagent_model' => $this->read_configured_founder_model( 'founder_subagent_model' ),
            'effective_main_model'              => $this->route_for_founder_agent(),
            'effective_subagent_model'          => $this->route_for_founder_subagent(),
            'auth_mode'                         => $this->read_auth_mode( 'founder' ),
            'runtime_version'                   => defined( 'NIWA_AI_VERSION' ) ? (string) NIWA_AI_VERSION : '',
            'model_override_active'             => false,
        );
    }

    public function route_for_rlm( $price_table = array() ) {
        $mode = $this->read_auth_mode();
        if ( 'oauth' === $mode ) {
            return 'gpt-5.3-codex-spark';
        }

        $configured = $this->read_model_from_settings( 'rlm_model' );
        if ( ! $this->is_valid_for_mode( $mode, $configured ) ) {
            $configured = $this->read_model_from_settings( 'model' );
        }
        if ( $this->is_valid_for_mode( $mode, $configured ) ) {
            return $configured;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'get_default_rlm_model' ) ) {
            return (string) $this->model_catalog->get_default_rlm_model( $mode );
        }
        return 'gpt-5.4-mini';
    }

    /**
     * Route the single model used by the complete frontend chat pipeline.
     *
     * Retrieval decisions, tool continuation, and the customer-facing answer
     * all stay on this model so the frontend never performs a model handoff.
     *
     * @return string Model ID for frontend generation.
     */
    public function route_for_frontend_chat() {
        $mode = $this->read_auth_mode();

        $configured = $this->read_first_valid_model( $mode, array( 'model' ) );
        if ( '' !== $configured ) {
            return $configured;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'get_default_chat_model' ) ) {
            return (string) $this->model_catalog->get_default_chat_model( $mode );
        }

        return 'gpt-5.4-mini';
    }

    private function read_configured_founder_model( $key ) {
        $model = $this->read_founder_model_from_autonomy_settings( $key );
        if ( '' !== $model ) {
            return $model;
        }

        return $this->read_model_from_settings( $key );
    }

    private function read_model_from_settings( $key ) {
        $opts = get_option( Niwa_AI_Constants::OPT_SETTINGS, array() );
        if ( empty( $opts[ $key ] ) || ! is_string( $opts[ $key ] ) ) {
            return '';
        }
        $model = trim( (string) $opts[ $key ] );
        if ( '' === $model ) {
            return '';
        }
        $migrated = Niwa_AI_Model_Catalog::migrate_retired_selector( $model );
        if ( $migrated !== $model ) {
            $opts[ $key ] = $migrated;
            update_option( Niwa_AI_Constants::OPT_SETTINGS, $opts, false );
            $model = $migrated;
        }
        return preg_match( '/^[a-zA-Z0-9._:-]{2,80}$/', $model ) ? $model : '';
    }

    private function read_first_valid_model( $mode, $keys ) {
        foreach ( (array) $keys as $key ) {
            $model = $this->read_model_from_settings( (string) $key );
            if ( $this->is_valid_for_mode( $mode, $model ) ) {
                return $model;
            }
        }

        return '';
    }

    private function read_auth_mode( $lane = 'default' ) {
        if ( defined( 'NIWA_AI_AUTH_MODE' ) && in_array( NIWA_AI_AUTH_MODE, array( 'api_key', 'oauth' ), true ) ) {
            return strtolower( trim( (string) NIWA_AI_AUTH_MODE ) );
        }

        if ( 'founder' === sanitize_key( (string) $lane ) ) {
            $autonomy_opts = get_option( Niwa_AI_Constants::OPT_AUTONOMY, array() );
            $autonomy_opts = is_array( $autonomy_opts ) ? $autonomy_opts : array();
            $founder_mode  = isset( $autonomy_opts['founder_auth_mode'] ) ? strtolower( trim( (string) $autonomy_opts['founder_auth_mode'] ) ) : '';
            if ( in_array( $founder_mode, array( 'api_key', 'oauth' ), true ) ) {
                return $founder_mode;
            }
        }

        $opts = get_option( Niwa_AI_Constants::OPT_AUTH, array() );
        $mode = isset( $opts['mode'] ) ? strtolower( trim( (string) $opts['mode'] ) ) : 'api_key';
        return in_array( $mode, array( 'api_key', 'oauth' ), true ) ? $mode : 'api_key';
    }

    private function read_founder_model_from_autonomy_settings( $key ) {
        $opts = get_option( Niwa_AI_Constants::OPT_AUTONOMY, array() );
        if ( ! is_array( $opts ) || empty( $opts[ $key ] ) || ! is_string( $opts[ $key ] ) ) {
            return '';
        }

        $model = trim( (string) $opts[ $key ] );
        if ( '' === $model ) {
            return '';
        }

        $migrated = Niwa_AI_Model_Catalog::migrate_retired_selector( $model );
        if ( $migrated !== $model ) {
            $opts[ $key ] = $migrated;
            update_option( Niwa_AI_Constants::OPT_AUTONOMY, $opts, false );
            $model = $migrated;
        }

        return preg_match( '/^[a-zA-Z0-9._:-]{2,80}$/', $model ) ? $model : '';
    }

    private function read_first_valid_founder_model( $mode, $keys ) {
        foreach ( (array) $keys as $key ) {
            $model = $this->read_founder_model_from_autonomy_settings( (string) $key );
            if ( $this->is_valid_founder_for_mode( $mode, $model ) ) {
                return $model;
            }

            $legacy_model = $this->read_model_from_settings( (string) $key );
            if ( $this->is_valid_founder_for_mode( $mode, $legacy_model ) ) {
                return $legacy_model;
            }
        }

        return '';
    }

    private function is_valid_for_mode( $mode, $model ) {
        $mode = strtolower( trim( (string) $mode ) );
        $model = strtolower( trim( (string) $model ) );
        if ( '' === $model ) {
            return false;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'is_valid_model_for_mode' ) ) {
            return (bool) $this->model_catalog->is_valid_model_for_mode( $mode, $model );
        }

        if ( 'oauth' === $mode ) {
            if ( preg_match( '/^gpt-5\.6-(?:terra|sol)-(?:light|medium|high|xhigh)$/', $model ) ) {
                return true;
            }

            return in_array(
                $model,
                array(
                    'gpt-5.5-medium',
                    'gpt-5.5-high',
                    'gpt-5.5-xhigh',
                    'gpt-5.4',
                    'gpt-5.4-mini',
                    'gpt-5.3-codex-spark',
                    'gpt-5.3-codex',
                    'gpt-5.2-codex',
                    'gpt-5.1-codex',
                ),
                true
            );
        }

        return (bool) preg_match( '/^(?:gpt-4o|gpt-5\.[456])([-.].+)?$/', $model );
    }

    private function is_valid_founder_for_mode( $mode, $model ) {
        $mode  = strtolower( trim( (string) $mode ) );
        $model = strtolower( trim( (string) $model ) );
        if ( '' === $model ) {
            return false;
        }

        if ( $this->model_catalog && method_exists( $this->model_catalog, 'is_valid_founder_model_for_mode' ) ) {
            return (bool) $this->model_catalog->is_valid_founder_model_for_mode( $mode, $model );
        }

        return (bool) preg_match( '/^gpt-5([-.].+)?$/', $model ) || false !== strpos( $model, 'codex' );
    }

}
