<?php

namespace AtlasAiDev\Awfah\REST;

use AtlasAiDev\Awfah\Plugin;
use WP_Error;
use WP_Post;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;

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

class Workflows_Controller extends WP_REST_Controller {

    const OPTION_KEY = 'awfah_saved_workflows';

    public function __construct() {
        $this->namespace = 'awfah/v1';
        $this->rest_base = 'workflows';
    }

    public function register_routes(): void {
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base,
            [
                [
                    'methods'             => 'GET',
                    'callback'            => [ $this, 'get_items' ],
                    'permission_callback' => [ $this, 'permissions_check' ],
                    'args'                => [
                        'context' => [
                            'default'           => 'view',
                            'sanitize_callback' => 'sanitize_key',
                        ],
                    ],
                ],
                [
                    'methods'             => 'POST',
                    'callback'            => [ $this, 'create_item' ],
                    'permission_callback' => [ $this, 'permissions_check' ],
                ],
            ]
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/run',
            [
                [
                    'methods'             => 'POST',
                    'callback'            => [ $this, 'run_workflow' ],
                    'permission_callback' => [ $this, 'permissions_check' ],
                ],
            ]
        );

        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/(?P<id>[a-zA-Z0-9\-]+)',
            [
                [
                    'methods'             => 'PUT',
                    'callback'            => [ $this, 'update_item' ],
                    'permission_callback' => [ $this, 'permissions_check' ],
                ],
                [
                    'methods'             => 'DELETE',
                    'callback'            => [ $this, 'delete_item' ],
                    'permission_callback' => [ $this, 'permissions_check' ],
                ],
            ]
        );
    }

    public function permissions_check(): bool {
        return current_user_can( 'edit_posts' );
    }

    public function get_items( $request ) {
        $context   = $request->get_param( 'context' ) ?: 'view';
        $workflows = $this->get_workflows();

        // Admin context: return all workflows unfiltered.
        if ( 'admin' === $context && current_user_can( 'manage_options' ) ) {
            return new WP_REST_Response( [ 'workflows' => $workflows ] );
        }

        // Filter workflows by current user's role.
        $allowed_ids = Plugin::get_current_user_allowed_workflows();

        $workflows = array_values( array_filter( $workflows, static function ( $w ) use ( $allowed_ids ) {
            return in_array( $w['id'] ?? '', $allowed_ids, true );
        } ) );

        return new WP_REST_Response( [ 'workflows' => $workflows ] );
    }

    public function create_item( $request ) {
        $params = $request->get_json_params();

        $workflow = $this->sanitize_workflow( $params );
        if ( is_wp_error( $workflow ) ) {
            return $workflow;
        }

        $existing = $this->get_workflows();

        // Enforce workflow count limit (free: 3, Pro: unlimited).
        $max = apply_filters( 'awfah_max_workflows', 3 );
        if ( count( $existing ) >= $max ) {
            return new \WP_Error(
                'awfah_workflow_limit',
                sprintf(
                    /* translators: %d: maximum number of workflows allowed */
                    __( 'You have reached the maximum of %d workflows. Upgrade to Pro for unlimited workflows.', 'ai-workflow-automation-ai-agent-hub' ),
                    $max
                ),
                [ 'status' => 403 ]
            );
        }

        $workflow['id']         = $workflow['id'] ?: wp_generate_uuid4();
        $workflow['created_at'] = current_time( 'mysql' );
        $workflow['updated_at'] = current_time( 'mysql' );

        $existing[] = $workflow;
        $this->save_workflows( $existing );

        return new WP_REST_Response( [ 'workflow' => $workflow ] );
    }

    public function update_item( $request ) {
        $id     = (string) $request['id'];
        $params = $request->get_json_params();

        $workflow = $this->sanitize_workflow( $params, $id );
        if ( is_wp_error( $workflow ) ) {
            return $workflow;
        }

        $workflows = $this->get_workflows();
        $found     = false;

        foreach ( $workflows as $index => $item ) {
            if ( isset( $item['id'] ) && $id === $item['id'] ) {
                $workflow['created_at'] = $item['created_at'] ?? current_time( 'mysql' );
                $workflow['updated_at'] = current_time( 'mysql' );
                $workflows[ $index ]    = $workflow;
                $found                  = true;
                break;
            }
        }

        if ( ! $found ) {
            return new WP_Error(
                'ai_workflow_not_found',
                __( 'Workflow not found.', 'ai-workflow-automation-ai-agent-hub' ),
                [ 'status' => 404 ]
            );
        }

        $this->save_workflows( $workflows );

        return new WP_REST_Response( [ 'workflow' => $workflow ] );
    }

    public function delete_item( $request ) {
        $id        = (string) $request['id'];
        $workflows = $this->get_workflows();

        $filtered = array_filter(
            $workflows,
            static function ( $item ) use ( $id ) {
                return isset( $item['id'] ) && $item['id'] !== $id;
            }
        );

        $this->save_workflows( array_values( $filtered ) );

        return new WP_REST_Response( [ 'deleted' => $id ] );
    }

    /**
     * Execute a workflow: run each ability in order via the Abilities API.
     */
    public function run_workflow( WP_REST_Request $request ) {
        $params          = $request->get_json_params();
        $ability_ids     = isset( $params['abilities'] ) && is_array( $params['abilities'] ) ? array_values( $params['abilities'] ) : [];
        $post_id         = isset( $params['post_id'] ) ? (int) $params['post_id'] : 0;
        $prompt          = isset( $params['prompt'] ) ? (string) $params['prompt'] : '';
        $provider        = isset( $params['provider'] ) ? (string) $params['provider'] : 'auto';
        $ability_params  = isset( $params['ability_params'] ) && is_array( $params['ability_params'] ) ? $params['ability_params'] : [];
        $ai_resolve      = ! empty( $params['ai_resolve_params'] );

        if ( empty( $ability_ids ) ) {
            return new WP_Error(
                'awfah_workflow_missing_abilities',
                __( 'Select at least one ability to run.', 'ai-workflow-automation-ai-agent-hub' ),
                [ 'status' => 400 ]
            );
        }

        if ( '' === $prompt ) {
            $prompt = self::build_prompt_from_abilities( $ability_ids, $post_id );
        }

        $results = [];

        foreach ( $ability_ids as $ability_id ) {
            if ( ! function_exists( 'wp_get_ability' ) ) {
                $results[ $ability_id ] = [ 'error' => __( 'Abilities API not available.', 'ai-workflow-automation-ai-agent-hub' ) ];
                continue;
            }

            $ability = wp_get_ability( $ability_id );
            if ( ! $ability ) {
                $results[ $ability_id ] = [ 'error' => __( 'Ability not found.', 'ai-workflow-automation-ai-agent-hub' ) ];
                continue;
            }

            // --- Tier 1: Explicit per-ability params ---
            if ( isset( $ability_params[ $ability_id ] ) && is_array( $ability_params[ $ability_id ] ) ) {
                $ability_input = $ability_params[ $ability_id ];
                if ( $post_id && ! isset( $ability_input['post_id'] ) ) {
                    $ability_input['post_id'] = $post_id;
                }
                if ( $post_id && ! isset( $ability_input['id'] ) ) {
                    $ability_input['id'] = $post_id;
                }
                if ( ! isset( $ability_input['provider'] ) ) {
                    $ability_input['provider'] = $provider;
                }
            }
            // --- Tier 2: AI-powered param resolution ---
            elseif ( $ai_resolve && '' !== $prompt ) {
                $resolved = self::resolve_ability_params_with_ai( $ability, $prompt, $post_id, $provider );
                if ( is_wp_error( $resolved ) ) {
                    $results[ $ability_id ] = [
                        'error'      => $resolved->get_error_message(),
                        'resolution' => 'ai_failed',
                    ];
                    continue;
                }
                $ability_input = $resolved;
            }
            // --- Tier 3: Fallback (shared context only) ---
            else {
                $ability_input = [
                    'post_id'  => $post_id,
                    'provider' => $provider,
                ];
                if ( $post_id ) {
                    $ability_input['id'] = $post_id;
                }
            }

            $result = $ability->execute( (object) $ability_input );
            $results[ $ability_id ] = is_wp_error( $result )
                ? [ 'error' => $result->get_error_message() ]
                : $result;
        }

        return new WP_REST_Response( [
            'prompt'  => $prompt,
            'results' => $results,
        ] );
    }

    /**
     * Build a human-readable prompt from ability IDs (for display / AI context).
     */
    public static function build_prompt_from_abilities( array $ability_ids, int $post_id ): string {
        $post      = $post_id ? get_post( $post_id ) : null;
        $title     = $post instanceof WP_Post ? get_the_title( $post ) : __( 'this draft', 'ai-workflow-automation-ai-agent-hub' );
        $summaries = [];

        foreach ( $ability_ids as $ability_id ) {
            if ( function_exists( 'wp_get_ability' ) ) {
                $ability = wp_get_ability( $ability_id );
                if ( $ability ) {
                    $summaries[] = sprintf( '- %s: %s', $ability->get_label(), $ability->get_description() );
                    continue;
                }
            }
            $summaries[] = sprintf( '- %s', $ability_id );
        }

        $summary_text = implode( "\n", $summaries );

        return sprintf(
            "You are assisting with the post titled '%s'. Apply the following abilities in sequence and provide clear, concise output for each ability:\n%s\nReturn a structured summary per ability.",
            $title,
            $summary_text
        );
    }

    /**
     * Use AI to extract structured parameters for an ability from the workflow prompt.
     *
     * @param \WP_Ability $ability  The ability instance.
     * @param string      $prompt   The user's natural language workflow prompt.
     * @param int         $post_id  The current post ID (0 if none).
     * @param string      $provider The selected AI provider.
     * @return array|WP_Error Resolved parameters array, or WP_Error on failure.
     */
    private static function resolve_ability_params_with_ai( $ability, string $prompt, int $post_id, string $provider ) {
        $input_schema = $ability->get_input_schema();
        if ( empty( $input_schema ) || empty( $input_schema['properties'] ) ) {
            // No schema to resolve — return defaults.
            $fallback = [ 'post_id' => $post_id, 'provider' => $provider ];
            if ( $post_id ) {
                $fallback['id'] = $post_id;
            }
            return $fallback;
        }

        $known_params = [ 'provider' => $provider ];
        if ( $post_id ) {
            $known_params['post_id'] = $post_id;
            $known_params['id']      = $post_id;
        }

        // Build JSON schema for structured AI output.
        $resolution_schema = [
            'type'       => 'object',
            'properties' => $input_schema['properties'],
        ];
        if ( ! empty( $input_schema['required'] ) ) {
            $resolution_schema['required'] = $input_schema['required'];
        }

        $ai_prompt = sprintf(
            "You are a parameter extraction assistant. Extract parameter values from the user's instruction to match the JSON Schema below.\n\n"
            . "Ability: %s\nDescription: %s\n\n"
            . "Known context (use as defaults, do NOT override unless the user explicitly specifies different values):\n%s\n\n"
            . "JSON Schema:\n%s\n\n"
            . "User instruction:\n%s\n\n"
            . "Return ONLY a valid JSON object matching the schema. For required parameters not found in the instruction or known context, use a sensible default.",
            $ability->get_label(),
            $ability->get_description(),
            wp_json_encode( $known_params, JSON_PRETTY_PRINT ),
            wp_json_encode( $resolution_schema, JSON_PRETTY_PRINT ),
            $prompt
        );

        try {
            $result = \AtlasAiDev\Awfah\Service\AI_Provider_Manager::generate_text_with_usage(
                $ai_prompt,
                [
                    'json_schema' => $resolution_schema,
                    'temperature' => 0.3,
                    'tool_slug'   => 'workflow-param-resolution',
                    'post_id'     => $post_id,
                ]
            );
        } catch ( \Throwable $e ) {
            return new WP_Error(
                'awfah_ai_resolution_failed',
                sprintf(
                    /* translators: 1: ability label, 2: error message */
                    __( 'AI param resolution failed for "%1$s": %2$s', 'ai-workflow-automation-ai-agent-hub' ),
                    $ability->get_label(),
                    $e->getMessage()
                )
            );
        }

        $text = $result['text'] ?? '';
        if ( '' === $text ) {
            return new WP_Error(
                'awfah_ai_resolution_empty',
                sprintf(
                    /* translators: %s: ability label */
                    __( 'AI returned an empty response for ability "%s".', 'ai-workflow-automation-ai-agent-hub' ),
                    $ability->get_label()
                )
            );
        }

        $resolved = json_decode( $text, true );
        if ( ! is_array( $resolved ) ) {
            return new WP_Error(
                'awfah_ai_resolution_invalid_json',
                sprintf(
                    /* translators: %s: ability label */
                    __( 'AI returned invalid JSON for ability "%s".', 'ai-workflow-automation-ai-agent-hub' ),
                    $ability->get_label()
                )
            );
        }

        // Merge known params as fallbacks.
        foreach ( $known_params as $key => $value ) {
            if ( ! isset( $resolved[ $key ] ) ) {
                $resolved[ $key ] = $value;
            }
        }

        return $resolved;
    }

    private function sanitize_workflow( array $params, string $forced_id = '' ) {
        $name       = isset( $params['name'] ) ? sanitize_text_field( wp_unslash( $params['name'] ) ) : '';
        $abilities  = isset( $params['abilities'] ) && is_array( $params['abilities'] ) ? array_values( array_map( 'sanitize_text_field', $params['abilities'] ) ) : [];
        $prompt     = isset( $params['prompt'] ) ? wp_kses_post( $params['prompt'] ) : '';
        $id         = $forced_id ?: ( isset( $params['id'] ) ? sanitize_text_field( $params['id'] ) : '' );

        $assigned_roles = isset( $params['assigned_roles'] ) && is_array( $params['assigned_roles'] )
            ? array_values( array_map( 'sanitize_key', $params['assigned_roles'] ) )
            : [ 'all' ];

        if ( '' === $name ) {
            return new WP_Error(
                'ai_workflow_missing_name',
                __( 'Workflow name is required.', 'ai-workflow-automation-ai-agent-hub' ),
                [ 'status' => 400 ]
            );
        }

        if ( empty( $abilities ) ) {
            return new WP_Error(
                'ai_workflow_missing_abilities',
                __( 'Select at least one ability for this workflow.', 'ai-workflow-automation-ai-agent-hub' ),
                [ 'status' => 400 ]
            );
        }

        return [
            'id'             => $id,
            'name'           => $name,
            'abilities'      => $abilities,
            'prompt'         => $prompt,
            'assigned_roles' => $assigned_roles,
        ];
    }

    private function get_workflows(): array {
        $stored = get_option( self::OPTION_KEY, [] );
        return is_array( $stored ) ? $stored : [];
    }

    private function save_workflows( array $workflows ): void {
        update_option( self::OPTION_KEY, $workflows );
    }
}
