<?php
/* quotation_helpers.php */

if (!function_exists('qh')) {
    function qh($value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); }
}

if (!function_exists('quote_money')) {
    function quote_money($amount): string { return number_format((float)$amount, 2); }
}

if (!function_exists('quote_current_user_id')) {
    function quote_current_user_id(): int {
        foreach (['user_id','consultant_id','login_user_id','id'] as $key) {
            if (!empty($_SESSION[$key]) && (int)$_SESSION[$key] > 0) return (int)$_SESSION[$key];
        }
        return 0;
    }
}

if (!function_exists('quote_column_exists')) {
    function quote_column_exists(PDO $pdo, string $table, string $column): bool {
        static $cache = [];
        $key = $table.'.'.$column;
        if (array_key_exists($key, $cache)) return $cache[$key];
        try {
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :t AND COLUMN_NAME = :c");
            $stmt->execute([':t'=>$table, ':c'=>$column]);
            $cache[$key] = ((int)$stmt->fetchColumn() > 0);
        } catch (Throwable $e) { $cache[$key] = false; }
        return $cache[$key];
    }
}

if (!function_exists('next_quote_no')) {
    function next_quote_no(PDO $pdo): string {
        do {
            $no = 'QT-' . date('YmdHis') . '-' . random_int(100,999);
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM reservation_quotes WHERE quote_no = :no");
            $stmt->execute([':no'=>$no]);
        } while ((int)$stmt->fetchColumn() > 0);
        return $no;
    }
}

if (!function_exists('next_order_no_from_quote')) {
    function next_order_no_from_quote(PDO $pdo): string {
        do {
            $no = 'BK-' . date('YmdHis') . '-' . random_int(100,999);
            $stmt = $pdo->prepare("SELECT COUNT(*) FROM orders WHERE order_no = :no");
            $stmt->execute([':no'=>$no]);
        } while ((int)$stmt->fetchColumn() > 0);
        return $no;
    }
}

if (!function_exists('split_quote_guest_name')) {
    function split_quote_guest_name(string $fullName): array {
        $fullName = trim(preg_replace('/\s+/', ' ', $fullName));
        if ($fullName === '') return ['', ''];
        $parts = explode(' ', $fullName, 2);
        return [trim($parts[0] ?? ''), trim($parts[1] ?? '')];
    }
}

if (!function_exists('quote_find_or_create_guest')) {
    function quote_find_or_create_guest(PDO $pdo, string $guestName): int {
        [$first, $last] = split_quote_guest_name($guestName);
        if ($first === '' && $last === '') throw new RuntimeException('Guest name is required.');
        $stmt = $pdo->prepare("SELECT id FROM guests WHERE firstname = :f AND lastname = :l LIMIT 1");
        $stmt->execute([':f'=>$first, ':l'=>$last]);
        $id = (int)($stmt->fetchColumn() ?: 0);
        if ($id > 0) return $id;
        $stmt = $pdo->prepare("INSERT INTO guests (firstname, lastname) VALUES (:f, :l)");
        $stmt->execute([':f'=>$first, ':l'=>$last]);
        return (int)$pdo->lastInsertId();
    }
}

if (!function_exists('quote_fetch_room_types_by_property')) {
    function quote_fetch_room_types_by_property(PDO $pdo, int $propertyId): array {
        if ($propertyId <= 0) return [];
        $stmt = $pdo->prepare("SELECT id, title, COALESCE(higher_occupancy,0) AS higher_occupancy FROM room_types WHERE property_id = :pid ORDER BY title ASC");
        $stmt->execute([':pid'=>$propertyId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
    }
}

if (!function_exists('quote_fetch_room_type_meta')) {
    function quote_fetch_room_type_meta(PDO $pdo, int $roomTypeId): array {
        static $cache = [];
        if ($roomTypeId <= 0) return ['title'=>'', 'higher_occupancy'=>0];
        if (isset($cache[$roomTypeId])) return $cache[$roomTypeId];
        $stmt = $pdo->prepare("SELECT title, COALESCE(higher_occupancy,0) AS higher_occupancy FROM room_types WHERE id = :id LIMIT 1");
        $stmt->execute([':id'=>$roomTypeId]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
        return $cache[$roomTypeId] = ['title'=>(string)($row['title'] ?? ''), 'higher_occupancy'=>(int)($row['higher_occupancy'] ?? 0)];
    }
}

if (!function_exists('quote_fetch_rate_plan')) {
    function quote_fetch_rate_plan(PDO $pdo, int $roomTypeId, ?int $agentId, string $stayDate): ?array {
        if ($roomTypeId <= 0 || $stayDate === '') return null;
        if ($agentId && $agentId > 0) {
            $stmt = $pdo->prepare("SELECT * FROM room_type_rate_plans WHERE room_type_id = :rt AND status = 1 AND valid_from <= :d1 AND valid_to >= :d2 AND agent_id = :agent ORDER BY id DESC LIMIT 1");
            $stmt->execute([':rt'=>$roomTypeId, ':d1'=>$stayDate, ':d2'=>$stayDate, ':agent'=>$agentId]);
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($row) return $row;
        }
        $stmt = $pdo->prepare("SELECT * FROM room_type_rate_plans WHERE room_type_id = :rt AND status = 1 AND valid_from <= :d1 AND valid_to >= :d2 AND agent_id IS NULL ORDER BY id DESC LIMIT 1");
        $stmt->execute([':rt'=>$roomTypeId, ':d1'=>$stayDate, ':d2'=>$stayDate]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
}

if (!function_exists('quote_calculate_room_night_total')) {
    function quote_calculate_room_night_total(int $adults, int $children, float $sharingRate, float $singleRate, float $singleSupplement, float $childPercent = 50.0): array {
        $adults=max(0,$adults); $children=max(0,$children); $childPercent=max(0,$childPercent);
        if ($adults <= 0) return ['adult_total'=>0,'child_total'=>0,'room_total'=>0,'applied_rate_type'=>'empty_room','rate_label'=>'Empty'];
        if ($adults === 1) {
            $adultTotal = $singleRate > 0 ? $singleRate : ($sharingRate + $singleSupplement);
            $type = $singleRate > 0 ? 'single_rate' : 'sharing_plus_single_supplement';
            $label = $singleRate > 0 ? 'Single' : 'Sharing + Supplement';
        } else {
            $adultTotal = $adults * $sharingRate;
            $type='sharing'; $label='Sharing';
        }
        $childTotal = $children * ($sharingRate * ($childPercent / 100));
        return ['adult_total'=>round($adultTotal,2),'child_total'=>round($childTotal,2),'room_total'=>round($adultTotal+$childTotal,2),'applied_rate_type'=>$type,'rate_label'=>$label];
    }
}

if (!function_exists('quote_allocate_guests_to_rooms')) {
    function quote_allocate_guests_to_rooms(int $adults, int $children, int $totalRooms): array {
        $totalRooms=max(1,$totalRooms); $adults=max(0,$adults); $children=max(0,$children);
        $rooms=array_fill(0,$totalRooms,['adults'=>0,'children'=>0]);
        for($i=0;$i<$totalRooms && $adults>0;$i++){ $rooms[$i]['adults']++; $adults--; }
        for($i=0;$i<$totalRooms && $adults>0;$i++){ while($rooms[$i]['adults']<2 && $adults>0){$rooms[$i]['adults']++; $adults--;} }
        $i=0; while($adults>0){ $rooms[$i % $totalRooms]['adults']++; $adults--; $i++; }
        $i=0; while($children>0){ if($rooms[$i % $totalRooms]['adults']>0){$rooms[$i % $totalRooms]['children']++; $children--;} $i++; if($i>1000) break; }
        return $rooms;
    }
}

if (!function_exists('quote_normalize_room_rows')) {
    function quote_normalize_room_rows(array $rows): array {
        $clean=[];
        foreach($rows as $row){
            $rt=(int)($row['room_type_id'] ?? 0); $qty=max(1,(int)($row['qty_rooms'] ?? 1)); $ad=max(0,(int)($row['adults'] ?? 0)); $ch=max(0,(int)($row['children'] ?? 0));
            if($rt<=0 && $ad<=0 && $ch<=0) continue;
            $clean[]=['row_no'=>count($clean)+1,'room_type_id'=>$rt,'qty_rooms'=>$qty,'adults'=>$ad,'children'=>$ch];
        }
        return $clean ?: [['row_no'=>1,'room_type_id'=>0,'qty_rooms'=>1,'adults'=>1,'children'=>0]];
    }
}

if (!function_exists('quote_summarize_room_rows')) {
    function quote_summarize_room_rows(array $roomRows): array {
        $rooms=0; $ad=0; $kids=0;
        foreach($roomRows as $r){ $rooms+=max(1,(int)($r['qty_rooms']??1)); $ad+=(int)($r['adults']??0); $kids+=(int)($r['children']??0); }
        return ['totalrooms'=>$rooms,'adults'=>$ad,'kids'=>$kids,'total_pax'=>$ad+$kids];
    }
}

if (!function_exists('quote_expand_room_rows_to_slots')) {
    function quote_expand_room_rows_to_slots(array $roomRows): array {
        $slots=[];
        foreach($roomRows as $row){
            $alloc = quote_allocate_guests_to_rooms((int)$row['adults'], (int)$row['children'], max(1,(int)$row['qty_rooms']));
            foreach($alloc as $a){ $slots[]=['room_type_id'=>(int)$row['room_type_id'],'adults'=>(int)$a['adults'],'children'=>(int)$a['children']]; }
        }
        return $slots;
    }
}

if (!function_exists('quote_build_nightly_rows')) {
    function quote_build_nightly_rows(PDO $pdo, array $roomRows, ?int $agentId, string $checkIn, string $checkOut): array {
        $in=strtotime($checkIn); $out=strtotime($checkOut); $rows=[];
        if(!$in || !$out || $out <= $in) return [];
        $slots=quote_expand_room_rows_to_slots($roomRows);
        $cursor=$in;
        while($cursor < $out){
            $date=date('Y-m-d',$cursor);
            foreach($slots as $idx=>$slot){
                $plan=quote_fetch_rate_plan($pdo,(int)$slot['room_type_id'],$agentId,$date);
                $meta=quote_fetch_room_type_meta($pdo,(int)$slot['room_type_id']);
                if(!$plan){
                    $rows[]=['stay_date'=>$date,'room_no'=>$idx+1,'room_type_id'=>(int)$slot['room_type_id'],'room_type_title'=>$meta['title'],'adults_count'=>(int)$slot['adults'],'kids_count'=>(int)$slot['children'],'rate_plan_id'=>0,'rate_plan_title'=>'No rate plan','rate_plan_currency'=>'','rate_plan_season_label'=>'','rate_plan_season_color'=>'secondary','sharing_rate'=>0,'single_rate'=>0,'single_supplement'=>0,'child_rate_percent'=>50,'adult_total'=>0,'child_total'=>0,'total'=>0,'applied_rate_type'=>'missing_rate'];
                } else {
                    $calc=quote_calculate_room_night_total((int)$slot['adults'],(int)$slot['children'],(float)$plan['sharing_rate'],(float)$plan['single_rate'],(float)$plan['single_supplement'],(float)$plan['child_rate_percent']);
                    $rows[]=['stay_date'=>$date,'room_no'=>$idx+1,'room_type_id'=>(int)$slot['room_type_id'],'room_type_title'=>$meta['title'],'adults_count'=>(int)$slot['adults'],'kids_count'=>(int)$slot['children'],'rate_plan_id'=>(int)$plan['id'],'rate_plan_title'=>(string)$plan['title'],'rate_plan_currency'=>(string)($plan['currency']??''),'rate_plan_season_label'=>(string)($plan['season_label']??''),'rate_plan_season_color'=>(string)($plan['season_color']??'secondary'),'sharing_rate'=>(float)$plan['sharing_rate'],'single_rate'=>(float)$plan['single_rate'],'single_supplement'=>(float)$plan['single_supplement'],'child_rate_percent'=>(float)$plan['child_rate_percent'],'adult_total'=>$calc['adult_total'],'child_total'=>$calc['child_total'],'total'=>$calc['room_total'],'applied_rate_type'=>$calc['applied_rate_type']];
                }
            }
            $cursor=strtotime('+1 day',$cursor);
        }
        return $rows;
    }
}

if (!function_exists('quote_count_available_rooms_by_type')) {
    function quote_count_available_rooms_by_type(PDO $pdo, int $propertyId, int $roomTypeId, string $checkIn, string $checkOut): array {
        if($propertyId<=0 || $roomTypeId<=0 || $checkIn==='' || $checkOut==='') return ['total_rooms'=>0,'occupied_rooms'=>0,'available_rooms'=>0];
        $stmt=$pdo->prepare("SELECT COUNT(*) FROM rooms WHERE property_id=:p AND room_type_id=:rt");
        $stmt->execute([':p'=>$propertyId,':rt'=>$roomTypeId]);
        $total=(int)$stmt->fetchColumn();
        $stmt=$pdo->prepare("SELECT COALESCE(SUM(x.rooms_used),0) FROM (SELECT COUNT(rmg.id) rooms_used FROM order_rooming rmg INNER JOIN orders o ON o.id=rmg.order_id WHERE o.property_id=:p1 AND rmg.room_type_id=:rt1 AND COALESCE(o.status,1)<>0 AND o.check_in<:co1 AND o.check_out>:ci1 UNION ALL SELECT COALESCE(SUM(o.totalrooms),0) rooms_used FROM orders o WHERE o.property_id=:p2 AND o.room_type_id=:rt2 AND COALESCE(o.status,1)<>0 AND o.check_in<:co2 AND o.check_out>:ci2 AND NOT EXISTS (SELECT 1 FROM order_rooming r2 WHERE r2.order_id=o.id)) x");
        $stmt->execute([':p1'=>$propertyId,':rt1'=>$roomTypeId,':co1'=>$checkOut,':ci1'=>$checkIn,':p2'=>$propertyId,':rt2'=>$roomTypeId,':co2'=>$checkOut,':ci2'=>$checkIn]);
        $occ=(int)$stmt->fetchColumn();
        return ['total_rooms'=>$total,'occupied_rooms'=>$occ,'available_rooms'=>max(0,$total-$occ)];
    }
}
