<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }
function lt_core_register_rest_routes(){
    register_rest_route('law-temple/v1','/directory',array('methods'=>WP_REST_Server::READABLE,'callback'=>'lt_core_rest_directory','permission_callback'=>'__return_true','args'=>array('type'=>array('sanitize_callback'=>'sanitize_key'),'q'=>array('sanitize_callback'=>'sanitize_text_field'),'practice'=>array('sanitize_callback'=>'absint'),'sector'=>array('sanitize_callback'=>'absint'),'office'=>array('sanitize_callback'=>'absint'))));
    register_rest_route('law-temple/v1','/search',array('methods'=>WP_REST_Server::READABLE,'callback'=>'lt_core_rest_search','permission_callback'=>'__return_true','args'=>array('q'=>array('required'=>true,'sanitize_callback'=>'sanitize_text_field'),'limit'=>array('sanitize_callback'=>'absint'))));
    register_rest_route('law-temple/v1','/entities',array('methods'=>WP_REST_Server::READABLE,'callback'=>'lt_core_rest_entities','permission_callback'=>'lt_core_rest_entities_permission','args'=>array('type'=>array('required'=>true,'sanitize_callback'=>'sanitize_key'),'q'=>array('sanitize_callback'=>'sanitize_text_field'),'include'=>array('sanitize_callback'=>'sanitize_text_field'),'limit'=>array('sanitize_callback'=>'absint'))));
}
function lt_core_rest_entities_permission(){return current_user_can('edit_posts')||current_user_can('lt_access_firm_dashboard')||current_user_can('manage_options');}
function lt_core_rest_directory(WP_REST_Request $request){$type=$request->get_param('type')?:'lawyer';$allowed=array('lawyer','practice','insight','matter','office','career');if(!in_array($type,$allowed,true))$type='lawyer';$args=array('post_type'=>$type,'post_status'=>'publish','posts_per_page'=>50,'s'=>$request->get_param('q')?:'','orderby'=>'menu_order title','order'=>'ASC');
    $meta=array();$sets=array();
    if('lawyer'===$type&&$request['practice']){if(function_exists('lt_core_relationship_source_ids')&&lt_core_relationship_table_exists())$sets[]=lt_core_relationship_source_ids('lawyer','lt_practice_ids',absint($request['practice']),0);else $meta[]=array('key'=>'lt_practice_ids','value'=>'(^|,)'.absint($request['practice']).'(,|$)','compare'=>'REGEXP');}
    if('lawyer'===$type&&$request['office']){if(function_exists('lt_core_relationship_source_ids')&&lt_core_relationship_table_exists())$sets[]=lt_core_relationship_source_ids('lawyer','lt_office_ids',absint($request['office']),0);else $meta[]=array('key'=>'lt_office_ids','value'=>'(^|,)'.absint($request['office']).'(,|$)','compare'=>'REGEXP');}
    foreach($sets as $set){$args['post__in']=isset($args['post__in'])?array_values(array_intersect((array)$args['post__in'],$set)):$set;}if($sets&&empty($args['post__in']))$args['post__in']=array(0);if($meta)$args['meta_query']=$meta;
    if($request['sector'])$args['tax_query']=array(array('taxonomy'=>'sector','field'=>'term_id','terms'=>absint($request['sector'])));
    $q=new WP_Query($args);$items=array_map(function($p)use($type){return array('id'=>$p->ID,'title'=>get_the_title($p),'url'=>get_permalink($p),'excerpt'=>get_the_excerpt($p),'image'=>get_the_post_thumbnail_url($p,'medium_large'),'role'=>'lawyer'===$type?get_post_meta($p->ID,'lt_role',true):'','position'=>'lawyer'===$type?get_post_meta($p->ID,'lt_position',true):'');},$q->posts);return rest_ensure_response(array('items'=>$items,'count'=>count($items)));}


function lt_core_search_add_candidate( &$scores, $post_id, $score ) {
    $post_id = absint( $post_id );
    if ( ! $post_id || 'publish' !== get_post_status( $post_id ) ) { return; }
    if ( 'lawyer' === get_post_type( $post_id ) && 'hidden' === get_post_meta( $post_id, 'lt_profile_visibility', true ) ) { return; }
    if ( 'practice' === get_post_type( $post_id ) && 'hidden' === get_post_meta( $post_id, 'lt_archive_visibility', true ) ) { return; }
    $scores[ $post_id ] = max( $scores[ $post_id ] ?? 0, absint( $score ) );
}

/**
 * Taxonomy- and relationship-aware legal search. Direct textual matches rank
 * highest; structured sector/practice/profile matches supplement them.
 */
function lt_core_rest_search( WP_REST_Request $request ) {
    $term = trim( (string) $request->get_param( 'q' ) );
    if ( function_exists('mb_strlen') ? mb_strlen($term) < 2 : strlen($term) < 2 ) { return rest_ensure_response( array( 'items'=>array(), 'count'=>0 ) ); }
    $configured_limit = max( 1, min( 20, absint( lt_core_option( 'search_max_results', 8 ) ) ) );
    $requested_limit  = absint( $request->get_param( 'limit' ) );
    $limit = $requested_limit ? max( 1, min( $configured_limit, $requested_limit ) ) : $configured_limit;
    $allowed_types = array( 'page','practice','lawyer','insight','matter','office','career' );
    $configured_types = array_values( array_intersect( $allowed_types, array_filter( array_map( 'sanitize_key', preg_split( '/[\s,]+/', (string) lt_core_option( 'search_types', implode( ',', $allowed_types ) ) ) ) ) ) );
    if ( ! $configured_types ) { $configured_types = $allowed_types; }
    $types = apply_filters( 'lt_core_search_post_types', $configured_types );
    $include_metadata = (bool) lt_core_option( 'search_include_metadata', 1 );
    $include_relationships = (bool) lt_core_option( 'search_include_relationships', 1 );
    $scores = array();

    // Direct WordPress full-text matches.
    $direct = get_posts( array( 'post_type'=>$types, 'post_status'=>'publish', 'posts_per_page'=>40, 's'=>$term, 'orderby'=>'relevance date', 'order'=>'DESC', 'no_found_rows'=>true ) );
    foreach ( $direct as $post ) {
        $score = stripos( (string) $post->post_title, $term ) !== false ? 100 : 72;
        lt_core_search_add_candidate( $scores, $post->ID, $score );
    }

    // Structured professional/office metadata matches.
    if ( $include_metadata ) {
        $meta_queries = array(
            'lawyer'=>array( 'lt_role','lt_position','lt_short_bio' ),
            'office'=>array( 'lt_city','lt_country','lt_address','lt_digital_address' ),
        );
        foreach ( $meta_queries as $post_type => $keys ) {
            if ( ! in_array( $post_type, $types, true ) ) { continue; }
            $mq = array( 'relation'=>'OR' );
            foreach ( $keys as $key ) { $mq[] = array( 'key'=>$key, 'value'=>$term, 'compare'=>'LIKE' ); }
            $posts = get_posts( array( 'post_type'=>$post_type, 'post_status'=>'publish', 'posts_per_page'=>20, 'meta_query'=>$mq, 'no_found_rows'=>true ) );
            foreach ( $posts as $post ) { lt_core_search_add_candidate( $scores, $post->ID, 58 ); }
        }
    }

    // Sector matches surface content assigned to matching industry terms.
    if ( $include_relationships && taxonomy_exists( 'sector' ) ) {
        $terms = get_terms( array( 'taxonomy'=>'sector', 'hide_empty'=>false, 'search'=>$term, 'number'=>10 ) );
        if ( ! is_wp_error( $terms ) ) {
            foreach ( $terms as $sector ) {
                $ids = get_objects_in_term( $sector->term_id, 'sector' );
                if ( ! is_wp_error( $ids ) ) { foreach ( $ids as $id ) { lt_core_search_add_candidate( $scores, $id, 62 ); } }
            }
        }
    }

    // Matching practice names surface professionals, insights and matters linked to them.
    $practices = $include_relationships ? get_posts( array( 'post_type'=>'practice', 'post_status'=>'publish', 'posts_per_page'=>10, 's'=>$term, 'no_found_rows'=>true ) ) : array();
    foreach ( $practices as $practice ) {
        lt_core_search_add_candidate( $scores, $practice->ID, 92 );
        foreach ( array_values( array_intersect( array( 'lawyer','insight','matter' ), $types ) ) as $related_type ) {
            $q = function_exists( 'lt_core_relationship_query' ) ? lt_core_relationship_query( $related_type, 'lt_practice_ids', $practice->ID, 20 ) : null;
            if ( $q ) { foreach ( $q->posts as $post ) { lt_core_search_add_candidate( $scores, $post->ID, 55 ); } }
        }
        if ( in_array( 'lawyer', $types, true ) ) { foreach ( lt_core_get_related_ids( $practice->ID, 'lt_lawyer_ids' ) as $id ) { lt_core_search_add_candidate( $scores, $id, 56 ); } }
        if ( in_array( 'insight', $types, true ) ) { foreach ( lt_core_get_related_ids( $practice->ID, 'lt_insight_ids' ) as $id ) { lt_core_search_add_candidate( $scores, $id, 56 ); } }
    }

    arsort( $scores, SORT_NUMERIC );
    $ids = array_slice( array_keys( $scores ), 0, $limit );
    $items = array();
    foreach ( $ids as $id ) {
        $post = get_post( $id ); if ( ! $post ) { continue; }
        $obj = get_post_type_object( $post->post_type );
        $items[] = array(
            'id'=>$post->ID,
            'title'=>get_the_title($post),
            'url'=>get_permalink($post),
            'type'=>$obj && isset($obj->labels->singular_name) ? $obj->labels->singular_name : $post->post_type,
            'excerpt'=>wp_trim_words(wp_strip_all_tags(get_the_excerpt($post)),18),
            'score'=>(int)($scores[$id]??0),
        );
    }
    return rest_ensure_response( array( 'items'=>$items, 'count'=>count($items) ) );
}

/** Searchable entity source for Gutenberg relationship controls. */
function lt_core_rest_entities( WP_REST_Request $request ) {
    $type = sanitize_key( (string) $request->get_param( 'type' ) );
    $q = trim( (string) $request->get_param( 'q' ) );
    $include = array_filter( array_map( 'absint', explode( ',', (string) $request->get_param( 'include' ) ) ) );
    $limit = max( 1, min( 30, absint( $request->get_param( 'limit' ) ?: 20 ) ) );
    if ( in_array( $type, array( 'sector','insight_type','insight_topic' ), true ) ) {
        $args = array( 'taxonomy'=>$type, 'hide_empty'=>false, 'number'=>$limit, 'orderby'=>'name', 'order'=>'ASC' );
        if ( $q ) { $args['search'] = $q; }
        if ( $include ) { $args['include'] = $include; $args['number'] = 0; }
        $terms = get_terms( $args );
        if ( is_wp_error( $terms ) ) { return rest_ensure_response( array( 'items'=>array() ) ); }
        return rest_ensure_response( array( 'items'=>array_map( static fn($term)=>array('id'=>(int)$term->term_id,'title'=>$term->name,'type'=>$type), $terms ) ) );
    }
    $allowed = array( 'lawyer','practice','insight','office','matter','testimonial','award','career','lt_faq','lt_cta' );
    if ( ! in_array( $type, $allowed, true ) ) { return new WP_Error( 'invalid_type', __( 'Unsupported entity type.', 'law-temple-core' ), array( 'status'=>400 ) ); }
    $args = array( 'post_type'=>$type, 'post_status'=>'publish', 'posts_per_page'=>$include ? max( 1, count($include) ) : $limit, 'orderby'=>$include?'post__in':'title', 'order'=>'ASC', 'no_found_rows'=>true );
    if ( $include ) { $args['post__in'] = $include; }
    elseif ( $q ) { $args['s'] = $q; }
    $posts = get_posts( $args );
    $items = array();
    foreach ( $posts as $post ) {
        if ( 'lawyer' === $type && 'hidden' === get_post_meta( $post->ID, 'lt_profile_visibility', true ) ) { continue; }
        if ( 'practice' === $type && 'hidden' === get_post_meta( $post->ID, 'lt_archive_visibility', true ) ) { continue; }
        $items[] = array( 'id'=>(int)$post->ID, 'title'=>get_the_title($post), 'type'=>$type );
    }
    return rest_ensure_response( array( 'items'=>$items ) );
}
