<?php

namespace RadiusTheme\RadiusBooking\ExportImport\Importers;

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

use RadiusTheme\RadiusBooking\ExportImport\Contracts\ImporterInterface;
use RadiusTheme\RadiusBooking\ExportImport\IdMapper;
use RadiusTheme\RadiusBooking\Models\User;
use RadiusTheme\RadiusBooking\Models\UserProfile;
use RadiusTheme\RadiusBooking\Models\EmployeeService;
use RadiusTheme\RadiusBooking\Models\EmployeeDayoff;
use RadiusTheme\RadiusBooking\Models\EmployeeWeekday;
use RadiusTheme\RadiusBooking\Models\EmployeeWeekdayTimePeriod;
use RadiusTheme\RadiusBooking\Models\EmployeeWeekdayTimePeriodService;
use RadiusTheme\RadiusBooking\Models\EmployeeWeekdayTimePeriodLocation;
use RadiusTheme\RadiusBooking\Models\EmployeeWeekdayBreakTime;
use RadiusTheme\RadiusBooking\Models\EmployeeSpecialDay;
use RadiusTheme\RadiusBooking\Models\EmployeeSpecialDayTimePeriod;
use RadiusTheme\RadiusBooking\Models\EmployeeSpecialDayTimePeriodService;
use RadiusTheme\RadiusBooking\Models\EmployeeSpecialDayTimePeriodLocation;

/**
 * Class StaffImporter
 *
 * Imports employees with all nested schedule data and full ID remapping.
 *
 * @package RadiusTheme\RadiusBooking\ExportImport\Importers
 */
class StaffImporter implements ImporterInterface {

	/**
	 * {@inheritDoc}
	 */
	public function getModuleName(): string {
		return 'staff';
	}

	/**
	 * {@inheritDoc}
	 */
	public function import( array $records, IdMapper $id_mapper ): int {
		$imported = 0;

		foreach ( $records as $record ) {
			$old_id      = (int) ( $record['id'] ?? 0 );
			$profile     = $record['profile'] ?? null;
			$services    = $record['services'] ?? array();
			$days_off    = $record['days_off'] ?? array();
			$weekdays    = $record['weekdays'] ?? array();
			$special_days = $record['special_days'] ?? array();

			unset(
				$record['id'],
				$record['profile'],
				$record['services'],
				$record['days_off'],
				$record['weekdays'],
				$record['special_days'],
				$record['created_at'],
				$record['updated_at']
			);

			// Check for duplicate email.
			$existing = User::where( 'email', $record['email'] ?? '' )->first();
			if ( $existing ) {
				$new_id = (int) $existing->id;
				if ( $old_id ) {
					$id_mapper->addMapping( 'staff', $old_id, $new_id );
				}
				++$imported;
				continue;
			}

			// Generate random password.
			$record['password'] = wp_hash_password( wp_generate_password( 16 ) );

			$user = User::create( $record );
			if ( ! $user ) {
				continue;
			}

			$new_id = (int) $user->id;
			if ( $old_id ) {
				$id_mapper->addMapping( 'staff', $old_id, $new_id );
			}

			// Profile.
			if ( $profile ) {
				$this->importProfile( $profile, $new_id );
			}

			// Employee services.
			$this->importEmployeeServices( $services, $new_id, $id_mapper );

			// Days off.
			$this->importDaysOff( $days_off, $new_id );

			// Weekdays.
			$this->importWeekdays( $weekdays, $new_id, $id_mapper );

			// Special days.
			$this->importSpecialDays( $special_days, $new_id, $id_mapper );

			++$imported;
		}

		return $imported;
	}

	/**
	 * Import user profile.
	 *
	 * @param array $profile Profile data.
	 * @param int   $user_id New user ID.
	 */
	private function importProfile( array $profile, int $user_id ): void {
		unset( $profile['created_at'], $profile['updated_at'] );
		$profile['user_id']    = $user_id;
		$profile['wp_user_id'] = null;
		$profile['image_id']   = null;
		UserProfile::create( $profile );
	}

	/**
	 * Import employee service assignments.
	 *
	 * @param array    $services  Services data.
	 * @param int      $user_id   New user ID.
	 * @param IdMapper $id_mapper ID mapper.
	 */
	private function importEmployeeServices( array $services, int $user_id, IdMapper $id_mapper ): void {
		foreach ( $services as $svc ) {
			unset( $svc['created_at'], $svc['updated_at'] );
			$svc['user_id'] = $user_id;

			// Remap service_id.
			if ( ! empty( $svc['service_id'] ) ) {
				$new_svc_id = $id_mapper->getNewId( 'service', (int) $svc['service_id'] );
				if ( $new_svc_id ) {
					$svc['service_id'] = $new_svc_id;
				}
			}

			EmployeeService::create( $svc );
		}
	}

	/**
	 * Import employee days off.
	 *
	 * @param array $days_off Days off data.
	 * @param int   $user_id  New user ID.
	 */
	private function importDaysOff( array $days_off, int $user_id ): void {
		foreach ( $days_off as $day ) {
			unset( $day['created_at'], $day['updated_at'] );
			$day['user_id'] = $user_id;
			EmployeeDayoff::create( $day );
		}
	}

	/**
	 * Import weekdays with nested time periods, break times, services, and locations.
	 *
	 * @param array    $weekdays  Weekdays data.
	 * @param int      $user_id   New user ID.
	 * @param IdMapper $id_mapper ID mapper.
	 */
	private function importWeekdays( array $weekdays, int $user_id, IdMapper $id_mapper ): void {
		foreach ( $weekdays as $wd ) {
			$time_periods = $wd['time_periods'] ?? array();
			$break_times  = $wd['break_times'] ?? array();
			unset( $wd['time_periods'], $wd['break_times'], $wd['created_at'], $wd['updated_at'] );
			$wd['user_id'] = $user_id;

			$weekday = EmployeeWeekday::create( $wd );
			if ( ! $weekday ) {
				continue;
			}

			$weekday_id = (int) $weekday->id;

			// Break times.
			foreach ( $break_times as $bt ) {
				unset( $bt['created_at'], $bt['updated_at'] );
				$bt['weekday_id'] = $weekday_id;
				EmployeeWeekdayBreakTime::create( $bt );
			}

			// Time periods.
			foreach ( $time_periods as $tp ) {
				$tp_services  = $tp['services'] ?? array();
				$tp_locations = $tp['locations'] ?? array();
				unset( $tp['services'], $tp['locations'], $tp['created_at'], $tp['updated_at'] );
				$tp['weekday_id'] = $weekday_id;

				$period = EmployeeWeekdayTimePeriod::create( $tp );
				if ( ! $period ) {
					continue;
				}

				$period_id = (int) $period->id;

				// Time period services.
				foreach ( $tp_services as $tps ) {
					unset( $tps['created_at'], $tps['updated_at'] );
					$tps['weekday_time_period_id'] = $period_id;
					if ( ! empty( $tps['service_id'] ) ) {
						$new_svc_id = $id_mapper->getNewId( 'service', (int) $tps['service_id'] );
						if ( $new_svc_id ) {
							$tps['service_id'] = $new_svc_id;
						}
					}
					EmployeeWeekdayTimePeriodService::create( $tps );
				}

				// Time period locations.
				foreach ( $tp_locations as $tpl ) {
					unset( $tpl['created_at'], $tpl['updated_at'] );
					$tpl['weekday_time_period_id'] = $period_id;
					if ( ! empty( $tpl['location_id'] ) ) {
						$new_loc_id = $id_mapper->getNewId( 'location', (int) $tpl['location_id'] );
						if ( $new_loc_id ) {
							$tpl['location_id'] = $new_loc_id;
						}
					}
					EmployeeWeekdayTimePeriodLocation::create( $tpl );
				}
			}
		}
	}

	/**
	 * Import special days with nested time periods, services, and locations.
	 *
	 * @param array    $special_days Special days data.
	 * @param int      $user_id      New user ID.
	 * @param IdMapper $id_mapper    ID mapper.
	 */
	private function importSpecialDays( array $special_days, int $user_id, IdMapper $id_mapper ): void {
		foreach ( $special_days as $sd ) {
			$time_periods = $sd['time_periods'] ?? array();
			unset( $sd['time_periods'], $sd['created_at'], $sd['updated_at'] );
			$sd['user_id'] = $user_id;

			$special_day = EmployeeSpecialDay::create( $sd );
			if ( ! $special_day ) {
				continue;
			}

			$sd_id = (int) $special_day->id;

			foreach ( $time_periods as $tp ) {
				$tp_services  = $tp['services'] ?? array();
				$tp_locations = $tp['locations'] ?? array();
				unset( $tp['services'], $tp['locations'], $tp['created_at'], $tp['updated_at'] );
				$tp['special_day_id'] = $sd_id;

				$period = EmployeeSpecialDayTimePeriod::create( $tp );
				if ( ! $period ) {
					continue;
				}

				$period_id = (int) $period->id;

				// Services.
				foreach ( $tp_services as $tps ) {
					unset( $tps['created_at'], $tps['updated_at'] );
					$tps['special_day_time_period_id'] = $period_id;
					if ( ! empty( $tps['service_id'] ) ) {
						$new_svc_id = $id_mapper->getNewId( 'service', (int) $tps['service_id'] );
						if ( $new_svc_id ) {
							$tps['service_id'] = $new_svc_id;
						}
					}
					EmployeeSpecialDayTimePeriodService::create( $tps );
				}

				// Locations.
				foreach ( $tp_locations as $tpl ) {
					unset( $tpl['created_at'], $tpl['updated_at'] );
					$tpl['special_day_time_period_id'] = $period_id;
					if ( ! empty( $tpl['location_id'] ) ) {
						$new_loc_id = $id_mapper->getNewId( 'location', (int) $tpl['location_id'] );
						if ( $new_loc_id ) {
							$tpl['location_id'] = $new_loc_id;
						}
					}
					EmployeeSpecialDayTimePeriodLocation::create( $tpl );
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public function getDependencies(): array {
		return array( 'service', 'location' );
	}
}
