<?php
/**
 * Plugin activation, deactivation, and database migration handler.
 *
 * @package MerchantKits\AttendanceManager
 */

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

/**
 * Handles creating database tables, seeding default data, and registering
 * default options on activation; clears scheduled events on deactivation.
 */
class MKAM_Activator {

	/**
	 * Run activation routines.
	 *
	 * @return void
	 */
	public static function activate() {
		self::create_tables();
		self::seed_default_shifts();
		self::seed_default_leave_policies();
		self::set_default_options();
		self::schedule_events();

		update_option( 'mkam_db_version', MKAM_DB_VERSION );
		flush_rewrite_rules();
	}

	/**
	 * Run deactivation routines.
	 *
	 * @return void
	 */
	public static function deactivate() {
		self::clear_events();
		flush_rewrite_rules();
	}

	/**
	 * Return the fully qualified table name for a given suffix.
	 *
	 * @param string $suffix Table suffix without the mkam_ prefix.
	 * @return string
	 */
	public static function table( $suffix ) {
		global $wpdb;
		return $wpdb->prefix . 'mkam_' . $suffix;
	}

	/**
	 * Create the five custom tables via dbDelta().
	 *
	 * @return void
	 */
	public static function create_tables() {
		global $wpdb;

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';

		$charset_collate = $wpdb->get_charset_collate();
		$employees       = self::table( 'employees' );
		$shifts          = self::table( 'shifts' );
		$attendance      = self::table( 'attendance' );
		$leaves          = self::table( 'leaves' );
		$leave_policies  = self::table( 'leave_policies' );

		$schemas = array();

		$schemas[] = "CREATE TABLE {$employees} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			wp_user_id bigint(20) unsigned DEFAULT NULL,
			employee_id varchar(50) NOT NULL,
			first_name varchar(100) NOT NULL,
			last_name varchar(100) NOT NULL,
			email varchar(255) NOT NULL,
			phone varchar(50) DEFAULT NULL,
			department varchar(100) DEFAULT NULL,
			designation varchar(100) DEFAULT NULL,
			shift_id bigint(20) unsigned DEFAULT NULL,
			employment_type varchar(20) NOT NULL DEFAULT 'full_time',
			hourly_rate decimal(10,2) DEFAULT NULL,
			monthly_salary decimal(10,2) DEFAULT NULL,
			join_date date DEFAULT NULL,
			status varchar(20) NOT NULL DEFAULT 'active',
			avatar_url varchar(500) DEFAULT NULL,
			metadata longtext DEFAULT NULL,
			created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY employee_id (employee_id),
			UNIQUE KEY email (email),
			KEY wp_user_id (wp_user_id),
			KEY shift_id (shift_id),
			KEY department (department),
			KEY status (status)
		) {$charset_collate};";

		$schemas[] = "CREATE TABLE {$shifts} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			name varchar(100) NOT NULL,
			start_time time NOT NULL,
			end_time time NOT NULL,
			grace_minutes int(11) NOT NULL DEFAULT 15,
			is_overnight tinyint(1) NOT NULL DEFAULT 0,
			working_days varchar(50) NOT NULL DEFAULT '1,2,3,4,5',
			break_minutes int(11) NOT NULL DEFAULT 60,
			status varchar(20) NOT NULL DEFAULT 'active',
			created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			KEY status (status)
		) {$charset_collate};";

		$schemas[] = "CREATE TABLE {$attendance} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			employee_id bigint(20) unsigned NOT NULL,
			date date NOT NULL,
			clock_in datetime DEFAULT NULL,
			clock_out datetime DEFAULT NULL,
			clock_in_ip varchar(45) DEFAULT NULL,
			clock_out_ip varchar(45) DEFAULT NULL,
			clock_in_location varchar(255) DEFAULT NULL,
			clock_out_location varchar(255) DEFAULT NULL,
			clock_in_note text DEFAULT NULL,
			clock_out_note text DEFAULT NULL,
			total_hours decimal(5,2) DEFAULT NULL,
			overtime_hours decimal(5,2) DEFAULT NULL,
			status varchar(20) NOT NULL DEFAULT 'present',
			late_minutes int(11) DEFAULT 0,
			early_leave_minutes int(11) DEFAULT 0,
			is_manual_entry tinyint(1) NOT NULL DEFAULT 0,
			approved_by bigint(20) unsigned DEFAULT NULL,
			created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY employee_date (employee_id, date),
			KEY employee_id (employee_id),
			KEY date (date),
			KEY status (status)
		) {$charset_collate};";

		$schemas[] = "CREATE TABLE {$leaves} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			employee_id bigint(20) unsigned NOT NULL,
			leave_type varchar(50) NOT NULL,
			start_date date NOT NULL,
			end_date date NOT NULL,
			total_days decimal(3,1) NOT NULL,
			is_half_day tinyint(1) NOT NULL DEFAULT 0,
			half_day_period varchar(20) DEFAULT NULL,
			reason text NOT NULL,
			status varchar(20) NOT NULL DEFAULT 'pending',
			reviewed_by bigint(20) unsigned DEFAULT NULL,
			reviewed_at datetime DEFAULT NULL,
			review_note text DEFAULT NULL,
			created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			KEY employee_id (employee_id),
			KEY leave_type (leave_type),
			KEY status (status),
			KEY start_date (start_date),
			KEY end_date (end_date)
		) {$charset_collate};";

		$schemas[] = "CREATE TABLE {$leave_policies} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			leave_type varchar(50) NOT NULL,
			label varchar(100) NOT NULL,
			days_per_year decimal(4,1) NOT NULL DEFAULT 0,
			carry_forward tinyint(1) NOT NULL DEFAULT 0,
			max_carry_forward_days decimal(4,1) DEFAULT 0,
			requires_approval tinyint(1) NOT NULL DEFAULT 1,
			min_notice_days int(11) NOT NULL DEFAULT 1,
			is_paid tinyint(1) NOT NULL DEFAULT 1,
			applicable_to varchar(50) NOT NULL DEFAULT 'all',
			status varchar(20) NOT NULL DEFAULT 'active',
			created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY leave_type (leave_type),
			KEY status (status)
		) {$charset_collate};";

		foreach ( $schemas as $schema ) {
			dbDelta( $schema );
		}
	}

	/**
	 * Insert the default shifts if the shifts table is empty.
	 *
	 * @return void
	 */
	public static function seed_default_shifts() {
		global $wpdb;

		$table = self::table( 'shifts' );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		if ( $count > 0 ) {
			return;
		}

		$shifts = array(
			array(
				'name'         => 'Morning Shift',
				'start_time'   => '09:00:00',
				'end_time'     => '17:00:00',
				'grace_minutes' => 15,
				'is_overnight' => 0,
				'working_days' => '1,2,3,4,5',
				'break_minutes' => 60,
			),
			array(
				'name'         => 'Evening Shift',
				'start_time'   => '14:00:00',
				'end_time'     => '22:00:00',
				'grace_minutes' => 15,
				'is_overnight' => 0,
				'working_days' => '1,2,3,4,5',
				'break_minutes' => 60,
			),
			array(
				'name'         => 'Night Shift',
				'start_time'   => '22:00:00',
				'end_time'     => '06:00:00',
				'grace_minutes' => 15,
				'is_overnight' => 1,
				'working_days' => '1,2,3,4,5',
				'break_minutes' => 60,
			),
			array(
				'name'         => 'Flexible',
				'start_time'   => '00:00:00',
				'end_time'     => '23:59:59',
				'grace_minutes' => 0,
				'is_overnight' => 0,
				'working_days' => '1,2,3,4,5,6',
				'break_minutes' => 60,
			),
		);

		foreach ( $shifts as $shift ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery
			$wpdb->insert(
				$table,
				$shift,
				array( '%s', '%s', '%s', '%d', '%d', '%s', '%d' )
			);
		}
	}

	/**
	 * Insert the default leave policies if the policies table is empty.
	 *
	 * @return void
	 */
	public static function seed_default_leave_policies() {
		global $wpdb;

		$table = self::table( 'leave_policies' );
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery
		$count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		if ( $count > 0 ) {
			return;
		}

		$policies = array(
			array(
				'leave_type'             => 'annual',
				'label'                  => 'Annual Leave',
				'days_per_year'          => 14,
				'carry_forward'          => 1,
				'max_carry_forward_days' => 5,
				'requires_approval'      => 1,
				'min_notice_days'        => 1,
				'is_paid'                => 1,
				'applicable_to'          => 'all',
			),
			array(
				'leave_type'             => 'sick',
				'label'                  => 'Sick Leave',
				'days_per_year'          => 10,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 0,
				'is_paid'                => 1,
				'applicable_to'          => 'all',
			),
			array(
				'leave_type'             => 'casual',
				'label'                  => 'Casual Leave',
				'days_per_year'          => 7,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 1,
				'is_paid'                => 1,
				'applicable_to'          => 'all',
			),
			array(
				'leave_type'             => 'unpaid',
				'label'                  => 'Unpaid Leave',
				'days_per_year'          => 30,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 1,
				'is_paid'                => 0,
				'applicable_to'          => 'all',
			),
			array(
				'leave_type'             => 'maternity',
				'label'                  => 'Maternity Leave',
				'days_per_year'          => 90,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 1,
				'is_paid'                => 1,
				'applicable_to'          => 'full_time',
			),
			array(
				'leave_type'             => 'paternity',
				'label'                  => 'Paternity Leave',
				'days_per_year'          => 7,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 1,
				'is_paid'                => 1,
				'applicable_to'          => 'full_time',
			),
			array(
				'leave_type'             => 'bereavement',
				'label'                  => 'Bereavement Leave',
				'days_per_year'          => 5,
				'carry_forward'          => 0,
				'max_carry_forward_days' => 0,
				'requires_approval'      => 1,
				'min_notice_days'        => 0,
				'is_paid'                => 1,
				'applicable_to'          => 'all',
			),
		);

		$format = array( '%s', '%s', '%f', '%d', '%f', '%d', '%d', '%d', '%s' );

		foreach ( $policies as $policy ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery
			$wpdb->insert( $table, $policy, $format );
		}
	}

	/**
	 * Register default plugin options without overwriting existing values.
	 *
	 * @return void
	 */
	public static function set_default_options() {
		$defaults = array(
			// General.
			'mkam_company_name'                  => get_bloginfo( 'name' ),
			'mkam_financial_year_start'          => 'January',
			'mkam_date_format'                   => get_option( 'date_format', 'Y-m-d' ),
			'mkam_week_start'                    => 'Monday',
			'mkam_currency'                      => '$',
			// Attendance.
			'mkam_enable_geolocation'            => 0,
			'mkam_restrict_ip'                   => 0,
			'mkam_allowed_ips'                   => '',
			'mkam_auto_clock_out'                => 1,
			'mkam_auto_clock_out_buffer'         => 60,
			'mkam_overtime_threshold'            => 30,
			'mkam_enable_clock_in_note'          => 0,
			'mkam_enable_employee_pin'           => 0,
			// Notifications.
			'mkam_notify_admin_clock_in'         => 0,
			'mkam_notify_admin_leave_request'    => 1,
			'mkam_notify_employee_leave_decision' => 1,
			'mkam_admin_email'                   => get_option( 'admin_email' ),
			'mkam_enable_weekly_digest'          => 0,
			'mkam_weekly_digest_day'             => 'Monday',
			// AI.
			'mkam_openai_api_key'                => '',
			'mkam_ai_model'                      => 'gpt-4o-mini',
			// Advanced.
			'mkam_delete_data_on_uninstall'      => 0,
			'mkam_employee_role'                 => 'subscriber',
			'mkam_items_per_page'                => 20,
		);

		foreach ( $defaults as $option => $value ) {
			if ( false === get_option( $option, false ) ) {
				add_option( $option, $value );
			}
		}
	}

	/**
	 * Schedule the plugin's WP-Cron events.
	 *
	 * @return void
	 */
	public static function schedule_events() {
		if ( ! wp_next_scheduled( 'mkam_auto_clock_out' ) ) {
			wp_schedule_event( time(), 'hourly', 'mkam_auto_clock_out' );
		}

		if ( ! wp_next_scheduled( 'mkam_daily_absent_marker' ) ) {
			wp_schedule_event( strtotime( 'tomorrow midnight' ), 'daily', 'mkam_daily_absent_marker' );
		}

		if ( ! wp_next_scheduled( 'mkam_weekly_digest' ) ) {
			wp_schedule_event( strtotime( 'next monday 9am' ), 'weekly', 'mkam_weekly_digest' );
		}

		if ( ! wp_next_scheduled( 'mkam_leave_year_reset' ) ) {
			wp_schedule_event( strtotime( 'first day of january next year' ), 'daily', 'mkam_leave_year_reset' );
		}
	}

	/**
	 * Clear all scheduled WP-Cron events.
	 *
	 * @return void
	 */
	public static function clear_events() {
		$hooks = array(
			'mkam_auto_clock_out',
			'mkam_daily_absent_marker',
			'mkam_weekly_digest',
			'mkam_leave_year_reset',
		);

		foreach ( $hooks as $hook ) {
			wp_clear_scheduled_hook( $hook );
		}
	}
}
