<?php
declare(strict_types=1);
/**
 * fate 首頁：資料準備後交由模版 fate/templates/&lt;FATE_TEMPLATE&gt;/home.php 輸出。
 */
header('Content-Type: text/html; charset=UTF-8');

require_once __DIR__ . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'app.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_session.php';
fate_public_session_start();

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_install.php';
fate_install_maybe_redirect();

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_member_auth.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_urls.php';

$fatePublicMember = fate_public_member_current();

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_template.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_page_counter.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_store_listing.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_store_search.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_search_probe.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_seo.php';

$httpHost = $_SERVER['HTTP_HOST'] ?? '';

$frontendDb = fate_frontend_db_bootstrap();
$pdo = $frontendDb['pdo'];
$dbError = $frontendDb['dbError'];

if ($fatePublicMember !== null && $pdo instanceof PDO) {
    require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_member_profile.php';
    fate_public_member_ensure_admin_flag($pdo);
    fate_member_profile_hydrate_session($pdo, (int) $fatePublicMember['id']);
    $fatePublicMember = fate_public_member_current();
}

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_admin_nav_visibility.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_plugins.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_blog.php';
$fateAdminNavVisible = fate_admin_nav_visible_for_frontend();
$fateForumNavVisible = fate_store_forum_plugin_active();
$fateBlogNavVisible = fate_blog_nav_visible_for_frontend();
$fateBlogNavLabel = fate_blog_nav_label();
$blogHomeAnnouncements = [];
if (session_status() === PHP_SESSION_NONE) {
    fate_public_session_start();
}

/** @var list<array<string,mixed>> */
$stores = [];
$storeTotal = 0;
$storesError = null;
/** @var list<string> */
$cities = [];
$lastSyncMax = null;

$cityFilter = isset($_GET['city']) ? trim((string) $_GET['city']) : '';
if (strlen($cityFilter) > 120) {
    $cityFilter = substr($cityFilter, 0, 120);
}

$sort = isset($_GET['sort']) ? strtolower(trim((string) $_GET['sort'])) : 'rating';
if (!in_array($sort, ['rating', 'name', 'recent'], true)) {
    $sort = 'rating';
}

$page = isset($_GET['page']) ? max(1, (int) $_GET['page']) : 1;
$perPage = 24;

$storeSearchQ = fate_search_normalize_public_query(isset($_GET['q']) ? (string) $_GET['q'] : '');

$listingFilter = isset($_GET['listing']) ? fate_store_listing_normalize_tab((string) $_GET['listing']) : FATE_STORE_LISTING_FIXED;

$storeSearchMode = FATE_STORE_SEARCH_MODE_NONE;

if ($pdo instanceof PDO && $fateBlogNavVisible) {
    fate_blog_ensure_tables($pdo);
    $blogHomeAnnouncements = fate_blog_announcements_for_home($pdo);
}

if ($pdo instanceof PDO) {
    try {
        $mx = $pdo->query("SELECT MAX(synced_at) FROM spa_store_snapshots WHERE source_type = 'api'");
        $lastSyncMax = $mx ? $mx->fetchColumn() : null;
        $lastSyncMax = $lastSyncMax !== null && $lastSyncMax !== false ? (string) $lastSyncMax : null;

        $cityStmt = $pdo->query(
            "SELECT DISTINCT TRIM(city_name) AS c FROM spa_store_snapshots
             WHERE city_name IS NOT NULL AND TRIM(city_name) <> '' AND is_approved = 1
             ORDER BY c ASC LIMIT 80"
        );
        while ($cityStmt && ($r = $cityStmt->fetch(PDO::FETCH_ASSOC))) {
            $c = isset($r['c']) ? trim((string) $r['c']) : '';
            if ($c !== '') {
                $cities[] = $c;
            }
        }

        $filterConds = [];
        $filterParams = [];
        $filterConds[] = 'is_approved = 1';
        $filterConds[] = fate_store_listing_sql_condition($listingFilter);
        if ($cityFilter !== '') {
            $filterConds[] = 'city_name = :city';
            $filterParams[':city'] = $cityFilter;
        }
        if ($storeSearchQ !== '') {
            $filterCondsForSearch = $filterConds;
            $filterParamsForSearch = $filterParams;
            $searchResult = fate_store_search_list(
                $pdo,
                $filterCondsForSearch,
                $filterParamsForSearch,
                $storeSearchQ,
                $sort,
                $page,
                $perPage
            );
            $stores = $searchResult['stores'];
            $storeTotal = $searchResult['total'];
            $page = $searchResult['page'];
            $storeSearchMode = (string) $searchResult['mode'];
        } else {
            $whereClause = $filterConds !== [] ? ('WHERE ' . implode(' AND ', $filterConds)) : '';

            $countSql = 'SELECT COUNT(*) FROM spa_store_snapshots ' . $whereClause;
            $cst = $pdo->prepare($countSql);
            foreach ($filterParams as $k => $v) {
                $cst->bindValue($k, $v, PDO::PARAM_STR);
            }
            $cst->execute();
            $storeTotal = (int) $cst->fetchColumn();

            $totalPages = max(1, (int) ceil($storeTotal / $perPage));
            $page = min(max(1, $page), $totalPages);
            $offset = ($page - 1) * $perPage;

            $orderSql = match ($sort) {
                'name' => 'store_name ASC',
                'recent' => 'synced_at DESC, spa_store_id DESC',
                default => 'place_rating IS NULL, place_rating DESC, place_ratings_total DESC, store_name ASC',
            };

            $sql = "SELECT spa_store_id, store_name, display_address, city_name, district_name,
                           place_rating, place_ratings_total, cover_photo_path, photos_json,
                           public_detail_url_path, synced_at, phone, payload_json
                    FROM spa_store_snapshots " . $whereClause . '
                    ORDER BY ' . $orderSql . ' LIMIT ' . (int) $perPage . ' OFFSET ' . (int) $offset;

            $st = $pdo->prepare($sql);
            foreach ($filterParams as $k => $v) {
                $st->bindValue($k, $v, PDO::PARAM_STR);
            }
            $st->execute();
            while ($row = $st->fetch(PDO::FETCH_ASSOC)) {
                if (is_array($row)) {
                    $stores[] = $row;
                }
            }
        }
    } catch (Throwable $e) {
        $storesError = $e->getMessage();
        $stores = [];
        $storeTotal = 0;
        $cities = [];
    }
}

$totalPages = $storeTotal > 0 ? (int) ceil($storeTotal / $perPage) : 1;

require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_public_list_query.php';
$buildHomeQuery = static function (array $overrides): string {
    return fate_build_home_list_query($_GET, $overrides);
};
/** @var Closure $buildQuery 探索列表分頁／篩選（同首頁查詢，不含店家 id） */
$buildQuery = $buildHomeQuery;

$fatePageStatsKey = fate_page_stats_build_home_key($page, $cityFilter, $sort, $storeSearchQ, $listingFilter);
$fateMemberIdForLog = fate_page_stats_member_id($fatePublicMember);
require_once __DIR__ . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'fate_ui_settings.php';
$fateBrandForLogTitle = fate_public_site_branding();
$fatePageTitleForLog = $fateBrandForLogTitle['title_main'] . ' — ' . $fateBrandForLogTitle['title_sub'];
$fatePageStatsFooter = fate_page_stats_for_footer($pdo, $fatePageStatsKey, $fateMemberIdForLog, $fatePageTitleForLog);
$fatePageHitCount = $fatePageStatsFooter['fatePageHitCount'];
$fatePageStatsDbOk = $fatePageStatsFooter['fatePageStatsDbOk'];

/** @var list<array<string,mixed>> */
$weeklyTopStores = [];
$weeklyStatsRangeLabel = '';
if ($pdo instanceof PDO) {
    $ws = fate_stats_week_start_monday();
    $weeklyTopStores = fate_store_weekly_top_fetch($pdo, $ws, FATE_WEEKLY_TOP_LIMIT, $listingFilter);
    try {
        $tz = new DateTimeZone(date_default_timezone_get());
        $mon = new DateTimeImmutable($ws . ' 00:00:00', $tz);
        $sun = $mon->modify('+6 days');
        $weeklyStatsRangeLabel = $mon->format('Y/m/d') . ' — ' . $sun->format('Y/m/d');
    } catch (Throwable) {
        $weeklyStatsRangeLabel = $ws;
    }
}

$storeSearchTotal = $storeTotal;

$fateBrandForSeo = fate_public_site_branding();
$fateSeoContext = fate_seo_home_context([
    'listing' => $listingFilter,
    'city' => $cityFilter,
    'q' => $storeSearchQ,
    'page' => $page,
    'sort' => $sort,
    'storeTotal' => $storeTotal,
]);
$fatePageTitle = (string) ($fateSeoContext['title'] ?? ($fateBrandForSeo['title_main'] . ' — ' . $fateBrandForSeo['title_sub']));

fate_render_home(compact(
    'httpHost',
    'dbError',
    'stores',
    'storeTotal',
    'storesError',
    'cities',
    'lastSyncMax',
    'cityFilter',
    'sort',
    'storeSearchQ',
    'storeSearchMode',
    'page',
    'perPage',
    'totalPages',
    'buildQuery',
    'buildHomeQuery',
    'storeSearchTotal',
    'pdo',
    'fatePublicMember',
    'fatePageStatsKey',
    'fatePageHitCount',
    'fatePageStatsDbOk',
    'weeklyTopStores',
    'weeklyStatsRangeLabel',
    'fateAdminNavVisible',
    'fateForumNavVisible',
    'fateBlogNavVisible',
    'fateBlogNavLabel',
    'blogHomeAnnouncements',
    'listingFilter',
    'fateSeoContext',
    'fatePageTitle'
));
