<?php

namespace Limb_Chatbot\Includes\Services;

use Limb_Chatbot\Includes\Chatbot_Tools\Seeders\Actions_Seeder;
use Limb_Chatbot\Includes\Data_Objects\Lead_Field;
use Limb_Chatbot\Includes\Data_Objects\Widget;
use Limb_Chatbot\Includes\Services\System_Message\Chatbot_System_Message_Generator;
use Exception;
use Limb_Chatbot\Includes\Ai_Providers\AI_Providers;
use Limb_Chatbot\Includes\Data_Objects\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Setting;
use Limb_Chatbot\Includes\Data_Schemas;
use Limb_Chatbot\Includes\Database_Strategies\WPDB;
use Limb_Chatbot\Includes\Utilities\Chatbot_Utility;

/**
 * Class Seeder_Service
 *
 * Responsible for seeding initial data such as AI models and default settings.
 *
 * @since 1.0.0
 */
class Seeder_Service {
	/**
	 * @var false|mixed
	 */
	private bool $force = false;
	private bool $seed_default_widgets_on_first_activation = false;

	public function __construct( $force = false, bool $seed_default_widgets_on_first_activation = false ) {
		$this->force                                    = $force;
		$this->seed_default_widgets_on_first_activation = $seed_default_widgets_on_first_activation;
	}
	/**
	 * Runs the seeding process inside a transaction, handling errors gracefully.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function seed(): void {
		$wpdb = WPDB::instance();
		register_shutdown_function( function () {
			$error = error_get_last();
			if ( $error && in_array( $error['type'], [ E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR ] ) ) {
				$this->store_activation_error( $error );
			}
		} );
		try {
			$wpdb->start_transaction();
			$this->seed_ai_models();
			$this->seed_lead_fields();
			$this->seed_setting_defaults();
			$this->seed_default_widgets_once();
			$this->seed_system_instructions();
			$this->seed_actions();
			$wpdb->commit_transaction();
		} catch ( Exception $e ) {
			$wpdb->rollback_transaction();
			$this->store_activation_error( $e );
		}
	}

	/**
	 * Adds a setting if it does not already exist.
	 *
	 * @param string $key   Setting key.
	 * @param mixed  $value Setting value.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function maybe_add_setting( $key, $value ): void {
		if ( $this->force ) {
			Setting::create( [ 'key' => $key, 'value' => $value ] );
		} else {
			if ( ! Setting::exists( $key ) ) {
				Setting::create( [ 'key' => $key, 'value' => $value ] );
			}
		}
	}

	/**
	 * Stores an activation error in the settings for later inspection.
	 *
	 * @param mixed $error Error object or array describing the error.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function store_activation_error( $error ): void {
		$is_object = is_object( $error );
		Setting::update( [ 'key' => 'lbaic.plugins.'.Limb_Chatbot()->get_plugin_name().'.activation_error' ], [
			'value' => json_encode( [
				'type'    => $is_object ? get_class( $error ) : 'fatal',
				'message' => $is_object ? $error->getMessage() : $error,
				'file'    => $is_object ? $error->getFile() : '',
				'line'    => $is_object ? $error->getLine() : '',
				'trace'   => $is_object ? $error->getTraceAsString() : '',
				'time'    => current_time( 'mysql' ),
			] )
		] );
	}

	/**
	 * Seeds AI models by running the seeders provided by all registered AI providers.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function seed_ai_models(): void {
		foreach ( AI_Providers::instance()->get_ai_providers() as $ai_provider ) {
			$models_seeder = "Limb_Chatbot\\Includes\\AI_Providers\\{$ai_provider::$name}\\Seeders\\AI_Models_Seeder";
			if ( class_exists( $models_seeder ) ) {
				$models_seeder = new $models_seeder();
				$models_seeder->run();
			}
		}
	}

	/**
	 * Seeds default settings based on rules defined in the data schemas.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function seed_setting_defaults(): void {
		foreach (
		( Data_Schemas\Setting::general_rules() + Data_Schemas\Setting::chatbot_rules() + Data_Schemas\Setting::kb_rules() + Data_Schemas\Setting::fine_tuning_rules() + Data_Schemas\Setting::ai_provider_rules() + Data_Schemas\Setting::copilot_rules()  )
			as $key => $rule
		) {
			if ( isset( $rule['default'] ) ) {
				$this->maybe_add_setting( $key, $rule['default'] );
			}
		}
		update_option( 'lbaic.plugin.current_version', Limb_Chatbot()->get_version() );
	}

	/**
	 * Save default system instructions for the default chatbot
	 *
	 * @return void
	 * @throws Exception
	 */
	private function seed_system_instructions() {
		$chatbot                  = Chatbot::make(); // default chatbot
		$system_message_generator = new Chatbot_System_Message_Generator ();
		$chatbot_utility          = new Chatbot_Utility( $chatbot, true );
		$internal_system          = $system_message_generator->generate( $chatbot_utility, [], true );
		$chatbot->update_parameter( 'internal_system_message', $internal_system );
	}

	/**
	 * Seeds the actions with callbacks for testing
	 *
	 * @return void
	 */
	private function seed_actions () {
		$forms_seeder = new Actions_Seeder();
		$forms_seeder->seed();
	}

	public function seed_lead_fields() {
		try {
			// Check if default fields already exist
			$name_fields  = Lead_Field::where( [ 'field_key' => 'full_name' ] );
			$email_fields = Lead_Field::where( [ 'field_key' => 'email' ] );

			// Create email field if it doesn't exist
			if ( $email_fields->is_empty() ) {
				Lead_Field::create( [
					'field_key' => 'email',
					'label'     => 'Email Address',
					'data_type' => 'email',
				] );
			}

			// Create full_name field if it doesn't exist
			if ( $name_fields->is_empty() ) {
				Lead_Field::create( [
					'field_key' => 'full_name',
					'label'     => 'Full Name',
					'data_type' => 'string',
				] );
			}

			return true;
		} catch ( \Exception $e ) {
			return false;
		}
	}

	public function seed_default_widgets_once(): void {
		if ( ! $this->seed_default_widgets_on_first_activation ) {
			return;
		}

		$seeded_key = 'lbaic.plugin.default_widgets_seeded_once';
		if ( Setting::exists( $seeded_key ) ) {
			return;
		}

		// Skip writing defaults when widgets already exist (e.g. migrated/free installs).
		if ( ! Widget::where( [], 1, 1 )->is_empty() ) {
			$this->maybe_add_setting( $seeded_key, 1 );
			return;
		}

		$blog_name          = (string) get_option( 'blogname', '' );
		$privacy_policy_url = get_privacy_policy_url();
		if ( empty( $privacy_policy_url ) ) {
			$privacy_policy_url = home_url( '/privacy-policy' );
		}
		$seeded_at       = current_time( 'mysql', true );
		$supports_emojis = WPDB::instance()->table_supports_emojis( Widget::TABLE_NAME );

		$greeting_daytime_based = $supports_emojis
			? [
				'5'  => '☀️ Good morning!',
				'12' => '👋 Good afternoon!',
				'18' => '🌙 Good evening!',
			]
			: [
				'5'  => 'Good morning!',
				'12' => 'Good afternoon!',
				'18' => 'Good evening!',
			];

		$messages_intro = $supports_emojis
			? 'Hi there! 👋, Need any help?'
			: 'Hi there! Need any help?';

		$default_widgets = [
			[
				'uuid'       => '8674ba6a-101a-49d8-9ac8-45651d79d07a',
				'type'       => 'header',
				'published'  => 1,
				'config'     => [
					'logo'                           => 'monogram',
					'custom_logo'                    => [ 'type' => 'image', 'image' => '', 'svg' => '' ],
					'company_name'                   => $blog_name,
					'show_company_name'              => true,
					'show_ai_avatar'                 => true,
					'show_active_live_agents_avatar' => true,
				],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 1,
			],
			[
				'uuid'       => '459cc6b8-e8bf-4c33-8a70-6b3ce91abeaa',
				'type'       => 'greeting',
				'published'  => 1,
				'config'     => [
					'mode'          => 'daytime_based',
					'daytime_based' => $greeting_daytime_based,
					'custom'        => 'Welcome!',
					'sub_greeting'  => 'How can we help you?',
					'tagline'       => "We're here to answer your questions instantly and connect you with our team",
				],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 2,
			],
			[
				'uuid'       => '06a896bd-ad4d-47fd-9ddb-35b8773bd077',
				'type'       => 'start_chat_button',
				'published'  => 1,
				'config'     => [ 'text' => 'Chat with me...', 'typing_indicator' => true ],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 3,
			],
			[
				'uuid'       => '2564d0da-6b26-4c75-a761-118275e5756c',
				'type'       => 'availability',
				'published'  => 1,
				'config'     => [ 'status_text' => 'Online Now', 'response_time' => 'Typically replies in seconds' ],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 4,
			],
			[
				'uuid'       => '179b95cf-231f-4e74-8388-7ba0ccda52f9',
				'type'       => 'chats',
				'published'  => 1,
				'config'     => [ 'section_title' => 'Recent Conversations', 'max_items' => 2 ],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 5,
			],
			[
				'uuid'       => 'a18da450-eb14-4a70-a16c-c4574939c96f',
				'type'       => 'messages',
				'published'  => 1,
				'config'     => [
					'items' => [
						[
							'content' => [
								[
									'type' => 'text',
									'text' => [ 'value' => $messages_intro ],
								],
							],
						],
					],
					'sync'  => 'auto',
				],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'new_chat' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 3,
			],
			[
				'uuid'       => '5ecfab88-58b3-468d-b2dd-bddf7118f18d',
				'type'       => 'privacy_policy',
				'published'  => 0,
				'config'     => [ 'text' => '', 'url' => $privacy_policy_url ],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'new_chat' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 1,
			],
			[
				'uuid'       => '0a74ada1-0fa4-408a-94bb-60a2a2943a5f',
				'type'       => 'messages',
				'published'  => 1,
				'config'     => [
					'items'      => [
						[
							'content' => [
								[
									'type' => 'text',
									'text' => [ 'value' => $messages_intro ],
								],
							],
						],
					],
					'sync'       => 'auto',
					'appearance' => [ 'theme' => 'inherit' ],
				],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'chatbot_icon' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 1,
			],
			[
				'uuid'       => 'eed732cc-484a-498b-ad81-a76df2461a59',
				'type'       => 'prompts',
				'published'  => 1,
				'config'     => [
					'section_title' => 'Try asking',
					'items'         => [
						[
							'content' => [ [ 'type' => 'text', 'text' => [ 'value' => 'What can you help me with today?' ] ] ],
							'value'   => [ [ 'type' => 'text', 'text' => [ 'value' => '' ] ] ],
						],
						[
							'content' => [ [ 'type' => 'text', 'text' => [ 'value' => 'I’m looking for something.' ] ] ],
							'value'   => [ [ 'type' => 'text', 'text' => [ 'value' => '' ] ] ],
						],
						[
							'content' => [ [ 'type' => 'text', 'text' => [ 'value' => 'Hey! Need some help?' ] ] ],
							'value'   => [ [ 'type' => 'text', 'text' => [ 'value' => '' ] ] ],
						],
						[
							'content' => [ [ 'type' => 'text', 'text' => [ 'value' => 'Not sure what I need.' ] ] ],
							'value'   => [ [ 'type' => 'text', 'text' => [ 'value' => '' ] ] ],
						],
					],
				],
				'locations'  => [ [ [ 'param' => 'screen', 'operator' => '===', 'value' => 'home' ] ] ],
				'visibility' => [ 'roles' => [ 'everyone' ] ],
				'order'      => 6,
			],
		];

		foreach ( $default_widgets as $widget ) {
			Widget::create(
				array_merge(
					$widget,
					[
						'created_at' => $seeded_at,
						'updated_at' => $seeded_at,
					]
				)
			);
		}

		$this->maybe_add_setting( $seeded_key, 1 );
	}
}