<?php
/**
 * Availability Model
 *
 * @package Freelance_Studio
 */

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

class FS_Availability {

    /**
     * Get table name
     */
    private static function get_table_name() {
        global $wpdb;
        return $wpdb->prefix . 'fs_availability';
    }

    /**
     * Get weekly schedule
     */
    public static function get_weekly_schedule() {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_results(
            "SELECT * FROM $table WHERE type = 'weekly' ORDER BY day_of_week ASC, start_time ASC"
        );
    }

    /**
     * Get schedule for a specific day of week (0=Sunday, 6=Saturday)
     */
    public static function get_day_schedule($day_of_week) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table WHERE type = 'weekly' AND day_of_week = %d AND is_available = 1 ORDER BY start_time ASC",
            $day_of_week
        ));
    }

    /**
     * Get date overrides for a date range
     */
    public static function get_date_overrides($start_date, $end_date) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table WHERE type IN ('date_override', 'blocked') AND specific_date BETWEEN %s AND %s ORDER BY specific_date ASC, start_time ASC",
            $start_date,
            $end_date
        ));
    }

    /**
     * Get blocked dates
     */
    public static function get_blocked_dates($start_date, $end_date) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table WHERE type = 'blocked' AND specific_date BETWEEN %s AND %s",
            $start_date,
            $end_date
        ));
    }

    /**
     * Check if a specific date is blocked entirely
     */
    public static function is_date_blocked($date) {
        global $wpdb;
        $table = self::get_table_name();
        
        $blocked = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM $table WHERE type = 'blocked' AND specific_date = %s AND start_time IS NULL",
            $date
        ));
        
        return $blocked > 0;
    }

    /**
     * Save weekly schedule for a day
     */
    public static function save_day_schedule($day_of_week, $time_blocks) {
        global $wpdb;
        $table = self::get_table_name();
        
        // Delete existing entries for this day
        $wpdb->delete($table, array(
            'type' => 'weekly',
            'day_of_week' => $day_of_week,
        ));
        
        // Insert new time blocks
        foreach ($time_blocks as $block) {
            if (!empty($block['start_time']) && !empty($block['end_time'])) {
                $wpdb->insert($table, array(
                    'type' => 'weekly',
                    'day_of_week' => $day_of_week,
                    'start_time' => $block['start_time'],
                    'end_time' => $block['end_time'],
                    'is_available' => 1,
                ));
            }
        }
        
        return true;
    }

    /**
     * Add a date override (custom hours for a specific date)
     */
    public static function add_date_override($date, $time_blocks, $note = '') {
        global $wpdb;
        $table = self::get_table_name();
        
        // Remove any existing overrides for this date
        $wpdb->delete($table, array(
            'type' => 'date_override',
            'specific_date' => $date,
        ));
        
        // Also remove any blocks for this date
        $wpdb->delete($table, array(
            'type' => 'blocked',
            'specific_date' => $date,
        ));
        
        // Insert new time blocks
        foreach ($time_blocks as $block) {
            if (!empty($block['start_time']) && !empty($block['end_time'])) {
                $wpdb->insert($table, array(
                    'type' => 'date_override',
                    'specific_date' => $date,
                    'start_time' => $block['start_time'],
                    'end_time' => $block['end_time'],
                    'is_available' => 1,
                    'note' => $note,
                ));
            }
        }
        
        return true;
    }

    /**
     * Block a specific date entirely
     */
    public static function block_date($date, $note = '') {
        global $wpdb;
        $table = self::get_table_name();
        
        // Remove any existing entries for this date
        $wpdb->delete($table, array('specific_date' => $date));
        
        // Insert block
        $wpdb->insert($table, array(
            'type' => 'blocked',
            'specific_date' => $date,
            'is_available' => 0,
            'note' => $note,
        ));
        
        return true;
    }

    /**
     * Block a time range on a specific date
     */
    public static function block_time_range($date, $start_time, $end_time, $note = '') {
        global $wpdb;
        $table = self::get_table_name();
        
        $wpdb->insert($table, array(
            'type' => 'blocked',
            'specific_date' => $date,
            'start_time' => $start_time,
            'end_time' => $end_time,
            'is_available' => 0,
            'note' => $note,
        ));
        
        return $wpdb->insert_id;
    }

    /**
     * Remove a date override or block
     */
    public static function remove_date_entry($id) {
        global $wpdb;
        $table = self::get_table_name();
        
        return $wpdb->delete($table, array('id' => $id));
    }

    /**
     * Get available time slots for a specific date, considering meeting type settings
     */
    public static function get_available_slots($date, $meeting_type, $existing_bookings = array(), $gcal_events = array()) {
        $day_of_week = gmdate('w', strtotime($date)); // 0 = Sunday
        $slots = array();
        
        // Check if date is entirely blocked
        if (self::is_date_blocked($date)) {
            return array();
        }
        
        // Get time blocks for this date (check overrides first, then weekly schedule)
        $time_blocks = self::get_time_blocks_for_date($date, $day_of_week);
        
        if (empty($time_blocks)) {
            return array();
        }
        
        $duration = $meeting_type->duration;
        $buffer_before = $meeting_type->buffer_before;
        $buffer_after = $meeting_type->buffer_after;
        $slot_interval = 15; // Generate slots every 15 minutes
        
        // Check minimum notice
        $now = current_time('timestamp');
        $min_notice = $now + ($meeting_type->min_notice_hours * 3600);
        
        foreach ($time_blocks as $block) {
            $block_start = strtotime($date . ' ' . $block->start_time);
            $block_end = strtotime($date . ' ' . $block->end_time);
            
            // Generate slots within this block
            $slot_start = $block_start;
            
            while ($slot_start + ($duration * 60) <= $block_end) {
                $slot_end = $slot_start + ($duration * 60);
                
                // Check minimum notice
                if ($slot_start < $min_notice) {
                    $slot_start += $slot_interval * 60;
                    continue;
                }
                
                // Check for conflicts with existing bookings (including buffers)
                $conflict = false;
                $check_start = $slot_start - ($buffer_before * 60);
                $check_end = $slot_end + ($buffer_after * 60);
                
                foreach ($existing_bookings as $booking) {
                    $booking_start = strtotime($booking->start_datetime);
                    $booking_end = strtotime($booking->end_datetime);
                    
                    if ($check_start < $booking_end && $check_end > $booking_start) {
                        $conflict = true;
                        break;
                    }
                }
                
                // Check for conflicts with Google Calendar events
                if (!$conflict && !empty($gcal_events)) {
                    foreach ($gcal_events as $event) {
                        $event_start = strtotime($event['start']);
                        $event_end = strtotime($event['end']);
                        
                        if ($check_start < $event_end && $check_end > $event_start) {
                            $conflict = true;
                            break;
                        }
                    }
                }
                
                if (!$conflict) {
                    $slots[] = array(
                        'start' => gmdate('Y-m-d H:i:s', $slot_start),
                        'end' => gmdate('Y-m-d H:i:s', $slot_end),
                        'start_time' => gmdate('g:i A', $slot_start),
                        'end_time' => gmdate('g:i A', $slot_end),
                        'start_24' => gmdate('H:i', $slot_start),
                    );
                }
                
                $slot_start += $slot_interval * 60;
            }
        }
        
        return $slots;
    }

    /**
     * Get time blocks for a specific date (considers overrides)
     */
    private static function get_time_blocks_for_date($date, $day_of_week) {
        global $wpdb;
        $table = self::get_table_name();
        
        // First check for date-specific overrides
        $overrides = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table WHERE type = 'date_override' AND specific_date = %s AND is_available = 1 ORDER BY start_time ASC",
            $date
        ));
        
        if (!empty($overrides)) {
            return $overrides;
        }
        
        // Fall back to weekly schedule
        return self::get_day_schedule($day_of_week);
    }

    /**
     * Install default availability (Mon-Fri 9am-5pm)
     */
    public static function install_defaults() {
        global $wpdb;
        $table = self::get_table_name();
        
        // Check if any weekly schedule exists
        $existing = $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE type = 'weekly'");
        
        if ($existing > 0) {
            return;
        }
        
        // Default: Monday-Friday, 9am-5pm
        for ($day = 1; $day <= 5; $day++) {
            $wpdb->insert($table, array(
                'type' => 'weekly',
                'day_of_week' => $day,
                'start_time' => '09:00:00',
                'end_time' => '17:00:00',
                'is_available' => 1,
            ));
        }
    }

    /**
     * Get day names
     */
    public static function get_day_names() {
        return array(
            0 => __('Sunday', 'freelance-studio'),
            1 => __('Monday', 'freelance-studio'),
            2 => __('Tuesday', 'freelance-studio'),
            3 => __('Wednesday', 'freelance-studio'),
            4 => __('Thursday', 'freelance-studio'),
            5 => __('Friday', 'freelance-studio'),
            6 => __('Saturday', 'freelance-studio'),
        );
    }
}
